如何让两个键同时响应?

时间:2014-06-30 14:41:36

标签: python python-2.7 pygame

我目前正在使用python进行乒乓球游戏:

enter image description here

然而,说球是粉红色的,黄色的家伙决定发送他的ws密钥。然后他的桨将开始移动(精细),但随后粉红色将停止(不是很好)。

python是否可以同时收听两个事件键?

以下是代码:

import pygame, sys
from pygame.locals import *
pygame.init()

DISPLAYSURF = pygame.display.set_mode((1439, 790))
YELLOW = (255, 255, 0)
PINK = (255, 0, 255)
BLUE = (120, 214, 208)
y1, y2 = (0, 0)
circx, circy = (1439//2, 790//2)
diffx, diffy = (15, 15)
pygame.key.set_repeat(1, 10)
while True:
        if (0 <= circy <= 780) == False:
                diffy*=-1
        if circx <= 60 and y1-10 <= circy <= y1+75:
                diffx*=-1
        if circx >= 1439-60 and y2-10 <= circy <= y2+75:
                diffx*=-1
        if (0 <= circx <= 1439) == False:
                circx, circy = (720, 395)
        DISPLAYSURF.fill((0, 0, 0))
        pygame.draw.rect(DISPLAYSURF, YELLOW, (50, y1, 10, 75))
        pygame.draw.rect(DISPLAYSURF, PINK, (1439-60, y2, 10, 75))
        pygame.draw.circle(DISPLAYSURF, BLUE, (circx, circy), 10)
        circx+=diffx
        circy+=diffy
        try:
                for event in pygame.event.get():
                        if event.type == QUIT or event.key == pygame.K_ESCAPE or event.key == pygame.K_q:
                                pygame.quit()
                                sys.exit()
                        if event.key == pygame.K_w:
                                y1-=15
                        if event.key == pygame.K_s:
                                y1+=15
                        if event.key == pygame.K_UP:
                                y2-=15
                        if event.key == pygame.K_DOWN:
                                y2+=15
        except AttributeError:
                pass
        pygame.display.flip()

如果有两个同时按键,如何让它独立处理每个按键?

5 个答案:

答案 0 :(得分:1)

我同意SilasRay的观点,这几乎肯定不是线程阻塞的问题,但如果是:这应该解决它(因此如果它没有,那么它是键盘或键盘的问题) Silas提到的SDL层)。无论如何,从你的桨中制造物体是非常重要的,所以无论如何都要考虑做那个部分。线程部分位于paddlelisten()

import threading

class Paddle(object):
    def __init__(self, posx, color):
        self.posx = posx
        self.posy = 0
        self.color = color
    @property
    def pos():
        return (self.posx, self.posy, 10, 75)

def main():
    # the logic for the program
    p1_paddle = Paddle(50, YELLOW)
    p2_paddle = Paddle(1439-60, PINK)
    def paddlelisten(paddle, upkey, downkey):
        if event.key == upkey:
            paddle.posy -= 15
        if event.key == pygame.downkey:
            paddle.posy += 15
    t1 = threading.Thread(target=lambda: paddlelisten(p1_paddle, pygame.K_w, pygame.K_s))
    t2 = threading.Thread(target=lambda: paddlelisten(p2_paddle, pygame.K_UP, pygame.K_DOWN))
    for t in [t1, t2]:
        t.daemon = True
        t.start()
    while True:
        # game loop
        pygame.draw.rect(DISPLAYSURF, p1_paddle.color, p1_paddle.pos)
        pygame.draw.rect(DISPLAYSURF, p2_paddle.color, p2_paddle.pos)

答案 1 :(得分:1)

经过一番研究,我认为这实际上是一个SDL事件队列溢出问题。 SDL是一个C事件库,PyGame的事件系统建立在它之上。根据我的阅读,事件队列有一个128事件限制,之后只需删除添加的新事件,直到刷新队列。

您的渲染逻辑效率不高,并且您已将输入轮询速率限制为渲染逻辑(您在每个游戏循环中重新渲染整个屏幕,拨片和球,然后轮询事件队列,所以你不能以比从头开始渲染整个框架更快的速度清空事件队列。我认为你需要做的是改进渲染逻辑(看看如何擦除/重绘精灵的部分而不是刷新整个缓冲区)并通过将渲染放在一个单独的线程中解除渲染事件轮询。

答案 2 :(得分:0)

我认为你需要使用线程,否则程序总是顺序的。

检查此示例:

Make 2 functions run at the same time

尝试将while True放在每个线程的函数中,以便两者都响应命令。

答案 3 :(得分:0)

正如我上面所说,我只使用了pygame.key.set_repeat(1, 10),所以即使按下按键,事件也会发生。

我发现了另一种方法,使用pygame.key.get_pressed()[pygame.DESIRED_KEY]

pygame.key.get_pressed()返回一个元组,如下所示:

(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

当按下特定键时,0变为1,使我们能够使用if pygame.key.get_pressed()[pygame.DESIRED_KEY]

以下是您编辑的代码:

import pygame, sys
from pygame.locals import *
pygame.init()

DISPLAYSURF = pygame.display.set_mode((1439, 790))
YELLOW = (255, 255, 0)
PINK = (255, 0, 255)
BLUE = (120, 214, 208)
y1, y2 = (0, 0)
circx, circy = (1439//2, 790//2)
diffx, diffy = (15, 15)
pygame.key.set_repeat(1, 10)
while True:
        if pygame.key.get_pressed()[pygame.K_UP]:
                y1-=15
        if pygame.key.get_pressed()[pygame.K_DOWN]:
                y1+=15
        if pygame.key.get_pressed()[pygame.K_w]:
                y2-=15
        if pygame.key.get_pressed()[pygame.K_s]:
                y2+=15
        if (0 <= circy <= 780) == False:
                diffy*=-1
        if circx <= 60 and y1-10 <= circy <= y1+75:
                diffx*=-1
        if circx >= 1439-60 and y2-10 <= circy <= y2+75:
                diffx*=-1
        if (0 <= circx <= 1439) == False:
                circx, circy = (720, 395)
        DISPLAYSURF.fill((0, 0, 0))
        pygame.draw.rect(DISPLAYSURF, YELLOW, (50, y1, 10, 75))
        pygame.draw.rect(DISPLAYSURF, PINK, (1439-60, y2, 10, 75))
        pygame.draw.circle(DISPLAYSURF, BLUE, (circx, circy), 10)
        circx+=diffx
        circy+=diffy
        try:
                for event in pygame.event.get():
                        if event.type == QUIT or event.key == pygame.K_ESCAPE or event.key == pygame.K_q:
                                pygame.quit()
                                sys.exit()
        except AttributeError:
                pass
        pygame.display.flip()

答案 4 :(得分:0)

在我制作的游戏中,角色可以在各个方向上移动,我这样做是为了当你按下一个键,而不是直接改变角色的sx和y时,它只会使其中一个变量moveLeft,moveRight,moveUp或moveDown(取决于按下的键)True。然后你必须制作一个单独的东西,当钥匙被抬起时将其关闭。稍后在循环中检查每个变量是否为True,并根据按下的键移动字符。另外,我不明白为什么Try循环就在那里。

您可以将主循环更改为:

p1moveup = False
p1movedown = False
p2moveup = False
p2movedown = False
while True:
    if (0 <= circy <= 780) == False:
            diffy*=-1
    if circx <= 60 and y1-10 <= circy <= y1+75:
            diffx*=-1
    if circx >= 1439-60 and y2-10 <= circy <= y2+75:
            diffx*=-1
    if (0 <= circx <= 1439) == False:
            circx, circy = (720, 395)
    DISPLAYSURF.fill((0, 0, 0))
    pygame.draw.rect(DISPLAYSURF, YELLOW, (50, y1, 10, 75))
    pygame.draw.rect(DISPLAYSURF, PINK, (1439-60, y2, 10, 75))
    pygame.draw.circle(DISPLAYSURF, BLUE, (circx, circy), 10)
    circx+=diffx
    circy+=diffy
    for event in pygame.event.get():
        if event.type == QUIT or event.key == pygame.K_ESCAPE or event.key == pygame.K_q:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                p1moveup = True
            if event.key == pygame.K_s:
                p1movedown = True
            if event.key == pygame.K_UP:
                p2moveup = True
            if event.key == pygame.K_DOWN:
                p2movedown = True
        if event.type === pygame.KEYUP:
            if event.key == pygame.K_w:
                p1moveup = False
            if event.key == pygame.K_s:
                p1movedown = False
            if event.key == pygame.K_UP:
                p2moveup = False
            if event.key == pygame.K_DOWN:
                p2movedown = False
    if p1moveup == True:
        y1-=15
    if p1movedown == True:
        y1+=15
    if p2moveup == True:
        y2-=15
    if p2movedown == True:
        y2+=15
    pygame.display.flip()