Smooth player movement PyGame?


Still Fresh
Jun 10, 2013
Is there a way to use smooth player movement in PyGame? The way I have it the player moves choppy.

Also, is there a way to add a way to make it so you can hold down a button? Right now I have to keep pressing D to make the character move :(

Code snippit:

clock = pygame.time.Clock()

x,y = 0, 500

dt = clock.tick(60)

speed = 1

if event.type == KEYDOWN and event.key == K_d:

    x += speed * dt

elif event.type == KEYDOWN and event.key == K_a:

    x -= speed * dt

I have an image but I don't think it's necessary to include that code. I'm new to PyGame so this might be wrong.

I'm coming from LÖVE so that's why I did the * dt thing. It might be wrong though!

Thanks! Any help is appreciated!


Jun 17, 2009
The event "KEYDOWN" will most likely fire only once at the moment you press the button down (same goes for KEYUP).

You need to save the state the button is in, I recommend creating a "controller" or "input" class, which listens for these events and provides boolean variables of the state each button is in (pressed/released).


Internal Development
Mar 11, 2003
Typically you would have a main loop - non-blocking.

You would then (either in the main loop, or another thread, or some timer thing..) poll or otherwise assume input.

If you're using events, then consider.. once you get a key down, you can wait for that key to go _up_; if it has not yet gone up, it is _still_ down.

If you're sitting and waiting for events, thats no good; a game doesn't just sit there and wait for you to wiggle the mouse or hit keys to work.. its got audio to play, animation to stpw through, etc. So your main loop should run just fine without input at all, and you just so happen to also check for input (or handle _past_ inputs.)

An obvious way to do it is to have an array (say), and store each active key-down in that:

down [ mykey ].1

Or use a bitmask:

down |= mykeymask

So have an event handler function that records what event of note happened, and adds appropriate meta ("we are movint, request is West"); then in your loop processing you apply the motion meta ("if we're trying West, add some west to our vector".

So your event receive/unreceive is one place, and your motion processing is entirely separate. Barely related.