In this version of a test game with pygame we added the chance to put more tha one question into a list. The right answer will be put as first and then it will be put in a random order on the screen. There is a little number on the top left corner that indicates the number of the question.
The next things to do will be:
- add the score somewhere
- understand when the test is ended
- add the final result
- allow to start again
- choose among different tests
- add some graphic feedback to the click and the response
- put some particles system for the effects
- add chance to put images in the questions
import pygame import pygame.gfxdraw import sys import time import random pygame.init() screen = pygame.display.set_mode((600, 400)) clock = pygame.time.Clock() buttons = pygame.sprite.Group() class Button(pygame.sprite.Sprite): def __init__(self, position, text, size, colors="white on blue", hover_colors="red on green", style=1, borderc=(255,255,255), command=lambda: print("No command activated for this button")): # the hover_colors attribute needs to be fixed super().__init__() self.text = text self.command = command # --- colors --- self.colors = colors self.original_colors = colors self.fg, self.bg = self.colors.split(" on ") if hover_colors == "red on green": self.hover_colors = f"{self.bg} on {self.fg}" else: self.hover_colors = hover_colors self.style = style self.borderc = borderc # for the style2 # font self.font = pygame.font.SysFont("Arial", size) self.render() self.x, self.y, self.w , self.h = self.text_render.get_rect() self.x, self.y = position self.rect = pygame.Rect(self.x, self.y, self.w, self.h) self.position = position self.pressed = 1 # the groups with all the buttons buttons.add(self) def render(self): # we have a surface self.text_render = self.font.render(self.text, 1, self.fg) # memorize the surface in the image attributes self.image = self.text_render def update(self): self.fg, self.bg = self.colors.split(" on ") if self.style == 1: self.draw_button1() elif self.style == 2: self.draw_button2() if self.command != None: self.hover() self.click() def draw_button1(self): ''' draws 4 lines around the button and the background ''' # horizontal up pygame.draw.line(screen, (150, 150, 150), (self.x, self.y), (self.x + self.w , self.y), 5) pygame.draw.line(screen, (150, 150, 150), (self.x, self.y - 2), (self.x, self.y + self.h), 5) # horizontal down pygame.draw.line(screen, (50, 50, 50), (self.x, self.y + self.h), (self.x + self.w , self.y + self.h), 5) pygame.draw.line(screen, (50, 50, 50), (self.x + self.w , self.y + self.h), [self.x + self.w , self.y], 5) # background of the button pygame.draw.rect(screen, self.bg, (self.x, self.y, self.w , self.h)) def draw_button2(self): ''' a linear border ''' pygame.draw.rect(screen, self.bg, (self.x, self.y, self.w , self.h)) pygame.gfxdraw.rectangle(screen, (self.x, self.y, self.w , self.h), self.borderc) def check_collision(self): if self.rect.collidepoint(pygame.mouse.get_pos()): # you can change the colors when the pointer is on the button if you want self.colors = self.hover_colors # pygame.mouse.set_cursor(*pygame.cursors.diamond) else: self.colors = self.original_colors # pygame.mouse.set_cursor(*pygame.cursors.arrow) def hover(self): ''' checks if the mouse is over the button and changes the color if it is true ''' if self.style == 1: self.check_collision() self.render() else: self.check_collision() def click(self): ''' checks if you click on the button and makes the call to the action just one time''' if self.rect.collidepoint(pygame.mouse.get_pos()): if pygame.mouse.get_pressed()[0] and self.pressed == 1: print("The answer is:'" + self.text + "'") self.command() self.pressed = 0 if pygame.mouse.get_pressed() == (0,0,0): self.pressed = 1 # FUNCTIONS for the buttons on click # I used this convention ... on_+text of the button def on_click(): print("Click on one answer") def on_run(): print("Ciao bello questo è RUN") def on_save(): print("This is Save") def on_right(): print("Right") forward() def on_false(): print("Wrong") forward() def forward(): global qnum screen.fill(0) if qnum < len(questions): time.sleep(.3) qnum += 1 question(qnum) questions = [ ["What is Italy's Capital?", ["Rome", "Paris"]], ["What is France's Capital?", ["Paris", "Rome"]], ["What is England's Capital?", ["London", "Rome"]], ] def question(qnum): ''' put your buttons here ''' for sprites in buttons: sprites.kill() pos = [100, 150] # this is a label, a button with no border does nothing: command = None lbl_num = Button((0, 0), str(qnum-1), 20, "white on black", hover_colors="blue on orange", style=2, borderc=(255,0,0), command=None) lbl_question = Button((10, 10), questions[qnum-1][0], 55, "white on black", hover_colors="blue on orange", style=2, borderc=(0,0,0), command=None) x1 = random.sample(pos, 1) pos.pop(pos.index(x1[0])) print(pos) b1 = Button((10, x1[0]), questions[qnum-1][1][0], 36, "red on yellow", hover_colors="blue on orange", style=2, borderc=(255,255,0), command=on_right) y1 = 100 if x1[0] == 150 else 150 b2 = Button((10, y1), questions[qnum-1][1][1], 36, "red on yellow", hover_colors="blue on orange", style=2, borderc=(255,255,0), command=on_false) # ======================= this code is just for example, start the program from the main file # in the main folder, I mean, you can also use this file only, but I prefer from the main file # 29.8.2021 qnum = 1 if __name__ == '__main__': pygame.init() game_on = 0 def loop(): # BUTTONS ISTANCES global qnum game_on = 1 question(qnum) while True: screen.fill(0) for event in pygame.event.get(): if (event.type == pygame.QUIT): game_on = 0 pygame.quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() game_on = 0 if game_on: buttons.update() buttons.draw(screen) else: pygame.quit() sys.exit() buttons.draw(screen) clock.tick(60) pygame.display.update() pygame.quit() loop()
https://github.com/formazione/pygame_button.git
Subscribe to the newsletter for updates
Tkinter templates
My youtube channel
Twitter: @pythonprogrammi - python_pygame