I'm making a simple project for Pygame, which is basically intended to run as a text-based strategy/fighting game. I coded it just using Python, but now I'm trying to implement a GUI using Pygame (and expand on it eventually).
In this game, the player has a number of available moves depending on their current position (stored as an array). What I'm hoping to do is create and display a button for each of these moves that the user can choose from.
I know how to make a button, but I'm struggling to figure out how to add a button per move and constantly updates, based on the player's changing position.
You basically want a Button
class for that. That way you can create button objects, put them in a list and operate on them easily. Here is an example with a barely-even-a-button Button
class just to get the point across. I have created a list with 4 buttons, but you can just as easily .append
those buttons to dynamically create them according to the needs of your program.
import pygame
from sys import exit as _exit
##just pygame stuff here. You can ignore them and go
##to the interesting things below
class PG_Widnow_UI:
def __init__(self, width, height):
pygame.init()
self.widht = width
self.height = height
self.window = pygame.display.set_mode((width, height))
def update(self):
pygame.display.flip()
def clear(self, r, g, b):
self.window.fill((r, g, b))
def close(self):
pygame.quit()
_exit()
#handles events
def handleEvents(events):
exitGame = False
for event in events:
if event.type == pygame.QUIT:
pg_window.close()
#Takes rectangle's size, position and a point. Returns true if that
#point is inside the rectangle and false if it isnt.
def pointInRectanlge(px, py, rw, rh, rx, ry):
if px > rx and px < rx + rw:
if py > ry and py < ry + rh:
return True
return False
##=====================================================================##
#This class will act as a bllueprint for all the buttons in the game
class Button:
def __init__(self, text:str, position:tuple
, size:tuple=(200, 50), outline:bool=True)->None:
self.position = position
self.size = size
self.button = pygame.Surface(size).convert()
self.button.fill((0, 0, 0))
self.outline = outline
#Text is about 70% the height of the button
font = pygame.font.Font(pygame.font.get_default_font(), int((70/100)*self.size[1]))
#First argument always requires a str, so f-string is used.
self.textSurf = font.render(f"{text}", True, (255, 255, 255))
def clicked(self, events)->None:
mousePos = pygame.mouse.get_pos()
if pointInRectanlge(mousePos[0], mousePos[1], self.size[0], self.size[1], self.position[0], self.position[1]):
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN:
return True
return False
#Renders the button and text. Text position is calculated depending on position of button.
#Also draws outline if self.outline is true
def render(self, display:pygame.display)->None:
#calculation to centre the text in button
textx = self.position[0] + (self.button.get_rect().width/2) - (self.textSurf.get_rect().width/2)
texty = self.position[1] + (self.button.get_rect().height/2) - (self.textSurf.get_rect().height/2)
#display button first then text
display.blit(self.button, (self.position[0], self.position[1]))
display.blit(self.textSurf, (textx, texty))
#draw outline
if self.outline:
thickness = 5
posx = self.position[0] - thickness
posy = self.position[1] - thickness
sizex = self.size[0] + thickness * 2
sizey = self.size[1] + thickness * 2
pygame.draw.rect(display, (255, 0, 0), (posx, posy, sizex, sizey), thickness)
windowWidth = 1000
windowHeight = 500
pg_window = PG_Widnow_UI(windowWidth, windowHeight)
##LOOP TO ADD BUTTONS TO THE LIST
number_of_buttons = 4
buttons = [Button(f"Button {i}", ((220 * (i%4) + 10), ((i % 4) * 70) + 10))
for i in range(number_of_buttons)]
while True:
pg_window.clear(255, 255, 255)
events = pygame.event.get()
handleEvents(events)
##DRAWING THE BUTTONS
for button in buttons:
button.render(pg_window.window)
if button.clicked(events):
print(f"button at position: {button.position} was clicked")
pg_window.update()