2017-09-28 57 views
1

我目前遇到pygame中的按鈕有問題。目前我正在用pygame測試自己,我正在嘗試創建一種飛揚的鳥類遊戲。我試圖實現的是,當我點擊主菜單上的播放按鈕時,它將更改按鈕精靈並運行主遊戲。如何在pygame中點擊時創建一個更改精靈的按鈕?

我已經設法定義了按鈕功能,並讓我點擊時切換到主遊戲。唯一的問題是點擊時它不會顯示不同的精靈,我可以在應用程序的任何地方點擊以切換到主遊戲,而不必點擊按鈕。

任何幫助將不勝感激。

由於提前

import time 
 
import random 
 

 
import pygame 
 
from pygame.locals import * 
 

 
pygame.init() 
 

 
#Predefined Colors 
 
white = (255,255,255) 
 
black = (0,0,0) 
 

 
red = (200,0,0) 
 
light_red = (255,0,0) 
 

 
yellow = (200,200,0) 
 
light_yellow = (255,255,0) 
 

 
green = (34,177,76) 
 
light_green = (0,255,0) 
 

 
blue = (0,0,255) 
 
light_blue = (0, 0, 200) 
 

 
player_list = (
 
    # Red Bird 
 
    ('assets/sprites/redbird-upflap.png', 'assets/sprites/redbird-midflap.png', 
 
    'assets/sprites/redbird-downflap.png'), 
 

 
    # Blue Bird 
 
    ('assets/sprites/bluebird-upflap.png', 'assets/sprites/bluebird-midflap.png', 
 
    'assets/sprites/bluebird-downflap.png'), 
 

 
    # Yellow Bird 
 
    ('assets/sprites/yellowbird-upflap.png', 'assets/sprites/yellowbird-midflap.png', 
 
    'assets/sprites/yellowbird-downflap.png') 
 
) 
 

 
background_list = (
 
    ('assets/sprites/background-day.png', 'assets/sprites/background-night.png') 
 
) 
 

 
pipe_list = (
 
    ('assets/sprites/pipe-green.png', 'assets/sprites/pipe-red.png') 
 
) 
 

 
FPS = 30 
 

 
images, sounds = {}, {} 
 

 
def main(): 
 
    global base_x, base_y, clock, gameDisplay, display_height, display_width 
 
    display_width = 288 
 
    display_height = 512 
 

 
    base_x = 0 
 
    base_y = display_height * 0.79 
 

 
    clock = pygame.time.Clock() 
 
    gameDisplay = pygame.display.set_mode((display_width, display_height)) 
 

 
    pygame.display.set_caption("Flappy Bird") 
 

 
    #Loading icon sprite 
 
    images['Icon'] = pygame.image.load('assets/sprites/yellowbird-midflap.png') 
 
    pygame.display.set_icon(images['Icon']) 
 

 
    #Loading all the Numbers sprites 
 
    images['Numbers'] = (
 
     pygame.image.load('assets/sprites/0.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/1.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/2.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/3.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/4.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/5.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/6.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/7.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/8.png').convert_alpha(), 
 
     pygame.image.load('assets/sprites/9.png').convert_alpha() 
 
    ) 
 

 
    #Game Over Sprite 
 
    images['Game Over'] = pygame.image.load('assets/sprites/gameover.png').convert_alpha() 
 
    #Starting Game sprite 
 
    images['Starting Game'] = pygame.image.load('assets/sprites/startgame-screen.png').convert_alpha() 
 
    #Flappy Bird Logo sprite 
 
    images['Flappy Bird Logo'] = pygame.image.load('assets/sprites/flappybird-logo.png').convert_alpha() 
 
    #Base Ground sprite 
 
    images['Base Ground'] = pygame.image.load('assets/sprites/base.png').convert_alpha() 
 
    #Play Button Up sprite 
 
    images['Play Button Up'] = pygame.image.load('assets/sprites/playbutton-up.png').convert_alpha() 
 
    #Play Button Down sprite 
 
    images['Play Button Down'] = pygame.image.load('assets/sprites/playbutton-down.png').convert_alpha() 
 
    #Quit Button Up sprite 
 
    #images['Quit Button Up'] = pygame.image.load('assets/sprites/quitbutton-up.png').convert_alpha() 
 
    #Quit Button Down sprite 
 
    #images['Quit Button Down'] = pygame.image.load('assets/sprites/quitbutton-down.png').convert_alpha() 
 

 
    #Sounds 
 
    # sounds['Die'] = pygame.mixer.Sound('assets/audio/die.wav') 
 
    # sounds['Hit'] = pygame.mixer.Sound('assets/audio/hit.wav') 
 
    # sounds['Point'] = pygame.mixer.Sound('assets/audio/point.wav') 
 
    # sounds['swoosh'] = pygame.mixer.Sound('assets/audio/swoosh.wav') 
 
    # sounds['wing'] = pygame.mixer.Sound('assets/audio/wing.wav') 
 

 
    while True: 
 
     #Select random Background sprites 
 
     random_background = random.randint(0, len(background_list) - 1) 
 
     images['Background'] = pygame.image.load(background_list[random_background]).convert() 
 

 
     #Select random Player sprites 
 
     random_player = random.randint(0, len(player_list) - 1) 
 
     images['Player'] = (
 
      pygame.image.load(player_list[random_player][0]).convert_alpha(), 
 
      pygame.image.load(player_list[random_player][1]).convert_alpha(), 
 
      pygame.image.load(player_list[random_player][2]).convert_alpha() 
 
     ) 
 

 
     #Select random Pipe sprite 
 
     random_pipe = random.randint(0, len(pipe_list) - 1) 
 
     images['Pipe'] = pygame.image.load(pipe_list[random_pipe]) 
 

 
     main_menu() 
 

 
    pygame.display.update() 
 
    clock.tick(FPS) 
 

 
def button(action = None): 
 
    cur = pygame.mouse.get_pos() 
 
    click = pygame.mouse.get_pressed() 
 

 
    if action == 'Play': 
 
     button = images['Play Button Up'].get_rect() 
 

 
     for event in pygame.event.get(): 
 
      if click[0] == 1: 
 
       if button.collidepoint(cur): 
 
        print ('Mouse Over') 
 
        images['Play Button Down'] 
 
        main_game() 
 

 
    else: 
 
     gameDisplay.blit(images['Play Button Up'], (0, -10)) 
 

 

 

 

 
def main_menu(): 
 
    global player_index, player_x, player_y 
 
    player_index = 0 
 

 
    player_x = int(display_width * 0.2) 
 
    player_y = int((display_height - images['Player']  [0].get_height())/2) 
 

 
    menu = True 
 

 
    while menu: 
 

 
     for event in pygame.event.get(): 
 
      if event.type == pygame.QUIT: 
 
       pygame.quit() 
 
       quit() 
 

 
     gameDisplay.blit(images['Background'], (0, 0)) 
 
     gameDisplay.blit(images['Base Ground'], (base_x, base_y)) 
 
     gameDisplay.blit(images['Flappy Bird Logo'], (50, -30)) 
 
     gameDisplay.blit(images['Player'][player_index], (125, 140)) 
 
     gameDisplay.blit(images['Play Button Up'], (10, 10)) 
 

 
     button(action = 'Play') 
 

 
     pygame.display.update() 
 
     clock.tick(FPS) 
 

 
def main_game(): 
 
    gameExit = False 
 
    gameOver = False 
 

 
    player_x = 0 
 
    player_y = 0 
 

 
    while not gameExit: 
 

 
     if gameOver == True: 
 
      gameDisplay.blit(images['Game Over'], 50, 50) 
 
      pygame.display.update() 
 

 
     for event in pygame.event.get(): 
 
      if event.type == pygame.QUIT: 
 
       pygame.quit() 
 
       quit() 
 

 

 

 
     gameDisplay.blit(images['Background'], (0, 0)) 
 
     gameDisplay.blit(images['Starting Game'], (0, 0)) 
 
     gameDisplay.blit(images['Base Ground'], (base_x, base_y)) 
 
     gameDisplay.blit(images['Player'][player_index], (player_x, player_y)) 
 

 
     pygame.display.update() 
 
     clock.tick(FPS) 
 

 

 
main()

+0

你已經知道如何面向對象編程的作品?另外,在您提交之前,請務必將您的代碼減少到[最小值](https://stackoverflow.com/help/mcve),但請確保它仍然完整且可運行。 – skrx

回答

0

這裏有一個小例子來說明如何能夠在不同的按鈕圖像之間進行切換。

當用戶按下鼠標按鈕(pygame.MOUSEBUTTONDOWN事件被添加到隊列中)時,檢查event.pos是否與按鈕rect衝突,如果碰撞,將圖像設置爲「向下」版本。

當用戶釋放按鈕(pygame.MOUSEBUTTONUP事件)時,只需將圖像設置回原始版本即可。

import pygame as pg 


pg.init() 
screen = pg.display.set_mode((640, 480)) 

GRAY = pg.Color('gray15') 
BLUE = pg.Color('dodgerblue1') 
LIGHTBLUE = pg.Color('lightskyblue1') 

BUTTON_UP_IMG = pg.Surface((50, 30)) 
BUTTON_UP_IMG.fill(BLUE) 
BUTTON_DOWN_IMG = pg.Surface((50, 30)) 
BUTTON_DOWN_IMG.fill(LIGHTBLUE) 


def main(): 
    clock = pg.time.Clock() 
    font = pg.font.Font(None, 30) 

    # Currently selected button image. 
    button_image = BUTTON_UP_IMG 
    button_rect = button_image.get_rect(topleft=(200, 200)) 
    x = 0 

    done = False 

    while not done: 
     for event in pg.event.get(): 
      if event.type == pg.QUIT: 
       done = True 
      if event.type == pg.MOUSEBUTTONDOWN: 
       if event.button == 1: 
        if button_rect.collidepoint(event.pos): 
         button_image = BUTTON_DOWN_IMG 
      elif event.type == pg.MOUSEBUTTONUP: 
       if event.button == 1: 
        button_image = BUTTON_UP_IMG 
        if button_rect.collidepoint(event.pos): 
         print('Button pressed.') 
         x += 1 

     screen.fill(GRAY) 
     screen.blit(button_image, button_rect) 
     txt = font.render(str(x), True, BLUE) 
     screen.blit(txt, (260, 206)) 

     pg.display.flip() 
     clock.tick(30) 


if __name__ == '__main__': 
    main() 
    pg.quit() 

我真的建議使用類,pygame的精靈和精靈羣體,而不是僅僅rects和圖像。然後,您可以根據需要輕鬆創建儘可能多的按鈕類實例。

import pygame as pg 


pg.init() 
GRAY= pg.Color('gray12') 
BLUE = pg.Color('dodgerblue1') 
FONT = pg.font.Font(None, 30) 

BUTTON_UP_IMG = pg.Surface((50, 30)) 
BUTTON_UP_IMG.fill(BLUE) 
BUTTON_DOWN_IMG = pg.Surface((50, 30)) 
BUTTON_DOWN_IMG.fill(pg.Color('lightskyblue1')) 

# The Button is a pygame sprite, that means we can add the 
# instances to a sprite group and then update and render them 
# by calling `sprite_group.update()` and `sprite_group.draw(screen)`. 
class Button(pg.sprite.Sprite): 

    def __init__(self, pos, callback): 
     pg.sprite.Sprite.__init__(self) 
     self.image = BUTTON_UP_IMG 
     self.rect = self.image.get_rect(topleft=pos) 
     self.callback = callback 

    def handle_event(self, event): 
     """Handle events that get passed from the event loop.""" 
     if event.type == pg.MOUSEBUTTONDOWN: 
      if event.button == 1: 
       if self.rect.collidepoint(event.pos): 
        self.image = BUTTON_DOWN_IMG 
     elif event.type == pg.MOUSEBUTTONUP: 
      if event.button == 1: 
       self.image = BUTTON_UP_IMG 
       if self.rect.collidepoint(event.pos): 
        print('Button pressed.') 
        # Call the function that we passed during the 
        # instantiation. (In this case just `increase_x`.) 
        self.callback() 


class Game: 

    def __init__(self): 
     self.screen = pg.display.set_mode((800, 600)) 
     self.clock = pg.time.Clock() 

     self.x = 0 
     self.buttons = pg.sprite.Group(
      Button((200, 200), callback=self.increase_x), 
      Button((500, 200), callback=self.decrease_x)) 
     self.done = False 

    # A callback function that we pass to the button instance. 
    # It gets called if a collision in the handle_event method 
    # is detected. 
    def increase_x(self): 
     """Increase self.x if button is pressed.""" 
     self.x += 1 

    def decrease_x(self): 
     """Decrease self.x if button is pressed.""" 
     self.x -= 1 

    def run(self): 
     while not self.done: 
      self.handle_events() 
      self.run_logic() 
      self.draw() 
      self.clock.tick(30) 

    def handle_events(self): 
     for event in pg.event.get(): 
      if event.type == pg.QUIT: 
       self.done = True 

      for button in self.buttons: 
       button.handle_event(event) 

    def run_logic(self): 
     self.buttons.update() 

    def draw(self): 
     self.screen.fill(GRAY) 
     self.buttons.draw(self.screen) 
     txt = FONT.render(str(self.x), True, BLUE) 
     self.screen.blit(txt, (360, 206)) 

     pg.display.flip() 


if __name__ == "__main__": 
    Game().run() 
    pg.quit() 
0

感謝您回答我以前的問題,您的答案解決了我以前的問題,但現在我遇到了另一個問題。

當我在主菜單上按下按鈕時,它會正確更改子畫面並正確加載主遊戲,但只要我移動鼠標,它就會切換回主菜單。我最好的猜測是,它是因爲它循環了整個按鈕序列,但我不完全確定。

import pygame 
 

 
pygame.init() 
 

 
display_width = 288 
 
display_height = 512 
 

 
def main_menu(): 
 
    done = False 
 

 
    play_button_image = images['Play Button Up'] 
 
    play_button_rect = play_button_image.get_rect(topleft=(30,15)) 
 

 
    while not done: 
 

 
     for event in pygame.event.get(): 
 

 
      if event.type == pygame.QUIT: 
 
       done = True 
 
       pygame.quit() 
 
       quit() 
 

 
      if event.type == pygame.MOUSEBUTTONDOWN: 
 

 
       if event.button == 1: 
 

 
        if play_button_rect.collidepoint(event.pos): 
 
         play_button_image = images['Play Button Down'] 
 

 
      elif event.type == MOUSEBUTTONUP: 
 

 
       if event.button == 1: 
 
        play_button_image = images['Play Button Up'] 
 

 
        if play_button_rect.collidepoint(event.pos): 
 
         main_game() 
 

 
      gameDisplay.blit(play_button_image, play_button_rect) 
 

 
      pygame.display.update() 
 
      clock.tick(FPS) 
 
      
 
def main_game(): 
 
    gameExit = False 
 
    gameOver = False 
 

 
    player_index = 0 
 
    player_x = int(display_width * 0.2) 
 
    player_y = int((display_height - images['Player'][0].get_height())/2) 
 
    player_index_gen = cycle([0, 1, 2, 1]) 
 

 
    loop_iter = 0 
 

 
    starting_game_x = int((display_width - images['Starting Game'].get_width())/2) 
 
    starting_game_y = int(display_height * 0.12) 
 

 
    base_x = 0 
 

 
    base_shift = images['Base Ground'].get_width() - images['Background'].get_width() 
 

 
    player_move_vals = {'val': 0, 'dir': 1} 
 

 
    while True: 
 
     for event in pygame.event.get(): 
 
      if event.type == pygame.QUIT: 
 
       pygame.quit() 
 
       quit() 
 
      if event.type == pygame.MOUSEBUTTONDOWN or pygame.K_SPACE or pygame.K_UP: 
 
       sounds['Wing'] 
 
       return { 
 
        'player_y': player_y + player_move_vals['val'], 
 
        'base_x': base_x, 
 
        'player_index_gen': player_index_gen 
 
       } 
 

 
     if (loop_iter + 1) % 5 == 0: 
 
      player_index = next(player_index_gen) 
 
     loop_iter = (loop_iter + 1) % 30 
 
     base_x = -((-base_x + 4) % base_shift) 
 
     player_move(player_move_vals) 
 

 
     # draw sprites 
 
     gameDisplay.blit(images['Background'], (0, 0)) 
 
     gameDisplay.blit(images['Player'][player_index], 
 
        (player_x, player_y + player_move_vals['val'])) 
 
     gameDisplay.blit(images['Starting Game'], (starting_game_x, starting_game_y)) 
 
     gameDisplay.blit(images['Base Ground'], (base_x, base_y)) 
 

 
     pygame.display.update() 
 
     clock.tick(FPS) 
 
     
 
if __name__ == '__main__': 
 
    main() 
 
    

+0

請不要將問題發佈爲答案。只需刪除此答案並將其作爲新問題發佈,並告訴我們您嘗試解決問題的方法。我已經在分析代碼。 – skrx

+0

看看[這些答案](https://stackoverflow.com/questions/4986756/why-is-this-string-always-the-highest-possible-number)。你需要檢查'if event.type == pg.KEYDOWN:',然後在這個子句中'if event.key in(pg.K_SPACE,pg.K_UP):'。 – skrx

相關問題