Home > Software design >  In Python, how to make the user wait before pressing another key?
In Python, how to make the user wait before pressing another key?

Time:09-08

I'm coding a simple snake game in pygame. The thing is, if the user presses UP and LEFT (just an example) too fast, the snake will collide with itself (it will not have the time to go up before trying to go left, thus colliding with its own body and dying).

I figured it could be solved if the user had to wait a quarter of a second or so before being able to move the snake again, so the snake would always have time to go up one step before changing directions. But how do I do it?

I've already tried simply reduncing the framerate of my game, but the problem remains.

    import pygame
from pygame.locals import *
from sys import exit
from random import randint

pygame.init()

largura = 640
altura = 480
x_cobra = int(largura/2 - 20)
y_cobra = int(altura/2 - 25)
x_maca = randint(40,600)
y_maca = randint(50, 430)
pontos = 0
fonte = pygame.font.SysFont('arial', 40, True, True)
tela = pygame.display.set_mode((largura, altura))
pygame.display.set_caption('Jogo da cobrinha')
relogio = pygame.time.Clock()
lista_cobra = []
comprimento_inicial = 5
velocidade = 20
x_controle = velocidade
y_controle = 0
morreu = False

def aumenta_cobra(lista_cobra):
    for XeY in lista_cobra:
        pygame.draw.rect(tela, (0,255,0), (XeY[0],XeY[1], 20,20))

def reiniciar_jogo():
    global pontos, comprimento_inicial, x_cobra, y_cobra, lista_cobra, lista_cabeca, x_maca, y_maca, morreu
    pontos = 0
    comprimento_inicial = 5
    x_cobra = int(altuara/2)
    y_cobra = int(largura/2)
    lista_cobra = []
    lista_cabeca = []
    x_maca = randint(40,600)
    y_maca = randint(50,430)
    morreu = False

while True:
    relogio.tick(15)
    tela.fill((255,255,255))
    mensagem = f'Pontos: {pontos}'
    texto_formatado = fonte.render(mensagem, True, (0,0,0))
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()

        if event.type == KEYDOWN:
            if event.key == K_LEFT and x_controle != velocidade:
                x_controle = -velocidade
                y_controle = 0
            if event.key == K_DOWN and y_controle != -velocidade:
                x_controle = 0
                y_controle = velocidade
            if event.key == K_UP and y_controle != velocidade:
                x_controle = 0
                y_controle = -velocidade
            if event.key == K_RIGHT and x_controle != -velocidade:
                x_controle = velocidade
                y_controle = 0

    x_cobra = x_cobra   x_controle
    y_cobra = y_cobra   y_controle

    cobra = pygame.draw.rect(tela, (0,255,0), (x_cobra, y_cobra,20,20))
    maca = pygame.draw.rect(tela, (255,0,0), (x_maca, y_maca,20,20))

    if cobra.colliderect(maca):
        x_maca = randint(40, 600)
        y_maca = randint(50, 430)
        pontos  = 1
        comprimento_inicial  = 1

    lista_cabeca = []
    lista_cabeca.append(x_cobra)
    lista_cabeca.append(y_cobra)
    lista_cobra.append(lista_cabeca)

    if lista_cobra.count(lista_cabeca) > 1:
        morreu = True
        while morreu:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    exit()
                if event.type == KEYDOWN:
                    if event.key == K_r:
                        reiniciar_jogo()

    if len(lista_cobra) > comprimento_inicial:
        del lista_cobra[0]

    aumenta_cobra(lista_cobra)


    tela.blit(texto_formatado, (400, 30))
    pygame.display.update()

CodePudding user response:

Just ignore any new key press events until you have updated the model for the previous key press. You could use some kind of flag in your key press event handler that is set by the key press and reset by the logic that draws the snake. If the flag is true then do nothing.

CodePudding user response:

One way to solve this is to just only accept the first input on each movement frame. So instead of allowing the event loop to run for all inputs, it stops and returns the first valid input.

Something like this (see get_keys function):

import pygame
from pygame.locals import *
from sys import exit
from random import randint

pygame.init()

largura = 640
altura = 480
x_cobra = int(largura/2 - 20)
y_cobra = int(altura/2 - 25)
x_maca = randint(40,600)
y_maca = randint(50, 430)
pontos = 0
fonte = pygame.font.SysFont('arial', 40, True, True)
tela = pygame.display.set_mode((largura, altura))
pygame.display.set_caption('Jogo da cobrinha')
relogio = pygame.time.Clock()
lista_cobra = []
comprimento_inicial = 5
velocidade = 20
x_controle = velocidade
y_controle = 0
morreu = False

def aumenta_cobra(lista_cobra):
    for XeY in lista_cobra:
        pygame.draw.rect(tela, (0,255,0), (XeY[0],XeY[1], 20,20))

def reiniciar_jogo():
    global pontos, comprimento_inicial, x_cobra, y_cobra, lista_cobra, lista_cabeca, x_maca, y_maca, morreu
    pontos = 0
    comprimento_inicial = 5
    x_cobra = int(altuara/2)
    y_cobra = int(largura/2)
    lista_cobra = []
    lista_cabeca = []
    x_maca = randint(40,600)
    y_maca = randint(50,430)
    morreu = False

def get_keys():
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()

        if event.type == KEYDOWN:
            if event.key == K_LEFT and x_controle != velocidade:
                # x_controle = -velocidade
                # y_controle = 0
                return [-velocidade,0]
            if event.key == K_DOWN and y_controle != -velocidade:
                # x_controle = 0
                # y_controle = velocidade
                return [0, velocidade]
            if event.key == K_UP and y_controle != velocidade:
                # x_controle = 0
                # y_controle = -velocidade
                return [0, -velocidade]
            if event.key == K_RIGHT and x_controle != -velocidade:
                # x_controle = velocidade
                # y_controle = 0
                return [velocidade, 0]
    return [x_controle, y_controle] # If no valid key presses found it continues moving in the same direction.

while True:
    relogio.tick(15)
    tela.fill((255,255,255))
    mensagem = f'Pontos: {pontos}'
    texto_formatado = fonte.render(mensagem, True, (0,0,0))
    
    [x_controle, y_controle] = get_keys()

    x_cobra = x_cobra   x_controle
    y_cobra = y_cobra   y_controle

    cobra = pygame.draw.rect(tela, (0,255,0), (x_cobra, y_cobra,20,20))
    maca = pygame.draw.rect(tela, (255,0,0), (x_maca, y_maca,20,20))

    if cobra.colliderect(maca):
        x_maca = randint(40, 600)
        y_maca = randint(50, 430)
        pontos  = 1
        comprimento_inicial  = 1

    lista_cabeca = []
    lista_cabeca.append(x_cobra)
    lista_cabeca.append(y_cobra)
    lista_cobra.append(lista_cabeca)

    if lista_cobra.count(lista_cabeca) > 1:
        morreu = True
        while morreu:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    exit()
                if event.type == KEYDOWN:
                    if event.key == K_r:
                        reiniciar_jogo()

    if len(lista_cobra) > comprimento_inicial:
        del lista_cobra[0]

    aumenta_cobra(lista_cobra)


    tela.blit(texto_formatado, (400, 30))
    pygame.display.update()
  • Related