Pygame Arrow Control

时间:2013-03-27 05:27:00

标签: python pygame

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

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 ()

3 个答案:

答案 0 :(得分:4)

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

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

  

distance_changed = direction * speed * time_change

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

  

1如果KEYDOWN-RIGHT

     

-1,如果KEYDOWN-LEFT

     

0,如果KEYUP-LEFTORRIGHT。

现在问题可能会出现,为什么要使用time_change?因为,我们无法预测程序将在哪台机器上工作,循环重复的次数将不知道。 如果你拿一台旧机器,游戏将会慢得多。因此,我们测量从最后一次移动所花费的时间,以便它不会在不同的机器上改变。

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

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

答案 1 :(得分: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事件,我可以确定哪些映射输入处于打开状态,哪些已关闭。

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

答案 2 :(得分: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)