moving character with keys

Hi i am looking for a good explanation of how to use the arrow keys to move my character. I know enough about panda to do this but when it gets to the sefl. thing i get very confused so can someone please help me with that thanks

Look at roaming Ralph tut.

/me kicks himself for saying that

I tried looking in that it didn’t work to well. If anyone can give a detailed explanation that would be great thanks.

My audio tutorial (link in my sig) briefly goes over movement using the keyboard in lesson 5. It may clear some things up.

can someone help please

Here’s the manual page about keyboard input:
panda3d.org/manual/index.php/Keyboard_Support

In your first post it sounds like you may be confused by the information here; could you perhaps be more specific about what exactly is confusing you?

basically what i am asking is how would i make this actor move when i press the up arrow key here is a part of the code to load the actor
actor = Actor.Actor(“phase_3/models/char/dogLL_Shorts-legs-1000.bam”,{“run”:“phase_3/models/char/dogLL_Shorts-legs-run.bam”})

i know how to do all the other things accept how to make an actor move. It starts to confuse me when its is like self.accept i do not really get that.

self.accept is just there to tell the system what function to run when the particular key is pressed. You need to do your movement inside of that called function.

For example, if pressing the up arrow means your actor should move 1 unit in the Y direction, then you would use something like:

self.actor.setY(self.actor.getY()+1)

inside the function that responds to the up arrow keypress event.

Can you pm me a small part of a code that you made so i can see if im doing it right thanks.

As this topic is close to task to what I am working on I will post here and maybe both me and a.ndrew can learn at the same time.

I am having a problem blending my animations. I have a walk, run, and attack animation that I want to be able to play on the actor smoothly. I have tried a few different ideas as I have researched this problem, but to no avail. Here is my code that controls my moves:

