2

我想知道为什么当我执行文件
时,即使我长时间按住箭头键,左侧矩形的箭头控制和移动也不会连续向上或向下移动。

import pygame

black    = (   0,   0,   0)
white    = ( 255, 255, 255)
green    = (   0, 255,   0)
red      = ( 255,   0,   0)

pygame.init()

size = [700,500]
screen = pygame.display.set_mode(size)

fonto = pygame.font.SysFont("algerian", 100)
font = pygame.font.SysFont("algerian", 12)
text = fonto.render("Game Over", True, (0, 128, 10))

pygame.display.set_caption("Vasanths First Legit Game")

done = False
pygame.mouse.set_visible(0)

clock = pygame.time.Clock()
score = 1

rect_x = 50
rect_y = 50
rect_xp = 10
rect_yp = 10

rect_change_x = 10
rect_change_y = 10
rect_change_xp = 10
rect_change_yp = 3

while done == False:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            done=True 

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                rect_yp = rect_change_yp+rect_yp
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                rect_yp = 0+rect_yp

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                rect_yp=-3+rect_yp
            if event.key == pygame.K_RIGHT:
                rect_yp=3+rect_yp
            if event.key == pygame.K_UP:
                rect_yp=-3+rect_yp
            if event.key == pygame.K_DOWN:
                rect_yp=3+rect_yp

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                rect_yp=0+rect_yp
            if event.key == pygame.K_RIGHT:
                rect_yp=0+rect_yp
            if event.key == pygame.K_UP:
                rect_yp=0+rect_yp
            if event.key == pygame.K_DOWN:
                rect_yp=0+rect_yp

    pos = pygame.mouse.get_pos()

    x = pos[0] 
    y = pos[1] 

    screen.fill(black)

    pygame.draw.rect(screen,white,[rect_x,rect_y,10,10])
    pygame.draw.rect(screen,green,[x,490,50,10])
    pygame.draw.rect(screen,green,[10,rect_yp,10,50])
    # Move the rectangle starting point
    rect_x += rect_change_x
    rect_y += rect_change_y

    if rect_y == 0:
        rect_change_x=rect_change_x*1
        rect_change_y=rect_change_y*-1
    if rect_y == 490:
       if rect_x < x + 50 :
            scoref = font.render(score, True, (0, 128, 0))
            screen.blit(scoref,
                (20 - scoref.get_width() // 10, 20 - scoref.get_height() // 10))
            rect_change_x=rect_change_x*1
            rect_change_y=rect_change_y*-1

        if rect_x < x:
            rect_change_y = 0
            rect_change_x = 0

            #dont do this , it will go bizzonkes
            score = str(score)
            score = int(score)

    if rect_y == 490:
        if rect_x < x + 50 :
            if rect_change_x !=0:
                if rect_change_y !=0:
                    score=int(score)
                    score = score + 1
                    score=str(score)
    if rect_change_x == 0:
        if rect_change_y == 0:
                    screen.blit(text,
                        (320 - text.get_width() // 2, 240 - text.get_height() // 2))

    if rect_x == 700:
        rect_change_x = rect_change_x*-1
        rect_change_y = rect_change_y*1

    if rect_x == 0:
        rect_change_x = rect_change_x*0
        rect_change_y = rect_change_y*0

    if rect_y == 500:
        rect_change_y = 0
        rect_change_x = 0
        screen.blit(text,
            (320 - text.get_width() // 2, 240 - text.get_height() // 2))
        score=str(score)


    print(score)
    score = str(score)

    scoref = font.render(score, True, (0, 128, 0))
    screen.blit(scoref,
                (20 - scoref.get_width() // 10, 20 - scoref.get_height() // 10))

    clock.tick(30)

    pygame.display.flip()

pygame.quit ()
4

3 回答 3

4

在 pygame 中,输入在事件循环中处理。有一个事件队列,系统从键盘发送输入,通过调用pygame.event.get()你得到队列中的第一个事件。有许多类型的事件,最受欢迎的是KEYUPKEYDOWN。大多数初学者犯的错误是,他们认为当按下按钮时,会一直发送 KEYDOWN 事件。这不是必需的,因为如果你按下一个按钮,它会一直被按下直到你释放它。因此,您需要有某些标志来查看是否按下了按钮。

最流行的方法是使用d = v*t方程。由于速度是恒定的,我们需要引入一个方向。所以我们的方程看起来像这样:

distance_changed = 方向 * 速度 * time_change

然后在您的事件循环中更改方向:

1 如果 KEYDOWN-RIGHT

-1 如果 KEYDOWN-LEFT

如果 KEYUP-LEFT 或 RIGHT,则为 0。

现在可能会出现问题,为什么要使用 time_change?由于我们无法预测程序将在哪些机器上运行,因此无法知道循环重复的次数。如果您使用旧机器,则游戏运行速度会慢得多。所以我们测量最后一次运动所花费的时间,这样它就不会在不同的机器上改变。

我看到您使用 pygame.tick(30),它会等待以使循环完成所花费的时间是恒定的。当您在较旧的机器上运行它时,就会出现问题。循环无法加速。

作为建议,您应该将游戏划分为功能。它更具可读性,您可以在不同的地方使用您的代码。此外,您的事件循环有很多 ifs。使用 elif,因为如果已经按下了 LEFT,则没有必要检查是否按下了 RIGTH 键。

于 2013-03-27T08:49:55.220 回答
1

我会用pygame.key.get_pressed(),但你也忘记了pygame.key.set_repeat()。第一个参数是开始重复所需的毫秒数,第二个参数是键重复的间隔。

这是一个同时使用两者的示例:

x = 400
y = 300

import pygame, sys

bkg = (255, 211, 0)
clr = (0, 0, 0)
squ = (8, 11, 134)

pygame.init()
size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Bloxy")
pygame.key.set_repeat(1, 1)
font = pygame.font.SysFont("Stencil", 20)
clock = pygame.time.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    keys_pressed = pygame.key.get_pressed()

    if keys_pressed[pygame.K_LEFT]:
        x -= 5
    if keys_pressed[pygame.K_RIGHT]:
        x += 5
    if keys_pressed[pygame.K_UP]:
        y -= 5
    if keys_pressed[pygame.K_DOWN]:
        y += 5

    if x > 800:
        x = 0
    if x < 0:
        x = 800
    if y > 600:
        y = 0
    if y < 0:
        y = 600

    screen.fill(bkg)
    text = font.render('(' + str(x) + ',' + str(y) + ')', True, clr)
    screen.blit(text, [10, 10])
    pygame.draw.rect(screen, squ, [x - 10, y - 10, 20, 20])

    pygame.display.flip()
    clock.tick(60)
于 2014-01-29T12:39:21.887 回答
1

这就是我在自己的一个 Pygame 项目中处理它的方式:

class Inputs:

def __init__(self):
    self.bindings = {"up": pygame.K_UP,
                     "down":  pygame.K_DOWN,
                     "left":  pygame.K_LEFT,
                     "right":   pygame.K_RIGHT,
                     "lp":  pygame.K_a,
                     "mp":  pygame.K_s,
                     "hp":  pygame.K_d,
                     "lk":  pygame.K_z,
                     "mk":  pygame.K_x,
                     "hk":  pygame.K_c,
                     "pause":   pygame.K_RETURN}

    self.inputState = {"up": False,
                   "down": False,
                   "right": False,
                   "left": False,
                   "lp": False,
                   "mp": False,
                   "hp": False,
                   "lk": False,
                   "mk": False,
                   "hk": False,
                   "pause": False}

    self.buffer = InputBuffer()

def lookupBinding(self, keyEntered):
    for binding, keyBound in self.bindings.items():
        if keyEntered == keyBound:
            return binding

    return "not found"

def getInputState(self, events):
    for event in events:

        if event.type == pygame.KEYDOWN:
            binding = self.lookupBinding(event.key)
            if binding != "not found":
                newInput = Input()
                newInput.inputName = binding
                newInput.timeSinceInput = 0
                self.buffer.push(newInput)
                self.inputState[binding] = True

        if event.type == pygame.KEYUP:
            binding = self.lookupBinding(event.key)
            if binding != "not found":
                self.inputState[binding] = False

    return self.inputState

我保留了两个字典,一个是游戏中的“命令”,例如方向,到 pygame 键,然后是另一个命令到一个布尔值,表示命令的开/关状态。通过观察 KEYDOWN 和 KEYUP 事件,我可以确定哪些映射输入是打开的,哪些是关闭的。

编辑:我应该提到的这种方法的一个好处是,它可以很容易地在以后更改键映射,甚至允许自定义键映射。您的游戏逻辑只需要依赖于基本输入,例如跳跃或移动输入,并且如果键映射发生更改,则无需更改。

于 2013-04-03T16:10:04.500 回答