2013-03-27 80 views
2

我很奇怪,爲什麼是它,當我執行該文件,
箭頭控制和左矩形的運動將不會持續向上或向下移動,即使我按住上的箭頭鍵長時間。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() 

回答

4

在pygame中,輸入在事件循環中處理。有一個事件隊列,系統從鍵盤發送輸入,並通過調用pygame.event.get()獲得隊列中的第一個事件。有很多類型的活動,最流行的是KEYUPKEYDOWN。 大多數初學者所犯的錯誤是,他們認爲按下按鈕時,KEYDOWN事件會一直髮送。這是不需要的,因爲如果你按下一個按鈕,它會被按下直到你釋放它。所以你需要有一些標誌來查看按鈕是否被按下。

這樣做的最流行的方式是使用d = v*t公式。由於速度不變,我們需要引入一個方向。因此,我們的公式是這樣的:

distance_changed =方向*速度* time_change

在你的事件循環,你再改變方向:

1如果KEYDOWN-RIGHT

-1 if KEYDOWN-LEFT

0 if KEYUP-LEFTORRIGHT。

現在問題可能會彈出,爲什麼使用time_change?因爲,我們無法預測程序在哪些機器上工作,所以循環重複的次數不會被知道。 如果你拿一臺舊機器,遊戲將工作得更慢。所以我們測量上次移動所花費的時間,以便它不會在不同的機器上改變。

我已經看到你使用pygame.tick(30),它等待循環完成所花費的時間是恆定的。問題在於,當你在舊機器上運行它時。循環無法加速。

作爲一個建議,你應該把遊戲分成功能。它更可讀,並且你可以在不同的地方使用你的代碼。此外,你的事件循環,有很多ifs。使用elif是因爲如果已經按下了LEFT,沒有必要檢查是否按下了RIGTH鍵。

+1

如何簡單地使用'pygame.key.get_pressed()'? – sloth 2013-03-27 09:03:49

+0

這也可以工作,但性能呢? – 2013-03-27 09:23:43

+0

我沒有看到任何使用'pygame.key.get_pressed()'而不是檢查'KEY_UP' /'KEY_DOWN'事件和管理一堆標誌(每個鍵所針對的一個標誌)的性能縮減。 – sloth 2013-03-27 09:33:21

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事件,我可以確定哪些映射輸入處於打開狀態,哪些處於關閉狀態。

編輯:我應該提到的這種方法的一個好處是,它可以很容易地稍後更改鍵映射,甚至允許自定義鍵映射。您的遊戲邏輯只需要依賴基本輸入,如跳轉或移動輸入,並且如果鍵映射更改則無需更改。

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)