Type to search…

Actor

Introduction

Awesome! You have a world, so now let’s give it an inhabitant.

Task

To make something move in a video game, you have to think about how games actually work.

Much like a flip book, a game is just a series of still pictures drawn on your screen very quickly — often 60 times every single second. Each picture is called a frame.

To make our panda spin, we can’t just tell the computer “spin the panda.” We have to give the game a repeating rule: “Every time you draw a frame, turn the panda a tiny bit more.”

In Panda3D, this repeating rule is called a Task.

python
panda.py
from direct.showbase.ShowBase import ShowBase

app = ShowBase()

# --- THE SCENERY ---
scene = app.loader.loadModel("models/environment")
scene.reparentTo(app.render)
scene.setScale(0.25)
scene.setPos(0, 60, 0)

# --- THE PANDA ---
# 1. Load the panda model and put it on the stage
panda = app.loader.loadModel("models/panda-model")
panda.reparentTo(app.render)

# 2. Shrink it down (the built-in panda is HUGE!)
panda.setScale(0.005)
panda.setPos(0, 20, 0)


# --- THE ANIMATION ---
# 3. Create a rule for spinning
def spin_panda(task):
    # Calculate a new angle based on the game's built-in stopwatch
    angle = task.time * 50.0

    # Set the panda's rotation
    panda.setHpr(angle, 0, 0)

    # Tell the engine to keep repeating this rule
    return task.cont


# 4. Give the rule to the game's "Task Manager"
app.taskMgr.add(spin_panda, "SpinPandaTask")

app.run()

FAQ’S

In Windows 10/11 you may need these lines of code before creating the app:

python
# Importacions
from panda3d.core import loadPrcFileData

# Codi font abans de crear la pantalla (ShowBase)
loadPrcFileData("", "load-display pandadx9")
loadPrcFileData("", "win-size 800 600")

Breaking Down the Magic

Run that in your terminal and you should see a giant panda spinning happily in front of your scenery! Here is exactly what is happening in the new code:

  • def spin_panda(task): The word def is Python’s way of saying “I am defining a new rule.” We named this rule spin_panda.

  • angle = task.time * 50.0. Every Task has a built-in stopwatch (task.time) that tracks how many seconds the game has been running. By multiplying the time by 50, we create a number that constantly grows larger as the seconds tick by. We store that growing number in a container we named angle.

  • panda.setHpr(angle, 0, 0). This is how things rotate in 3D space. HPR stands for Heading, Pitch, and Roll:

    • Heading: Turning left and right (like shaking your head “no”).
    • Pitch: Tilting forward and backward (like nodding your head “yes”).
    • Roll: Tilting side-to-side (like doing a cartwheel).

    Because we put our constantly growing angle number into the Heading slot, the panda continuously turns left!

  • return task.cont. This translates to “Task Continue.” It tells the game engine, “Once you finish this rule, don’t stop. Do it again on the next frame.”

  • app.taskMgr.add(spin_panda, "SpinPandaTask"). Writing the rule isn’t enough; we have to hire someone to enforce it. The “Task Manager” is your backstage crew chief. This line hands the rule over to the crew chief so it actually starts running.

The Python class Actor is designed to hold an animatable model and a set of animations.


Actor

Let’s bring our panda to life!

Right now, the panda we loaded is just a static 3D model. You can think of a standard model like a statue—it looks nice, but its joints are frozen solid. To make the legs bend and the arms swing, game developers use a technique called “skeletal animation” or “rigging,” which puts an invisible skeleton inside the model.

In Panda3D, to use a model that has a moving skeleton, we can’t use the standard loadModel command anymore. Instead, we need a special blueprint called an Actor.

Since the Actor class inherits from NodePath, everything that can be done to a NodePath, such as reparentTo() and setPos(), etc., may also be done to an Actor.

In addition to the basic NodePath functionality, Actors have several additional methods to control animation. In order for Actors to animate, their pointer (variable) must be retained in memory.

https://docs.panda3d.org/1.10/python/programming/models-and-actors/actor-animations

Here is the updated code.

python
panda_walk.py
from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor

