Adding menu with buttons to pygame

断了今生、忘了曾经 提交于 2020-02-04 01:11:27

问题


I am trying to add a menu to my game for a very long time but it doesn't show up. There is a screen which comes up, however it is empty and only has words but no buttons, so no matter where I click, it takes me to the same page. Like a screen shows but the buttons don't appear and I am not sure why. How do I add a button for the options?

background = pygame.image.load('background.png')
backgroundX = 0
backgroundX2 = background.get_width()
homeScreen = pygame.image.load('home_screen.png')
obstacle = pygame.image.load('obstacle.png')
obstacleX = 0
obstacleX2 = obstacle.get_width()
instructions = pygame.image.load('instructions.png')

# frame rate
clock = pygame.time.Clock()


# use procedure for game window rather than using it within loop
def redrawGameWindow():
    # background images for right to left moving screen
    screen.blit(background, (backgroundX, 0))
    screen.blit(background, (backgroundX2, 0))
    man.draw(screen)
    screen.blit(obstacle, (obstacleX, 400))
    screen.blit(obstacle, (obstacleX2, 400))
    pygame.display.flip()
    pygame.display.update()


# create class for character (object)
class player(object):
    def __init__(self, x, y, width, height):  # initialize attributes
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.left = True
        self.right = True
        self.isJump = False
        self.stepCount = 0
        self.jumpCount = 10
        self.standing = True

    def draw(self, screen):
        if self.stepCount + 1 >= 27:  # 9 sprites, with 3 frames - above 27 goes out of range
            self.stepCount = 0

        if not self.standing:
            if self.left:
                screen.blit(leftDirection[self.stepCount // 5], (self.x, self.y), )
                self.stepCount += 1
            elif self.right:
                screen.blit(rightDirection[self.stepCount // 5], (self.x, self.y), )
                self.stepCount += 1
        else:
            if self.right:
                screen.blit(rightDirection[0], (self.x, self.y))  # using index, include right faced photo
            else:
                screen.blit(leftDirection[0], (self.x, self.y))


class enlargement(object):
    def __init__(self, x, y, radius, color, facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.facing = facing

    def draw(self, screen):
        pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius, 1)


man = player(200, 313, 64, 64)

font = pygame.font.Font(None, 75)  # font for home screen
instructionsFont = pygame.font.Font(None, 30)  # font for instructions page

# HOME SCREEN

font = pygame.font.Font(None, 75)  # font for home screen
instructionsFont = pygame.font.Font(None, 30)  # font for instructions page

display_instructions = True
homePage = 1
play_page = 2

done = False

while not done and display_instructions:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            homePage += 1
            if homePage == 3:
                display_instructions = False

    # background
    screen.blit(homeScreen, (0, 0))

    if homePage == 1:
        text = font.render("Star Keeper", True, white)
        screen.blit(text, [115, 40])

        text = font.render("Home", True, white)
        screen.blit(text, [180, 130])

        text = font.render("Instructions", True, white)
        screen.blit(text, [100, 220])

        text = font.render("Play", True, white)
        screen.blit(text, [200, 300])

    if homePage == 2:
        # Draw instructions, page 2
        text1 = instructionsFont.render("Welcome to Star Keeper", True, white)
        text2 = instructionsFont.render("The objective of the game", True, white)
        text3 = instructionsFont.render("is to jump over obstacles using ", True, white)
        text4 = instructionsFont.render("the space key. Hitting an obstacle", True, white)
        text5 = instructionsFont.render("will cause you to lose. Good luck!", True, white)

        screen.blit(text1, [130, 50])
        screen.blit(text2, [130, 100])
        screen.blit(text3, [93, 150])
        screen.blit(text4, [93, 200])
        screen.blit(text5, [93, 250])

    # Limit to 60 frames per second
    clock.tick(60)

    # Go ahead and update the screen with what we've drawn.
    pygame.display.flip()
    pygame.display.update()

#  main loop

speed = 30  # NEW
man = player(200, 410, 64, 64)  # set main character attributes
run = True
while run:
        screen.fill(white)

        clock.tick(30)
        pygame.display.update()
        redrawGameWindow()  # call procedure
        clock.tick(speed)  # NEW
        backgroundX -= 1.4  # Move both background images back
        backgroundX2 -= 1.4
        obstacleX -= 1.4
        obstacleX2 -= 1.4

        if backgroundX < background.get_width() * -1:  # If our background is at the -width then reset its position
            backgroundX = background.get_width()

        if backgroundX2 < background.get_width() * -1:
            backgroundX2 = background.get_width()

        if obstacleX < obstacle.get_width() * -10:
            obstacleX = obstacle.get_width

        if obstacleX2 < obstacle.get_width() * -10:
            obstacleX2 = obstacle.get_width()

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

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            man.left = True
            man.right = False
            man.standing = False  # false, because man is walking
        # verify that character is within window parameters
        elif keys[pygame.K_RIGHT]:
            man.right = True
            man.left = False
            man.standing = False  # false, because man is walking
        else:
            man.standing = True
            man.stepCount = 0

        if not man.isJump:
            if keys[pygame.K_SPACE]:
                man.isJump = True  # when jumping, man shouldn't move directly left or right
                man.right = False
                man.left = False
                man.stepCount = 0
        else:
            if man.jumpCount >= -10:
                neg = 1
                if man.jumpCount < 0:
                    neg = -1
                man.y -= (man.jumpCount ** 2) * .5 * neg  # to jump use parabola
                man.jumpCount -= 1
            else:
                man.isJump = False
                man.jumpCount = 10

pygame.quit()

回答1:


You blit text but button needs something more than only text. It needs also size and position which you can keep in pygame.Rect() and which you can use to draw button's background/rectangle (pygame.draw.rect()) and to check collision with mouse (button.rect.collidepoint(event.pos)).


This example uses three functions:

button_create - to create pygame.Rect() with size and position, and to generate surface with text (but without background).

button_draw - to draw button's background/rectanlge and to draw text on this rectangle

button_check - to check collision between mouse and button - to change color and to run assigned function.

#!/usr/bin/env python3

import pygame

# --- constants --- (UPPER_CASE_NAMES)

WHITE = (255,255,255)
BLACK = (  0,  0,  0)

RED   = (255,  0,  0)
GREEN = (  0,255,  0)
BLUE  = (  0,  0,255)

YELLOW = (255,255, 0)

# --- classes --- (CamelCaseNanes)

# empty

# --- functions --- (lower_case_names_

def button_create(text, rect, inactive_color, active_color, action):

    font = pygame.font.Font(None, 40)

    button_rect = pygame.Rect(rect)

    text = font.render(text, True, BLACK)
    text_rect = text.get_rect(center=button_rect.center)

    return [text, text_rect, button_rect, inactive_color, active_color, action, False]


def button_check(info, event):

    text, text_rect, rect, inactive_color, active_color, action, hover = info

    if event.type == pygame.MOUSEMOTION:
        # hover = True/False   
        info[-1] = rect.collidepoint(event.pos)

    elif event.type == pygame.MOUSEBUTTONDOWN:
        if hover and action:      
            action()


def button_draw(screen, info):

    text, text_rect, rect, inactive_color, active_color, action, hover = info

    if hover:
        color = active_color
    else:
        color = inactive_color

    pygame.draw.rect(screen, color, rect)
    screen.blit(text, text_rect)

# ---

def on_click_button_1():
    global stage
    stage = 'game'

    print('You clicked Button 1')

def on_click_button_2():
    global stage
    stage = 'options'

    print('You clicked Button 2')

def on_click_button_3():
    global stage
    global running

    stage = 'exit'
    running = False

    print('You clicked Button 3')

def on_click_button_return():
    global stage
    stage = 'menu'

    print('You clicked Button Return')

# --- main ---  (lower_case_names)

# - init -

pygame.init()
screen = pygame.display.set_mode((800,600))
screen_rect = screen.get_rect()

# - objects -

stage = 'menu'

button_1 = button_create("GAME", (300, 100, 200, 75), RED, GREEN, on_click_button_1)
button_2 = button_create("OPTIONS", (300, 200, 200, 75), RED, GREEN, on_click_button_2)
button_3 = button_create("EXIT", (300, 300, 200, 75), RED, GREEN, on_click_button_3)

button_return = button_create("RETURN", (300, 400, 200, 75), RED, GREEN, on_click_button_return)

# - mainloop -

running = True

while running:

    # - events -

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

        if stage == 'menu':
            button_check(button_1, event)
            button_check(button_2, event)
            button_check(button_3, event)
        elif stage == 'game':
            button_check(button_return, event)
        elif stage == 'options':
            button_check(button_return, event)
        #elif stage == 'exit':
        #    pass

    # - draws -

    screen.fill(BLACK)

    if stage == 'menu':
        button_draw(screen, button_1)
        button_draw(screen, button_2)
        button_draw(screen, button_3)
    elif stage == 'game':
        button_draw(screen, button_return)
    elif stage == 'options':
        button_draw(screen, button_return)
    #elif stage == 'exit':
    #    pass

    pygame.display.update()

# - end -

pygame.quit()


Other method is to create class Button with methods __init__() (instead od button_create), draw() and handle_event() (or check()) - so it can be similar to class Player or pygame.sprite.Sprite



来源:https://stackoverflow.com/questions/59778780/adding-menu-with-buttons-to-pygame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!