I’m making a simple top-down game with moving and collision between player and walls, using pygame.
I made my code so that when keys[pygame.K_LSHIFT]
is True
during the pygame.key.get_pressed
at the state of the keyboard when it’s called, block_speed
changes to 5 instead of 3. So it works and when I hold SHIFT and move with WASD keys at the same time my speed becomes 5.
Now, the problem is when I let go of SHIFT while still moving, my speed doesn’t change back to 3 but stays at 5. But if I stop moving, then move, block_speed
changes back to 3 as expected. It seems as if any change to block_speed
only happens when I stop moving then move again.
I’m guessing it only receives the new value of block_speed
after the current copy of block_speed
is done being used.
How do I change block_speed
with SHIFT while this variable is being used by the program?
def run(self): pygame.init() pygame.display.set_caption("Platformer v1") block_speed = 3 sprite_list = pygame.sprite.Group() wall_list = pygame.sprite.Group() left_wall = Wall(0,0,10,resolution[1]) wall_list.add(left_wall) sprite_list.add(left_wall) top_wall = Wall(10,0,resolution[0]-10,10) wall_list.add(top_wall) sprite_list.add(top_wall) test_wall = Wall(10,150,200,10) wall_list.add(test_wall) sprite_list.add(test_wall) player = Player(50,50) player.walls = wall_list sprite_list.add(player) while True: self.screen.fill(black) keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == pygame.QUIT: return False if keys[pygame.K_LSHIFT]: block_speed = 5 else: block_speed = 3 if event.type == pygame.KEYDOWN: if event.key == pygame.K_d: player.change_x += block_speed elif event.key == pygame.K_a: player.change_x += -block_speed elif event.key == pygame.K_w: player.change_y += -block_speed elif event.key == pygame.K_s: player.change_y += block_speed elif event.type == pygame.KEYUP: if event.key == pygame.K_d or event.key == pygame.K_a: player.change_x = 0 elif event.key == pygame.K_w or event.key == pygame.K_s: player.change_y = 0 sprite_list.update() sprite_list.draw(self.screen) pygame.display.update() self.clock.tick(FPS)
Advertisement
Answer
Your issue is that when you add block speed to player.change_x
/change_y
, it performs that calculation at that time. Changing the variable afterwards won’t make a difference.
A simple solution for your case is to simply make the change to block_speed
happen before you use it. If you do this, block_speed
has the value you want when it comes to changing the other variables, giving you the result you want.
Edit: I realise there is another issue – that is, you only change the movement speed if the key is newly pressed (the event is fired), so changing block speed still won’t change the speed unless a direction key is pressed. The solution is to do your calculation every time, regardless.
keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == pygame.QUIT: return False if keys[pygame.K_LSHIFT]: block_speed = 5 else: block_speed = 3 if keys[pygame.K_d]: player.change_x += block_speed if keys[pygame.K_a]: player.change_x += -block_speed if keys[pygame.K_w]: player.change_y += -block_speed if keys[pygame.K_s]: player.change_y += block_speed elif event.type == pygame.KEYUP: if event.key == pygame.K_d or event.key == pygame.K_a: player.change_x = 0 elif event.key == pygame.K_w or event.key == pygame.K_s: player.change_y = 0
An alternative would be to store the direction when a key is pressed, then multiply this up by the speed at the time you do the movement each frame:
keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == pygame.QUIT: return False if keys[pygame.K_LSHIFT]: player.block_speed = 5 else: player.block_speed = 3 if event.type == pygame.KEYDOWN: if event.key == pygame.K_d: player.change_x += 1 elif event.key == pygame.K_a: player.change_x -= 1 elif event.key == pygame.K_w: player.change_y -= 1 elif event.key == pygame.K_s: player.change_y += 1 elif event.type == pygame.KEYUP: if event.key == pygame.K_d or event.key == pygame.K_a: player.change_x = 0 elif event.key == pygame.K_w or event.key == pygame.K_s: player.change_y = 0
And then in your position code, do self.rect.x += self.change_x * self.block_speed
instead. This is probably a preferable solution.