# PYGAME: When I release two directional keys together the player keep moving

I did the code this way to avoid the player to stop if a press two directional keys together making the movement more smooth. It works well but when I release two keys or more together the player keep moving in one of the directions of the key. I can't figure out how to solve this issue.

Here is my code:

def input(self, event, pygame):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.left_is_down = True
self.speed_x = -self.velocity
if event.key == pygame.K_RIGHT:
self.right_is_down = True
self.speed_x = self.velocity
if event.key == pygame.K_UP:
self.up_is_down = True
self.speed_y = -self.velocity
if event.key == pygame.K_DOWN:
self.down_is_down = True
self.speed_y = self.velocity

if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
self.left_is_down = False
if self.right_is_down:
self.speed_x = self.velocity
else:
self.speed_x = 0
if event.key == pygame.K_RIGHT:
self.right_is_down = False
if self.left_is_down:
self.speed_x = -self.velocity
else:
self.speed_x = 0
if event.key == pygame.K_UP:
self.up_is_down = False
if self.down_is_down:
self.speed_y = self.velocity
else:
self.speed_y = 0
if event.key == pygame.K_DOWN:
self.down_is_down = False
if self.up_is_down:
self.speed_y = -self.velocity
else:
self.speed_y = 0

def update(self):

self.x += self.speed_x
self.y += self.speed_y

• I'm not familiar with pygame, but this can usually be tackled by not checking if the button was just pressed down or released, but just checking the key's state. That way, you won't miss crazy situations like the keyboard being disconnected. – Peethor May 10 '16 at 18:12
• Thanks, you helped me to figure out a solution. It was realy necessary to check the key state in this case – Otavio May 12 '16 at 2:18

In pygame (and many other frameworks like it), events are received in an event queue. Multiple events can arrive per frame, for example when you press or release two buttons together. You need to consume the event queue before proceeding. Typically that looks like this:

while True:
for event in pygame.event.get():
if event == pygame.KEYDOWN:
# handle key pressed
elif event == pygame.KEYUP:
# handle key released
# handle other events
# update
# render


You haven't shown how your input() is called, but I suspect you're not looping over pygame.event.get(), which explains why some key events are missing.

But a simpler solution for your problem is to forget about key events, and simply get the state of all keys pressed, via pygame.key.get_pressed(), like in your proposed solution, but that's all you need. Leave the KEYDOWN/KEYUP events for when you need to know when a key is first pressed, or released. Then it's just:

while True:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
# Go left
if pressed[pygame.K_UP]:
# Go up
# Or handle diagonals, like pressed[pygame.K_LEFT] and pressed[pygame.K_UP]


If you remove the part bellow, maybe it can work. I do this in the JavaScript game and worked, try it:

if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
self.left_is_down = False
if self.right_is_down:
self.speed_x = self.velocity
else:
self.speed_x = 0
if event.key == pygame.K_RIGHT:
self.right_is_down = False
if self.left_is_down:
self.speed_x = -self.velocity
else:
self.speed_x = 0
if event.key == pygame.K_UP:
self.up_is_down = False
if self.down_is_down:
self.speed_y = self.velocity
else:
self.speed_y = 0
if event.key == pygame.K_DOWN:
self.down_is_down = False
if self.up_is_down:
self.speed_y = -self.velocity
else:
self.speed_y = 0


I'm a beginer in pygame and python so i'm having some troubles hahahahah.

I figured ou what my problem was. Pygame does not reognize two keys being pressed or released at the same time.

So for example, when i press the down button, and the right button the program states that self.down_is_down = True and self.right_is_down = True so the player gain a positive vertical speed and a positive horizontal speed.

But if i release two of then together pygame just recognize one being released so only one of self.down_is_down and self.right_is_down will be set False and the player will keep moving to one of the directions.

to solve this i add in the end if event.type == pygame.KEYUP block the following code:

      if not pygame.key.get_pressed()[pygame.K_LEFT] and not pygame.key.get_pressed()[pygame.K_RIGHT]:
self.speed_x = 0
self.left_is_down = False
self.right_is_down = False
if not pygame.key.get_pressed()[pygame.K_UP] and not pygame.key.get_pressed()[pygame.K_DOWN]:
self.speed_y = 0
self.down_is_down = False
self.up_is_down = False


wich checks if the keys are still being pressed. I don't think it's the better way to solve that problem but it works for now

• I'd better first detect the pressed keys, and then compute the velocity to add. after knowing such states and velocity (as a vector, perhaps) I'd assign the velocity vector to the appropriate variables – Luis Masuelli Aug 8 '16 at 21:24
• This actually not true. Pygame does recognize if keys is pressed or released simultaneously. Your solution must have fixed another problem with your code. – Ted Klein Bergman Aug 8 '16 at 21:27

I've tried out a smooth way to move around a player that works pretty well. It basically keeps track of the key presses in a list and moves the player based on the last key pressed. When you press a key it'll add a speed variable at the first position in the list, and when you release the key it'll remove that variable. In the update method you'll add the first speed variable of the list to corresponding x and y value.

import pygame
pygame.init()

screen = pygame.display.set_mode((720, 480))

class Player(pygame.sprite.Sprite):

def __init__(self):
super(Player, self).__init__()
self.rect = pygame.Rect((0, 0), (32, 32))
self.image = pygame.Surface((32, 32))
self.image.fill((255, 255, 255))
self.velocity = [0, 0]  # It's current velocity.
self.speed = 4  # The speed the player will move.
self.dx = []  # Keeps track of the horizontal movement.
self.dy = []  # Keeps track of the vertical movement.

def update(self):
try:
self.rect.x += self.dx[0]  # Index error if the list is empty.
except IndexError:
self.rect.x += 0
try:
self.rect.y += self.dy[0]  # Index error if the list is empty.
except IndexError:
self.rect.y += 0

player = Player()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise SystemExit
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
player.dx.insert(0, -player.speed)
elif event.key == pygame.K_d:
player.dx.insert(0, player.speed)
elif event.key == pygame.K_w:
player.dy.insert(0, -player.speed)
elif event.key == pygame.K_s:
player.dy.insert(0, player.speed)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.dx.remove(-player.speed)
elif event.key == pygame.K_d:
player.dx.remove(player.speed)
elif event.key == pygame.K_w:
player.dy.remove(-player.speed)
elif event.key == pygame.K_s:
player.dy.remove(player.speed)

player.update()
screen.fill((0, 0, 0))
screen.blit(player.image, player.rect)
pygame.display.update()

# print player.dx, player.dy  # Uncomment to see what's happening in action!