问题
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