piotrekobi
piotrekobi

Reputation: 75

Pygame menu buttons unresponsive

The buttons in my menu screen created with Pygame are sometimes unresponsive and require more than 1 click or holding LMB. What can I do to fix this?

def menu():
    global clock
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
                break

        gameDisplay.fill(white)
        print_to_screen("Tic Tac Toe", black, (200, 50), 50)
        # button(display, color_1, color_2, rectangle, text, action):
        button(gameDisplay, green, bright_green, (100, 120, 200, 60), "Start Game", game_loop)
        button(gameDisplay, red, bright_red, (100, 220, 200, 60), "Quit", quit_game)
        pygame.display.update()
        clock.tick(15) # now changed to clock.tick(60)


def button(display, color_1, color_2, rectangle, text, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if rectangle[0] < mouse[0] < rectangle[0] + rectangle[2] and rectangle[1] < mouse[1] < rectangle[1] + rectangle[3]:
        pygame.draw.rect(display, color_2, rectangle)
        if click[0] == 1:
            action()
    else:
        pygame.draw.rect(display, color_1, rectangle)
    small_text = pygame.font.Font('freesansbold.ttf', 20)
    text_surf, text_rect = text_objects(text, small_text, white)
    text_rect.center = ((rectangle[0] + rectangle[2] / 2), rectangle[1] + rectangle[3] / 2)
    gameDisplay.blit(text_surf, text_rect)

Upvotes: 3

Views: 132

Answers (1)

unlut
unlut

Reputation: 3775

Because your event loop consumes and discards some mouse click events. You can solve problem by saving mouse click event and pass it to button function. Take a look at responsive_button function. (Next time please share a full runnable code)

import numpy as np
import pygame
from pygame.locals import *
import time
import random
import math    #  trigonometry functions

#  initialize pygame
pygame.init()


gameDisplay = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()


#  COLOR CONSTANTS
black = (0,0,0)
white = (255,255,255)
red = (200,0,0)
green = (0,200,0)
blue = (0, 0, 200)
bright_red = (255,0,0)
bright_green = (0,255,0)


def game_loop():
    while True:
        pass

def quit_game():
    exit(0)

def menu():
    global clock
    while True:
        gameDisplay.fill(white)

        mouse_clicked = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
                break
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_clicked = True


        #button(gameDisplay, green, bright_green, (100, 120, 200, 60), "Start Game", game_loop)
        #button(gameDisplay, red, bright_red, (100, 220, 200, 60), "Quit", quit_game)



        responsive_button(gameDisplay, green, bright_green, (100, 120, 200, 60), "Start Game", mouse_clicked, game_loop)
        responsive_button(gameDisplay, red, bright_red, (100, 220, 200, 60), "Quit", mouse_clicked, quit_game)



        pygame.display.update()
        clock.tick(15) # now changed to clock.tick(60)



def text_objects(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()


def button(display, color_1, color_2, rectangle, text, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if rectangle[0] < mouse[0] < rectangle[0] + rectangle[2] and rectangle[1] < mouse[1] < rectangle[1] + rectangle[3]:
        pygame.draw.rect(display, color_2, rectangle)
        if click[0] == 1:
            action()
    else:
        pygame.draw.rect(display, color_1, rectangle)
    small_text = pygame.font.Font('freesansbold.ttf', 20)
    text_surf, text_rect = text_objects(text, small_text)
    text_rect.center = ((rectangle[0] + rectangle[2] / 2), rectangle[1] + rectangle[3] / 2)
    gameDisplay.blit(text_surf, text_rect)


def responsive_button(display, color_1, color_2, rectangle, text, mouse_clicked, action=None):
    mouse = pygame.mouse.get_pos()

    #  determine whether button contains mouse
    mouse_in_button = (rectangle[0] < mouse[0] < rectangle[0] + rectangle[2] and rectangle[1] < mouse[1] < rectangle[1] + rectangle[3])
    if (mouse_in_button):
        pygame.draw.rect(display, color_2, rectangle)
    else:
        pygame.draw.rect(display, color_1, rectangle)

    #  determine if clicked
    if (mouse_in_button and mouse_clicked):
        action()

    small_text = pygame.font.Font('freesansbold.ttf', 20)
    text_surf, text_rect = text_objects(text, small_text)
    text_rect.center = ((rectangle[0] + rectangle[2] / 2), rectangle[1] + rectangle[3] / 2)
    gameDisplay.blit(text_surf, text_rect)


menu()

Upvotes: 3

Related Questions