I am new to programming , PyGame and OOP especially. I can't figure out how to make a button execute a specific command in PyGame. I tried making a class for a button, and if you look at this code, I am able to execute the hover method/function as an example, but I am struggling to make the game close when I press the exit button. I can't seem to understand how to pass an argument that would make the main_menu be false for when exit is executed and main_game be true when play is executed.
from ColorsAndCoordinates import *
pygame.init()
screen = pygame.display.set_mode((1000, 700))
font = pygame.font.Font("freesansbold.ttf", 42)
class Button:
main_menu = True
def __init__(self, color, x, y, width, height, text):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def display(self, color):
self.color = color
pygame.draw.rect(screen, self.color, (self.x, self.y, self.width, self.height))
text = font.render(self.text, True, red)
screen.blit(text, (self.x, self.y))
def hover(self, color):
mouse = pygame.mouse.get_pos()
if self.x + self.width > mouse[0] > self.x and self.y + self.height > mouse[1] > self.y:
Button.display(self, color)
def clicked(self):
mouse = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if self.x + self.width > mouse[0] > self.x and self.y + self.height > mouse[1] > self.y:
pass
play_button = Button(blue, 200, 300, 95, 46, "Play")
exit_button = Button(blue, 700, 300, 95, 46, "Exit")
tutorial_button = Button(blue, 410, 550, 165, 46, "Tutorial")
main_menu = True
main_game = False
while main_menu:
screen.fill(black)
play_button.display(blue)
exit_button.display(blue)
tutorial_button.display(blue)
play_button.hover(black)
exit_button.hover(black)
tutorial_button.hover(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
main_menu = False
exit_button.clicked()
pygame.display.update()
There are different solutions for this, for instance polymorphism, an action or an event.
An obvious and simple solution, is to add an action
argument to the the method clicked
. The argument is an action function, which is invoked when the button is clicked:
class Button:
# [...]
def clicked(self, action = None):
mouse = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if self.x + self.width > mouse[0] > self.x and self.y + self.height > mouse[1] > self.y:
if action:
action()
Create a function, which changes the states. Consider to use the global
statement for the variables in global name space main_menu
and main_game
:
def action_exit():
global main_menu, main_game
main_menu = False
main_game = True
Pass the action to the exit_button.clicked
:
while main_menu:
# [...]
exit_button.clicked(action_exit)
Furthermore changed Button.display(self, color)
to self.display(color)
in the method display()
.
Complete example:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1000, 700))
font = pygame.font.Font("freesansbold.ttf", 42)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
black = (0, 0, 0)
class Button:
main_menu = True
def __init__(self, color, x, y, width, height, text):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def display(self, color):
self.color = color
pygame.draw.rect(screen, self.color, (self.x, self.y, self.width, self.height))
text = font.render(self.text, True, red)
screen.blit(text, (self.x, self.y))
def hover(self, color):
mouse = pygame.mouse.get_pos()
if self.x + self.width > mouse[0] > self.x and self.y + self.height > mouse[1] > self.y:
self.display(color)
def clicked(self, action = None):
mouse = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if self.x + self.width > mouse[0] > self.x and self.y + self.height > mouse[1] > self.y:
if action:
action()
def action_exit():
global main_menu, main_game
main_menu = False
main_game = True
play_button = Button(blue, 200, 300, 95, 46, "Play")
exit_button = Button(blue, 700, 300, 95, 46, "Exit")
tutorial_button = Button(blue, 410, 550, 165, 46, "Tutorial")
main_menu = True
main_game = False
while main_menu:
screen.fill(black)
play_button.display(blue)
exit_button.display(blue)
tutorial_button.display(blue)
play_button.hover(black)
exit_button.hover(black)
tutorial_button.hover(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
main_menu = False
exit_button.clicked(action_exit)
pygame.display.update()