2017-09-28 34 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

相关问题