Shyber
Shyber

Reputation: 23

I want to prevent diagonal movement in Pygame

I'm working on making a version of the game snake and I'm trying to prevent diagonal movement. Is there a way to prevent multiple KEYDOWN events

This is my helper function that detects KEYDOWN events.

def _keydown_events(self, event):
    '''Responds to pressing keystrokes'''
    if event.type == pg.KEYDOWN:
        if event.key == pg.K_q:
            pg.display.quit()
            running = False
            sys.exit()
        elif event.key == pg.K_RIGHT:
            self.snake.move_right = True
        elif event.key == pg.K_LEFT:
            self.snake.move_left = True
        elif event.key == pg.K_UP:
            self.snake.move_up = True 
        elif event.key == pg.K_DOWN:
            self.snake.move_down = True

Upvotes: 2

Views: 676

Answers (2)

Rabbid76
Rabbid76

Reputation: 210968

You have to ensure that just self.snake.move_right, self.snake.move_left, self.snake.move_up or self.snake.move_down is set, but never 2 or more states simultaneously. e.g:

def _keydown_events(self, event):
    '''Responds to pressing keystrokes'''
    if event.type == pg.KEYDOWN:
        if event.key == pg.K_q:
            pg.display.quit()
            running = False
            sys.exit()
        elif if event.key in [pg.K_RIGHT, pg.K_LEFT, pg.K_UP, pg.K_DOWN]:
            self.snake.move_right = False
            self.snake.move_left = False
            self.snake.move_up = False
            self.snake.move_down = False
            if event.key == pg.K_RIGHT:
                self.snake.move_right = True
            elif event.key == pg.K_LEFT:
                self.snake.move_left = True
            elif event.key == pg.K_UP:
                self.snake.move_up = True
            elif event.key == pg.K_DOWN:
                self.snake.move_down = True

Anyway I recommend to remove the states self.snake.move_right, self.snake.move_left, self.snake.move_up or self.snake.move_down.
Use a single state which indicates the direction of the snake. Add a state move_dir and assign pygame.key.name(event.key). The value of move_dir becomes "right", "left", "up" respectively "down" for RIGHT, LEFT, UP or DOWN. e.g:

def _keydown_events(self, event):
    '''Responds to pressing keystrokes'''
    if event.type == pg.KEYDOWN:
        if event.key == pg.K_q:
            pg.display.quit()
            running = False
            sys.exit()

        elif if event.key in [pg.K_RIGHT, pg.K_LEFT, pg.K_UP, pg.K_DOWN]:
            # move_dir becomes "right", "left", "up" or "down"
            self.snake.move_dir = pygame.key.name(event.key)

Of course you can state the move vector directly:

def _keydown_events(self, event):
    '''Responds to pressing keystrokes'''
    if event.type == pg.KEYDOWN:
        if event.key == pg.K_q:
            pg.display.quit()
            running = False
            sys.exit()

        elif if event.key in [pg.K_RIGHT, pg.K_LEFT, pg.K_UP, pg.K_DOWN]:

            move_dirs = {pg.K_RIGHT: (1, 0), pg.K_LEFT: (-1, 0), 
                         pg.K_UP: (0, -1), pg.K_DOWN: (0, 1)}
            self.snake.move_dir = move_dirs[event.key]

Upvotes: 4

AKX
AKX

Reputation: 169012

You may want to turn your movement direction variables into a single delta value instead:

if event.key == pg.K_RIGHT:
    self.snake.move_dir = (+1, 0)
elif event.key == pg.K_LEFT:
    self.snake.move_dir = (-1, 0)
elif event.key == pg.K_UP:
    self.snake.move_dir = (0, -1)
elif event.key == pg.K_DOWN:
    self.snake.move_dir = (0, +1)

and wherever you move your snake,

dx, dy = self.move_dir
x += dx
y += dy

Upvotes: 1

Related Questions