Pygame не определяет, когда клавиша нажата (используя события) - PullRequest
0 голосов
/ 01 октября 2019

Я работаю над игрой со змеями и пытаюсь заставить ее поворачиваться всякий раз, когда я нажимаю одну из клавиш со стрелками. Однако по какой-то причине pygame не обнаруживает, когда я нажимаю на них. Я пробовал только функцию move_snake в другой программе, и она отлично работала, поэтому я думаю, что что-то еще мешает ей. Я просто не могу понять, что.

Важно: я перебирал все ключи, используя keys = pygame.key.get_pressed (), перебирал ключи и метод работал. Однако это добавляло два поворота в мою программу каждый раз, когда я нажимал клавишу. Даже когда я использовал флаг, чтобы предотвратить это, он все равно делал это, поэтому мне пришлось прекратить его использовать. Если есть какой-нибудь способ заставить это прекратить это делать, я был бы рад узнать.

В любом случае, вот мой код:

import pygame
import random

pygame.init()

width = 800
height = 700

screen = pygame.display.set_mode((width, height))

snake_len = 2
snakes = []

dirx = 1
diry = 0
turning = False
run = True

turns = {}
turns1 = []

clock = pygame.time.Clock()

class Turns(object):
    def __init__(self, xdir, ydir):
        self.xdir = xdir
        self.ydir = ydir

class Body(object):
    def __init__(self, x, y, width, height, xdir, ydir):
        self.x = x
        self.y = y
        self.w = width
        self.h = height
        self.xdir = xdir
        self.ydir = ydir

def get_body(x, y, w, h, xdir, ydir):
    return Body(x, y, w, h, xdir, ydir)

def add_turn(xdir, ydir):
    return Turns(xdir, ydir)

def turn_snake(snek):
    global dirx, diry, turning

    turn = turns[0]
    snek.dirx = turns[0].xdir
    snek.diry = turns[0].ydir

    tail = get_tail()

    if snek == tail:
        turns.remove(turn)

    turning = False

def get_tail():
    if snakes:
        tail = snakes[-1]
        return tail

def add_snake():
    tail = get_tail()
    if not snakes:
        snek = get_body(400, 350, 10, 10, 1, 0)
        snakes.append(snek)
    else:
        if dirx == 1:
            snek = get_body(tail.x - tail.w, tail.y, tail.w, tail.h, snakes[0].xdir, snakes[0].ydir)
            snakes.append(snek)
        if diry == 1:
            snek = get_body(tail.x, tail.y - tail.h, tail.w, tail.h, snakes[0].xdir, snakes[0].ydir)
            snakes.append(snek)
        if dirx == -1:
            snek = get_body(tail.x + tail.w, tail.y, tail.w, tail.h, snakes[0].xdir, snakes[0].ydir)
            snakes.append(snek)
        if diry == -1:
            snek = get_body(tail.x, tail.y + tail.h, tail.w, tail.h, snakes[0].xdir, snakes[0].ydir)
            snakes.append(snek)

def draw_snake():
    screen.fill((0, 0, 0))
    for snake in snakes:
        pygame.draw.rect(screen, (95, 53, 203), (snake.x, snake.y, snake.w, snake.h))

def update_snake():
    for snake in snakes:
        if turns:
            if snake.x == turns[snakes[0].x, snakes[0].y].x and snake.y == turns[0].y:
                turn_snake(snake)
                snake.x += snake.dirx
                snake.y += snake.diry

def move_snake():
    global dirx, diry, turning

    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                turns1.append('left')
            if event.key == pygame.K_RIGHT:
                turn = add_turn(1, 0)
                turns[snakes[0].x, snakes[0].y] = turn
            if event.key == pygame.K_UP:
                turn = add_turn(0, -1)
                turns[snakes[0].x, snakes[0].y] = turn
            if event.key == pygame.K_DOWN:
                turn = add_turn(0, 1)
                turns[snakes[0].x, snakes[0].y] = turn

while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            pygame.display.quit()

    if len(snakes) < snake_len:
        add_snake()

    update_snake()
    draw_snake()
    move_snake()
    clock.tick(30)
    pygame.display.update()

Редактировать:

Видимо, использование только одного цикла событий устранило проблему в основной программе, но это все еще немного странно. Я запустил программу отладки, которая выполняла только функцию move_snake, и она прекрасно работала с двумя циклами событий.

Вот код:

import pygame

true = True
turns = []
screen = pygame.display.set_mode((700, 800))

def move_snake():
    global dirx, diry, turning
    keys = pygame.key.get_pressed()

    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                turns.append('left')
            if event.key == pygame.K_RIGHT:
                 turns.append('right')
            if event.key == pygame.K_UP:
                turns.append('up')
            if event.key == pygame.K_DOWN:
                turns.append('down')

    print(turns)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            pygame.display.quit()
    move_snake()

Это просто говорит о том, что у меня все еще нет хорошего ответа на то, что происходило в основной программе ... Если у кого-то есть идеи, ябыл бы рад узнать. Спасибо!

Ответы [ 2 ]

2 голосов
/ 01 октября 2019

У вас должен быть только один цикл

for event in pygame.event.get(): 

Второй цикл не может получить никакого события, потому что первый цикл получает все события.

Так что вам лучше использовать move_snake(event) с параметром event, но без for -loop и запускать его внутри for -loop в основном цикле:

def move_snake(event):
    global dirx, diry, turning

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            turns1.append('left')
        if event.key == pygame.K_RIGHT:
            turn = add_turn(1, 0)
            turns[snakes[0].x, snakes[0].y] = turn
        if event.key == pygame.K_UP:
            turn = add_turn(0, -1)
            turns[snakes[0].x, snakes[0].y] = turn
        if event.key == pygame.K_DOWN:
            turn = add_turn(0, 1)
            turns[snakes[0].x, snakes[0].y] = turn

while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            pygame.display.quit()
        move_snake(event) # <-- run it with every event

    if len(snakes) < snake_len:
        add_snake()

    update_snake()
    draw_snake()

    clock.tick(30)
    pygame.display.update()
1 голос
/ 01 октября 2019

Я не уверен на 100%, потому что я сам не могу проверить это прямо сейчас, но если вы исправите последнюю часть кода, как это, то это должно работать:одно событие за раз в основном цикле, и если это не событие QUIT, вы передаете его через функцию move_snake в качестве аргумента, чтобы проверить, является ли это событием KEYDOWN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...