【问题标题】:Pygame not detecting when a key is pressed (using events)Pygame 未检测到何时按下某个键(使用事件)
【发布时间】:2019-10-02 03:46:54
【问题描述】:

我正在开发一款贪吃蛇游戏,每当我按下其中一个箭头键时,我都会尝试让它转动。但是,由于某种原因,当我按下它们时,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()

这只是让我对主程序中发生的事情仍然没有一个好的答案......如果有人有任何想法,我将不胜感激。谢谢!

【问题讨论】:

  • 你应该只有一个for event in pygame.event.get()。第二个循环无法获取任何事件,因为第一个循环获取了所有事件。

标签: python pygame


【解决方案1】:

你应该只有一个循环

for event in pygame.event.get(): 

第二个循环无法获取任何事件,因为第一个循环获取所有事件。

所以你应该使用带有参数event但不带for-loop的move_snake(event),并在主循环的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()

【讨论】:

  • 我完全知道你不能做我正在做的事情,哈哈。非常感谢!
  • 实际上,我刚刚检查了仅使用 move_snake 函数运行的测试程序,它在两个事件循环中运行得非常好。我编辑了我的问题以显示这一点。你知道为什么会这样吗?谢谢。
  • 它只确认你不应该使用两个事件循环,因为有时它可以正常工作,有时它不会捕获键。你永远不知道系统会在哪个时刻发送带有按键的事件以及哪个循环会捕获它。
  • 当我运行你的新代码并显示文本而不是附加到列表时,我看到有时它会打印文本(它捕获按下的键)但在其他时候它不打印文本(它跳过按下键)。这一切都是因为有时我在程序运行第一个循环时按下键,有时在它运行第二个循环时按下键。所以这段代码的行为是不可预测的。这就是为什么你应该只使用一个事件循环。所有程序只使用一个事件循环。
  • 我明白了。那讲得通。谢谢。
【解决方案2】:

我不能 100% 确定,因为我自己现在无法检查它,但是如果你像这样修复代码的最后一部分,那么它应该可以工作:

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:
    ev=pygame.event.wait():

    if ev.type == pygame.QUIT:
        run = False
        pygame.display.quit()

    if len(snakes) < snake_len:
        add_snake()

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

基本上,您在主循环中一次解析一个事件,如果它不是 QUIT 事件,那么您将它作为参数传递给 move_snake 函数以检查它是否是 KEYDOWN 事件。

【讨论】:

  • 嗨。非常感谢您的回复。仅使用一个事件循环解决了该问题。然而,它仍然有点令人困惑,因为我只使用 move_snake 函数运行的测试程序在两个事件循环中运行得非常好。我编辑了我的问题以显示这一点。你知道为什么会这样吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
  • 1970-01-01
相关资源
最近更新 更多