self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, "cam-right":0} 
self.keyTimeMap = {"jump":0, "attack1":0, "attack2":0, "attack3":0, "run":0}
#regular keys down
        self.accept("arrow_left", self.setKey, ["left",1])
        self.accept("arrow_right", self.setKey, ["right",1])
        self.accept("arrow_up", self.setKey, ["forward",1])
        self.accept("arrow_down", self.setKey, ["backward",1])
        self.accept("a", self.setKey, ["cam-left",1])
        self.accept("s", self.setKey, ["cam-right",1])
        #time keys down
        self.JumpkeyMap = {"jump":0} 
        self.accept("space", self.setTimeKey, ["jump", 1])
        
        self.accept("z", self.setTimeKey, ["attack1",1])
        self.accept("x", self.setTimeKey, ["attack2",1])
        self.accept("c", self.setTimeKey, ["attack3",1])

        #regular keys up
        self.accept("arrow_left-up", self.setKey, ["left",0])
        self.accept("arrow_right-up", self.setKey, ["right",0])
        self.accept("arrow_up-up", self.setKey, ["forward",0])
        self.accept("arrow_down-up", self.setKey, ["backward",0])
        self.accept("a-up", self.setKey, ["cam-left",0])
        self.accept("s-up", self.setKey, ["cam-right",0]) 

        #time keys up
        self.accept("space-up", self.setTimeKey, ["jump",0])
        self.accept("z-up", self.setTimeKey, ["attack1",0])
        self.accept("x-up", self.setTimeKey, ["attack2",0])
        self.accept("c-up", self.setTimeKey, ["attack3",0])
        
        taskMgr.add(self.move,"moveTask") 

        # Game state variables 
        self.prevtime = 0 
        self.isMoving = False 

    # Records the state of the regular keys  
    def setKey(self, key, value): 
        self.keyMap[key] = value

    # Records the state of the time keys    
    def setTimeKey(self, key, value):  
        self.keyTimeMap[key] = value
        frame = globalClock.getFrameCount() 
        taskMgr.add(self.resetTimeKeys, "resetTimeKeys", 
                    extraArgs = [key, frame], 
                    appendTask = True) 

    #Resets the time keys
    def resetTimeKeys(self, key, frame, task): 
        if globalClock.getFrameCount() > frame:  
            self.keyTimeMap[key] = 0
            return Task.done 
        else: 
            return Task.cont 

    # Accepts arrow keys to move either the player or the menu cursor 
    def move(self, task): 

        elapsed = task.time - self.prevtime 

        # If the camera-left key or right is pressed, move camera
        base.camera.lookAt(self.player) 
        camright = base.camera.getNetTransform().getMat().getRow3(0) 
        camright.normalize() 
        if (self.keyMap["cam-left"]!=0): 
            base.camera.setPos(base.camera.getPos() - camright*(elapsed*20)) 
        if (self.keyMap["cam-right"]!=0): 
            base.camera.setPos(base.camera.getPos() + camright*(elapsed*20)) 

        # save player's initial position so that we can restore it
        startpos = self.player.getPos() 

        # If a move-key is pressed, move player 
        if (self.keyMap["left"]!=0): 
            self.player.setH(self.player.getH() + elapsed*300) 
        if (self.keyMap["right"]!=0): 
            self.player.setH(self.player.getH() - elapsed*300) 
        if (self.keyMap["forward"]!=0): 
            backward = self.player.getNetTransform().getMat().getRow3(1) 
            backward.setZ(0) 
            backward.normalize() 
            self.player.setPos(self.player.getPos() - backward*(elapsed*5)) 
        if (self.keyMap["backward"]!=0):
            backward = self.player.getNetTransform().getMat().getRow3(1)
            backward.setZ(0)
            backward.normalize()
            self.player.setPos(self.player.getPos() + backward*(elapsed*3))

        # loop/stop the 3 attack animations. 
        if (self.keyTimeMap["attack1"]!=0): 
            self.player.play("attack1") 
            self.jumpSound1.play()
         
        if (self.keyTimeMap["attack2"]!=0): 
            self.player.play("attack2") 
            self.jumpSound1.play()
            
        if (self.keyTimeMap["attack3"]!=0): 
            self.player.play("attack3") 
            self.jumpSound1.play()    

        # loop/stop the jump animation. 
        if (self.keyTimeMap["jump"]!=0): 
            self.player.play("jump") 
            self.jumpSound1.setLoopCount(1)
            self.jumpSound1.play()
            if self.isMoving is True:
                self.PlayerWalk.resume( )
                
        # loop/stop the run animation. 
        if (self.keyMap["forward"]!=0) or (self.keyMap["backward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): 
            if self.isMoving is False: 
                self.player.loop("walk") 
                self.walkSound1.play()
                self.isMoving = True 
        else: 
            if self.isMoving: 
                self.player.stop() 
                self.player.loop("idle",5) 
                self.walkSound1.stop()
                self.isMoving = False

and here is a short video of the problem I am trying to solve:

youtube.com/watch?v=kHTRWw5dGLc

Everything is working well but the blending of the animations.
As in my example above, i have tried to use a check if playerismoving, playerwalk resume, but it isnt working.

@ a.ndrew: besides the blending the animation code above works well, it is based on the roaming ralph movement code, and from birukoffs single key press code.

Any help on this would be greatly appreciated, I have been knocking my head against this problem for 8 hours now.

Ok, first off, im a complete newbie to coding for Panda, but i got a snippet of very PRIMITIVE and SIMPLE code that might help a.ndrew, which is the most basic way to move something with the keyboard i could think of.

class key(DirectObject.DirectObject):
	def __init__(self):
			
		self.accept('s-repeat', self.Move) 


	def Move(self):
		YourActor.setPos(YourActor, 0,15,0) 

x=key(); 

This is an example of a key that moves a model on the Y plane.

This is what i’ve been using for my very first test on panda, but my biggest problem is that there is somewhat of a Delay for the “repeat” to kick in, any way to reduce this?

Also, i’ve been trying to move on to using a code based on Roaming ralph (just like Metal3d) but i’ve been having a hard time completely understanding how it works (i am talking about the keyboard inputs, not the whole thing). I too would appreciate an expanded explanation on how roaming ralph works.

I wish i could be more useful.

I add one more thing to mine to eliminate the delay waiting for the repeat to kick in, as follows:


class key(DirectObject.DirectObject):
   def __init__(self):
         
      self.accept('s', self.Move)
      self.accept('s-repeat', self.Move)



   def Move(self):
      YourActor.setPos(YourActor, 0,15,0)

x=key(); 

There is no problem with multiple event handlers (The self.accept in this case) all calling the same function as a result. What this does is when the s key is first pressed, the first event handlers catches it, as it is the action for the key being pressed. This allows your program to respond immediately. Then, since you continue to hold the key down, the ‘s-repeat’ handler takes over, and continues to call the Move function.

when i try that i get this error class key(DirectObject.DirectObject):
NameError: name ‘DirectObject’ is not defined.

oh, forgot to mention, you need to import the dirctObject class, add this line to the begining of your code:

from direct.showbase import DirectObject

@Tutunkommon

I’ll try that, i tried something similar, but separated and it didn’t work, let’s see how that fares.

Thanks it worked! But is there a way that you can have an amination happen only when that actor is moving and when they stop it stops?

if pressed play

maybe i was a bit unkind, sorry…

this could help you (maybe) …

 def animation (self,task):

        

        
        if (self.walk[1]==1):
            if self.isMoving is False:
                self.model.enableBlend()
                self.model.setPlayRate(2, 'walk0')
                self.model.setControlEffect('walk0', 1)
                self.model.setControlEffect(walkBLENDS01, 0.6)
                self.model.loop('walk0')
                self.model.loop('walkBLENDS01')
                self.isMoving = True
        else:
            if self.isMoving:
                self.model.disableBlend()
                self.model.stop()
                self.model.pose("walk0",5)
                self.model.loop("idle")
                self.isMoving = False
        return task.cont
        

That didnt really help what im looking for is to make it that only when im holding down like “s” the animation will loop.

Use 3 self.accepts:

self.accept('s',startMove)
self.accept('s-repeat',Move)
self.accept('s-up',endMove)

In startMove you begin looping your animation and move your actor.

in Move you just move the actor. The animation is already looping.

in endMove you stop looping the animation.

oh now i got what you want, :unamused: or maybe not, you only want to think about and the animation start and stops??? but there you need sensor on your head (which gets the electric values, but this is a old dog), which you need to build and figure out where you have to place them :smiley: :wink: but im not sure if you find without help the right places :laughing:

anyway i dont understand what you are looking for :smiley: so good luck…
is it possible that you dont know what you want, i got this mind :wink: