2017-09-28 4 views
1

Je rencontre actuellement des problèmes avec les boutons de pygame. En ce moment je me fais tester dans pygame et j'essaye de créer un type de jeu d'oiseau flappy. Ce que j'essaye de réaliser est que quand je clique sur le bouton de jeu sur le menu principal cela changera le sprite de bouton et exécutera le jeu principal.Comment créer un bouton qui modifie les sprites lorsque vous cliquez sur pygame?

J'ai réussi à définir la fonction du bouton et l'amener à passer au jeu principal lorsque je clique. Le seul problème est qu'il n'affiche pas une autre image-objet quand on clique dessus et que je peux cliquer n'importe où dans l'application pour passer au jeu principal au lieu d'avoir à cliquer sur le bouton.

Toute aide serait grandement appréciée.

Merci à l'avance

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

Connaissez-vous déjà comment fonctionne la programmation orientée objet? En outre, essayez toujours de réduire votre code au [minimum] (https://stackoverflow.com/help/mcve) avant de le soumettre ici, mais assurez-vous qu'il est toujours complet et exécutable. – skrx

Répondre

0

Voici un exemple minimal pour montrer comment vous pouvez basculer entre les différentes images de bouton. Lorsque l'utilisateur appuie sur un bouton de la souris (un événement pygame.MOUSEBUTTONDOWN est ajouté à la file d'attente), vérifiez si le event.pos entre en collision avec le bouton rect et s'il entre en collision, définissez l'image sur la version «down».

Lorsque l'utilisateur relâche le bouton (événement pygame.MOUSEBUTTONUP), restaurez simplement l'image dans sa version d'origine.

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

Je recommande effectivement d'utiliser des classes, sprites Pygame et des groupes de sprite au lieu de simplement Rects et des images. Ensuite, vous pouvez facilement créer autant d'instances de la classe de boutons que vous le souhaitez.

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

Merci pour la réponse à ma question précédente, votre réponse a résolu mon précédent numéro, mais maintenant j'ai rencontré un autre problème. Lorsque j'appuie sur mon bouton dans le menu principal, il modifie correctement les sprites et charge le jeu principal correctement, mais dès que je bouge la souris, il revient au menu principal. Ma meilleure supposition est que c'est parce qu'il boucle toute la séquence de boutons, mais je ne suis pas entièrement sûr.

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

S'il vous plaît ne pas poster de questions en tant que réponses. Supprimez simplement cette réponse et postez-la comme nouvelle question, et dites-nous également ce que vous avez essayé de résoudre le problème. J'analyse déjà le code. – skrx

+0

Jetez un coup d'œil à [ces réponses] (https://stackoverflow.com/questions/4986756/why-is-this-string-always-the-highest-possible-number). Vous devez vérifier 'si event.type == pg.KEYDOWN:' et ensuite dans cette clause 'if event.key dans (pg.K_SPACE, pg.K_UP):'. – skrx