0
votes

I am creating a very simple game using the pygame library in which the player moves a square around the screen with the arrow keys. Unfortunately, the response of the controls are proving to be a problem.

The controls work fine until you switch direction e.g. left to right. When the player switches direction, the square the player is controlling jars to a halt.

The code for the controls looks like this in my game:

def move(self, event):
    speed = 6
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            self.rect.x -= speed
        if event.key == pygame.K_RIGHT:
            self.rect.x += speed
        if event.key == pygame.K_DOWN:
            self.rect.y += speed
        if event.key == pygame.K_UP:
            self.rect.y -= speed

This method is located in a class called Block (I stole Block from the pygame docs) that just makes a sprite for the player alongside providing movement.

The function move() is actually called inside the main.py file like this:

while going:
    clock.tick(60)

    # event handling
    for event in pygame.event.get():
        if event.type == QUIT:
            going = False

    # controller input
    player.move(event)

Where player is an instance of the Block class and event is just an item from the event queue of my game.

I tried using the pygame.key.get_pressed function (which did work better) but I would rather use the pygame.KEYDOWN locals alternatively because it returns the key presses as events in the event queue rather than booleans returned from a list.

If you are more investigative than your average joe you can take a look at the "full" game here: https://github.com/catmes/Project_React

You will need pygame 1.9.2 and python 2.7. Keep in my mind that the game itself is more a learning exercise so don't surprised when you see bad code (that will be fixed later of course ;) ).

Thanks for stopping by and giving this question a peek, I do appreciate your time.

1

1 Answers

0
votes

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!