Skip to content
Advertisement

pygame – How do I change a variable while it is being used?

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.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement