如何在 pygame 中获得键盘输入?

我在 pygame 1.9.2中做了一个游戏。 这是一个家庭式的简单游戏,游戏中一艘船在五列坏蛋之间移动,这些坏蛋通过缓慢向下移动来进攻。我正在尝试使它,以便船左右移动与左右箭头键。这是我的代码:

keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location-=1
if location==-1:
location=0
if keys[K_RIGHT]:
location+=1
if location==5:
location=4

效果太好了。船移动得太快了。它几乎不可能只移动一个位置,左边或右边。我怎么才能做到每次按键时船只移动一次?

275396 次浏览

您可以从 pygame 获取事件,然后注意 KEYDOWN事件,而不是查看由 get_pressed()返回的键(它给出当前按下的键,而 KEYDOWN事件显示在 那个相框上按下的键)。

现在你的代码是这样的: 如果你的游戏渲染速度是30fps,你按住左箭头键半秒钟,你就是在更新位置15次。

events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
location -= 1
if event.key == pygame.K_RIGHT:
location += 1

为了在按住一个键时支持连续移动,你必须建立某种限制,要么基于游戏循环的强制最大帧速率,要么基于一个计数器,它只允许你移动循环中的每一个刻度。

move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if move_ticker == 0:
move_ticker = 10
location -= 1
if location == -1:
location = 0
if keys[K_RIGHT]:
if move_ticker == 0:
move_ticker = 10
location+=1
if location == 5:
location = 4

然后在游戏循环的某个地方,你会做这样的事情:

if move_ticker > 0:
move_ticker -= 1

这将只允许你每10帧移动一次(所以如果你移动,股票代码设置为10,并在10帧之后,它将允许你再次移动)

您应该按照 医生中的说明使用 clock.tick(10)

试试这个:

keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if count == 10:
location-=1
count=0
else:
count +=1
if location==-1:
location=0
if keys[K_RIGHT]:
if count == 10:
location+=1
count=0
else:
count +=1
if location==5:
location=4

这意味着你只有1/10的时间移动。如果它仍然快速移动,你可以尝试增加你设置的值“计数”。

import pygame
pygame.init()
pygame.display.set_mode()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); #sys.exit() if sys is imported
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_0:
print("Hey, you pressed the key, '0'!")
if event.key == pygame.K_1:
print("Doing whatever")

注意 K _ 0和 K _ 1不是唯一的键,要查看所有的键,请参阅 pygame 文档,否则,键入后按 tab

玩具。

(请注意。在 pygame 之后)变成一个空闲程序。注意 K 必须是大写。还要注意,如果您没有给 pygame 一个显示大小(不传递参数) ,那么它将自动使用计算机屏幕/显示器的大小。编程愉快!

上面所有的答案都太复杂了,我会把变量从1改为0.1 这让飞船慢了10倍 如果这个速度还是太快,就把变量改为0.01 这会让飞船慢100倍 试试这个

keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location -= 0.1 #or 0.01
if location==-1:
location=0
if keys[K_RIGHT]:
location += 0.1 #or 0.01
if location==5:
location=4

顺便说一句,如果你想确保飞船不会和

location-=1
if location==-1:
location=0

你可以更好地利用

location -= 1
location = max(0, location)

这样,如果跳过 -1,程序就不会中断

要放慢你的游戏,使用 pygame.clock.tick(10)

我想你可以用:

pygame.time.delay(delayTime)

其中 delayTime以毫秒为单位。

把它放在事件之前。

这背后的原因是 pygame 窗口的运行速度是每秒60帧(帧率) ,当你按下按键1秒钟,它就会根据事件块的循环更新60帧。

clock = pygame.time.Clock()
flag = true
while flag :
clock.tick(60)

请注意,如果您的项目中有动画,那么图像的数量将定义 tick()中的值的数量。假设你有一个角色,它需要20组图像来行走和跳跃,那么你必须让 tick(20)以正确的方式移动这个角色。

pygame.key.get_pressed() 返回一个包含每个键状态的列表。如果按住某个键,则该键的状态为 1,否则为 0。使用 pygame.key.get_pressed()评估按钮的当前状态并获得连续运动:

while True:


keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed

这段代码可以通过从“右”中减去“左”,从“下”中减去“上”来简化:

while True:


keys = pygame.key.get_pressed()
x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed

键盘事件(请参阅 Pygame.event模块)仅在键的状态更改时发生一次。每按一次键,就会发生一次 KEYDOWN事件。每释放一个密钥,就会发生一次 KEYUP。将键盘事件用于单个动作或移动:

while True:


for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x -= speed
if event.key == pygame.K_RIGHT:
x += speed
if event.key == pygame.K_UP:
y -= speed
if event.key == pygame.K_DOWN:
y += speed

参见 键和键盘事件


连续运动的最小例子: replit.com/@Rabbid76/PyGame-ContinuousMovement

import pygame


pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()


rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5


run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))


keys = pygame.key.get_pressed()
    

rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
        

rect.centerx = rect.centerx % window.get_width()
rect.centery = rect.centery % window.get_height()


window.fill(0)
pygame.draw.rect(window, (255, 0, 0), rect)
pygame.display.flip()


pygame.quit()
exit()

单个操作的最小示例: replit.com/@Rabbid76/PyGame-ShootBullet

import pygame
pygame.init()


window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()


tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))


bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []


run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False


if event.type == pygame.KEYDOWN:
bullet_list.insert(0, tank_rect.midright)


for i, bullet_pos in enumerate(bullet_list):
bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
del bullet_list[i:]
break


window.fill((224, 192, 160))
window.blit(tank_surf, tank_rect)
for bullet_pos in bullet_list:
window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
pygame.display.flip()


pygame.quit()
exit()

做出这样的东西,但基于时间延迟。我第一次立即调用函数,然后是午餐计时器,当按钮被按下时,我调用它的每一个按钮 _ press _ delta 秒

from time import time
before main loop:
button_press_delta = 0.2
right_button_pressed = 0
while not done:
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
if not right_button_pressed:
call_my_function()
right_button_pressed = 1
right_button_pressed_time_start = time()
if right_button_pressed:
right_button_pressed_time = (
time() - right_button_pressed_time_start)
if right_button_pressed_time > button_press_delta:
call_my_function()
right_button_pressed_time_start = time()
else:
right_button_pressed = 0