如何在pygame中单击时创建一个更改精灵的按钮?

时间:2017-09-28 08:31:36

标签: python-3.x 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()




2 个答案:

答案 0 :(得分: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 sprites和sprite组,而不仅仅是rects和images。然后,您可以根据需要轻松创建任意数量的按钮类实例。

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

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