app = ShowBase()

# --- THE SCENERY ---
scene = app.loader.loadModel("models/environment")
scene.reparentTo(app.render)
scene.setScale(0.25, 0.25, 0.25)
scene.setPos(0, 60, 0)

# --- THE PANDA ---
# 1. Load the panda as an "Actor" and give it its animation files
panda = Actor("models/panda-model",
              {"walk": "models/panda-walk4"})

# 2. Put it on the stage and adjust size/position
panda.reparentTo(app.render)
panda.setScale(0.005)
panda.setPos(0, 20, 0)

# 3. Tell the panda to constantly repeat its walk animation
panda.loop("walk")

# --- THE SPINNING RULE ---
def spin_panda(task):
    angle = task.time * 50.0
    panda.setHpr(angle, 0, 0)
    return task.cont

app.taskMgr.add(spin_panda, "SpinPandaTask")

app.run()

What Changed?

If you run this, you will now see the panda continuously walking in a circle!

Here is the breakdown of the new pieces:

  • from direct.actor.Actor import Actor. Just like we did with the ShowBase blueprint, we are going back into the Panda3D library to grab a new blueprint called Actor. This tells Python how to handle moving skeletons.

  • panda = Actor("models/panda-model", {"walk": "models/panda-walk4"}). This is the most important change. We are combining two different files to create our character:

    • "models/panda-model" is the physical body of the panda (the fur, the shape).
    • "models/panda-walk4" is a hidden file in Panda3D that contains just the math for how a panda’s skeleton should step and sway.
    • By pairing them up, we are saying: “Here is your body, and here is a movement called ‘walk’. Memorize this movement!”
  • panda.loop("walk"). This tells the Actor to play the “walk” movement we just taught it, and when it reaches the end of the animation, loop back to the beginning and do it again forever.

Because we left our spin_panda task in the code, the game is spinning the entire panda at the exact same time the panda is moving its legs.


Events

Taking control of a character is where a program truly starts to feel like a game.

To make this happen, we have to teach our game two fundamental programming concepts: Events (listening for you to press a key) and Logic (deciding what to do based on those key presses).

Here is the updated code.

Notice that we completely removed the old spin_panda task and replaced it with a new keyboard setup and a move_panda task.

python
panda_move.py
from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor

app = ShowBase()

# --- THE SCENERY ---
scene = app.loader.loadModel("models/environment")
scene.reparentTo(app.render)
scene.setScale(0.25)
scene.setPos(0, 60, 0)

# --- THE PANDA ---
panda = Actor("models/panda-model", {"walk": "models/panda-walk4"})
panda.reparentTo(app.render)
panda.setScale(0.005)
panda.setPos(0, 20, 0)
panda.loop("walk")

# --- KEYBOARD CONTROLS ---
# 1. Create a "cheat sheet" to track which keys are currently held down
keys = {"turn_left": False, "turn_right": False, "walk_forward": False}


# 2. A rule to update our cheat sheet
def update_key(key_name, is_pressed):
    keys[key_name] = is_pressed


# 3. Tell the game engine to listen for specific keyboard events
app.accept("arrow_left", update_key, ["turn_left", True])
app.accept("arrow_left-up", update_key, ["turn_left", False])

app.accept("arrow_right", update_key, ["turn_right", True])
app.accept("arrow_right-up", update_key, ["turn_right", False])

app.accept("arrow_up", update_key, ["walk_forward", True])
app.accept("arrow_up-up", update_key, ["walk_forward", False])


# --- THE MOVEMENT RULE ---
def move_panda(task):
    # Turn left or right
    if keys["turn_left"]:
        panda.setH(panda.getH() + 2)
    if keys["turn_right"]:
        panda.setH(panda.getH() - 2)

    # Walk forward
    if keys["walk_forward"]:
        # Move the panda forward relative to the direction it is facing
        panda.setY(panda, -4)

    return task.cont


app.taskMgr.add(move_panda, "MovePandaTask")

app.run()

You're reading a preview.

Sign in with Google to read the full page. A Google account includes 5 free pages in total; students and teachers read their course pages without limit.

Sign in