Reputation: 51
I'm trying to make a simple menu for a game in pygame, but I'm struggling to display interactive text for the menu buttons. I have a very simple menu, with the 'Start' and 'Quit' options, and I'm trying to display them using a Button class I made.
For some reason the button background blits but the text doesn't appear. I get a bunch of rectangles which change colour correctly as I scroll over them but no text.
I looked at similar questions but can't seem to figure out why mine doesn't work. Any help or guidance would be appreciated.
Here is a code sample below. Colours are defined in a separate python file.
class Start(SceneBase):
def __init__(self):
SceneBase.__init__(self)
self.options = ['Start', 'Quit']
self.buttons = pygame.sprite.Group()
def initGraphics(self, screen):
SceneBase.initGraphics(self, screen)
info = pygame.display.Info()
screenWidth, screenHeight = info.current_w, info.current_h
font = pygame.font.Font('freesansbold.ttf', 30)
for i, option in enumerate(self.options):
rect = pygame.Rect(int(screenWidth/2) - 50, int(screenHeight/2) - 100 + i*50, 100, 30)
passive_color = colors.BLACK
active_color = colors.RED
button = Button(rect, font, active_color, option, colors.WHITE, passive_color, option, colors.WHITE)
self.buttons.add(button)
def ProcessInput(self, events, pressed_keys):
pass
def Update(self):
self.buttons.update()
def Render(self):
self.screen.fill(colors.WHITE)
self.buttons.draw(self.screen)
pygame.display.flip()
class Button(pygame.sprite.Sprite):
def __init__(self, rect, font, active_color, active_text, active_textcolor, passive_color, passive_text, passive_textcolor):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((rect[2], rect[3]))
self.rect = rect
self.font = font
self.active_color = active_color
self.active_text = active_text
self.active_textcolor = active_textcolor
self.passive_color = passive_color
self.passive_text = passive_text
self.passive_textcolor = passive_textcolor
def update(self):
mouse = pygame.mouse.get_pos()
if self.rect.x <= mouse[0] <= self.rect.x + self.rect.w and self.rect.y <= mouse[1] <= self.rect.y + self.rect.h:
self.image.fill(self.active_color)
self.renderButtonText(self.active_text, self.active_textcolor)
else:
self.image.fill(self.passive_color)
self.renderButtonText(self.passive_text, self.passive_textcolor)
def renderButtonText(self, text, color):
textsurf = self.font.render(text, True, color)
textrect = textsurf.get_rect()
textrect.center = self.rect.center
self.image.blit(textsurf, textrect)
This is the skeleton code for the SceneBase class:
pygame.init()
def run_game(width, height, fps, starting_scene):
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
active_scene = starting_scene
initialized = False
while active_scene:
if not initialized:
active_scene.initGraphics(screen)
initialized = True
pressed_keys = pygame.key.get_pressed()
# Event filtering
filtered_events = []
for event in pygame.event.get():
quit_attempt = False
if event.type == pygame.QUIT:
quit_attempt = True
elif event.type == pygame.KEYDOWN:
alt_pressed = pressed_keys[pygame.K_LALT] or \
pressed_keys[pygame.K_RALT]
if event.key == pygame.K_ESCAPE:
quit_attempt = True
elif event.key == pygame.K_F4 and alt_pressed:
quit_attempt = True
if quit_attempt:
active_scene.Terminate()
else:
filtered_events.append(event)
active_scene.ProcessInput(filtered_events, pressed_keys)
active_scene.Update()
active_scene.Render()
active_scene = active_scene.next
pygame.display.flip()
clock.tick(fps)
#==============================================================================
# The rest is code where you implement your game using the Scenes model
run_game(500, 500, 60, Start())
Upvotes: 2
Views: 419
Reputation: 233
It seems that you're rendering the button text before you're rendering the background, so what is probably happening is that the text is being drawn, but the button is being drawn over it in the same frame, so it seems that there's no text. Try adding the update function's code to a new function called checkIfHovering, and have it write:
def checkIfHovering(self):
mouse = pygame.mouse.get_pos()
if self.rect.x <= mouse[0] <= self.rect.x + self.rect.w and self.rect.y <= mouse[1] <= self.rect.y + self.rect.h:
self.image.fill(self.active_color)
self.renderButtonText(self.active_text, self.active_textcolor)
else:
self.image.fill(self.passive_color)
self.renderButtonText(self.passive_text, self.passive_textcolor)
and in addition to that, change the Render function to have:
def Render(self):
self.screen.fill(colors.WHITE)
self.buttons.draw(self.screen)
self.buttons.checkIfHovering()
pygame.display.flip()
That way it's printing the text after the button backgrounds are being drawn.
Upvotes: 1