为什么我的按钮在主循环之外不起作用
Why does my button not work outside of the main loop
我一直在关注 this tutorial pygame 中的动画按钮。在我在另一个函数的主循环之外创建一个按钮之前,它工作得很好。
这是我的代码:
import pygame
from pygame.locals import *
import sys
import random
# Constants
SCREEN = pygame.display.set_mode((1280, 720), 0, 32)
# Colours
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (100, 100, 100)
LIGHT_BLUE = (66, 233, 245)
# Button Class
class Button:
def __init__(self, text, width, height, pos, elevation):
# Core attributes
self.pressed = False
self.elevation = elevation
self.dynamicElevation = elevation
self.originalYPos = pos[1]
# Top Rectangle
self.topRectangle = pygame.Rect(pos, (width, height))
self.topColor = '#457B9D'
# Bottom Rectangle
self.bottomRectangle = pygame.Rect(pos, (width, elevation))
self.bottomColor = '#1D3557'
# Text
self.textSurface = gui_font.render(text, True, '#FFFFFF')
self.textRectangle = self.textSurface.get_rect(center = self.topRectangle.center)
def draw(self):
# Elevation Logic
self.topRectangle.y = self.originalYPos - self.dynamicElevation
self.textRectangle.center = self.topRectangle.center
self.bottomRectangle.midtop = self.topRectangle.midtop
self.bottomRectangle.height = self.topRectangle.height + self.dynamicElevation
bottom =pygame.draw.rect(SCREEN, self.bottomColor, self.bottomRectangle, border_radius = 12)
top = pygame.draw.rect(SCREEN, self.topColor, self.topRectangle, border_radius = 12)
pygame.draw.rect(SCREEN, '#000000', top, 1, border_radius = 12)
pygame.draw.rect(SCREEN, '#000000', bottom, 1, border_radius = 12)
SCREEN.blit(self.textSurface, self.textRectangle)
self.check_click()
def check_click(self):
mousePosition = pygame.mouse.get_pos()
if self.topRectangle.collidepoint(mousePosition):
self.topColor = '#F1FAEE'
if pygame.mouse.get_pressed()[0]:
self.dynamicElevation = 0
self.pressed = True
else:
self.dynamicElevation = self.elevation
if self.pressed == True:
print("Click")
self.pressed = False
else:
self.topColor = '#457B9D'
class GameState():
def __init__(self):
self.state = "welcome"
def welcomeScreen(self):
SCREEN.fill(WHITE)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
if event.key == K_F1:
self.state = "mainGame"
pygame.display.update()
def mainGame(self):
SCREEN.fill(GREY)
buttonBack = Button("Back to Main Screen", 250, 30, (1000, 650), 8)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
if event.key == K_F2:
self.state = "welcome"
buttonBack.draw()
pygame.display.update()
def stateManager(self):
if self.state == "welcome":
self.welcomeScreen()
if self.state == "mainGame":
self.mainGame()
pygame.init()
clock = pygame.time.Clock()
gameState = GameState()
pygame.display.set_caption("Button Test")
gui_font = pygame.font.Font(None, 30)
while True:
gameState.stateManager()
clock.tick(60)
我试过将按钮放在不同的屏幕或循环的不同阶段。是否存在我看不到的逻辑错误或其他地方的错误?
您实际上是在主循环内创建按钮,因为您每次调用 mainGame
时都会创建它。 mainGame
如果状态为“mainGame”,则由 stateManager
调用,并且会在 while True
循环中的每一帧调用。所以当你在每一帧重新创建你的按钮时,我认为你的问题可能来自那里。
我建议您改为在父级的 class 构造函数中创建按钮:
class GameState():
def __init__(self):
self.state = "welcome"
# Create the button here to make the object persistent.
self.buttonBack = Button("Back to Main Screen", 250, 30, (1000, 650), 8)
# ...
def mainGame(self):
SCREEN.fill(GREY)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
if event.key == K_F2:
self.state = "welcome"
self.buttonBack.draw() # <- use your button with self.buttonBack
pygame.display.update()
# ...
我一直在关注 this tutorial pygame 中的动画按钮。在我在另一个函数的主循环之外创建一个按钮之前,它工作得很好。
这是我的代码:
import pygame
from pygame.locals import *
import sys
import random
# Constants
SCREEN = pygame.display.set_mode((1280, 720), 0, 32)
# Colours
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (100, 100, 100)
LIGHT_BLUE = (66, 233, 245)
# Button Class
class Button:
def __init__(self, text, width, height, pos, elevation):
# Core attributes
self.pressed = False
self.elevation = elevation
self.dynamicElevation = elevation
self.originalYPos = pos[1]
# Top Rectangle
self.topRectangle = pygame.Rect(pos, (width, height))
self.topColor = '#457B9D'
# Bottom Rectangle
self.bottomRectangle = pygame.Rect(pos, (width, elevation))
self.bottomColor = '#1D3557'
# Text
self.textSurface = gui_font.render(text, True, '#FFFFFF')
self.textRectangle = self.textSurface.get_rect(center = self.topRectangle.center)
def draw(self):
# Elevation Logic
self.topRectangle.y = self.originalYPos - self.dynamicElevation
self.textRectangle.center = self.topRectangle.center
self.bottomRectangle.midtop = self.topRectangle.midtop
self.bottomRectangle.height = self.topRectangle.height + self.dynamicElevation
bottom =pygame.draw.rect(SCREEN, self.bottomColor, self.bottomRectangle, border_radius = 12)
top = pygame.draw.rect(SCREEN, self.topColor, self.topRectangle, border_radius = 12)
pygame.draw.rect(SCREEN, '#000000', top, 1, border_radius = 12)
pygame.draw.rect(SCREEN, '#000000', bottom, 1, border_radius = 12)
SCREEN.blit(self.textSurface, self.textRectangle)
self.check_click()
def check_click(self):
mousePosition = pygame.mouse.get_pos()
if self.topRectangle.collidepoint(mousePosition):
self.topColor = '#F1FAEE'
if pygame.mouse.get_pressed()[0]:
self.dynamicElevation = 0
self.pressed = True
else:
self.dynamicElevation = self.elevation
if self.pressed == True:
print("Click")
self.pressed = False
else:
self.topColor = '#457B9D'
class GameState():
def __init__(self):
self.state = "welcome"
def welcomeScreen(self):
SCREEN.fill(WHITE)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
if event.key == K_F1:
self.state = "mainGame"
pygame.display.update()
def mainGame(self):
SCREEN.fill(GREY)
buttonBack = Button("Back to Main Screen", 250, 30, (1000, 650), 8)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
if event.key == K_F2:
self.state = "welcome"
buttonBack.draw()
pygame.display.update()
def stateManager(self):
if self.state == "welcome":
self.welcomeScreen()
if self.state == "mainGame":
self.mainGame()
pygame.init()
clock = pygame.time.Clock()
gameState = GameState()
pygame.display.set_caption("Button Test")
gui_font = pygame.font.Font(None, 30)
while True:
gameState.stateManager()
clock.tick(60)
我试过将按钮放在不同的屏幕或循环的不同阶段。是否存在我看不到的逻辑错误或其他地方的错误?
您实际上是在主循环内创建按钮,因为您每次调用 mainGame
时都会创建它。 mainGame
如果状态为“mainGame”,则由 stateManager
调用,并且会在 while True
循环中的每一帧调用。所以当你在每一帧重新创建你的按钮时,我认为你的问题可能来自那里。
我建议您改为在父级的 class 构造函数中创建按钮:
class GameState():
def __init__(self):
self.state = "welcome"
# Create the button here to make the object persistent.
self.buttonBack = Button("Back to Main Screen", 250, 30, (1000, 650), 8)
# ...
def mainGame(self):
SCREEN.fill(GREY)
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
if event.key == K_F2:
self.state = "welcome"
self.buttonBack.draw() # <- use your button with self.buttonBack
pygame.display.update()
# ...