Проблема pygame.mouse.get_pressed()
, которая дает True
все время, когда вы удерживаете кнопку мыши нажатой. Кнопка нажимает на нее как можно больше щелчков, и она выполняет функцию много раз. Используя event
, вы можете поймать момент, когда состояние кнопки изменяется с не нажатой на нажатую, и это будет только один момент, поэтому она будет выполнять функцию только один раз.
Но при использовании события нужно много изменений. Если вы переместите все функции в for event
цикл, тогда он будет запускать действие только один раз, но он также будет рисовать кнопку только один раз - когда вы нажимаете область, где должна быть кнопка.
Простой метод - разделить эту функцию на две функции
action_button_draw
, который только рисует кнопку и использует ее в старом месте
action_button_click
, который только запускает действие и помещает его в for event
цикл
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # 1 = left button, 3 = right button
action_button_click(x, y, w, h, action)
или хотя бы
if event.type == pygame.MOUSEBUTTONDOWN:
action_button_click(x, y, w, h, action)
Функция:
def action_button_click(x, y, w, h, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
if click[0] == 1 and action != None:
action()
def action_button_draw(x, y, w, h, ic, ac, text, text_colour):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(screen, ac,(x,y,w,h))
else:
pygame.draw.rect(screen, ic,(x,y,w,h))
font = pygame.font.SysFont("arial black",20)
text = font.render(text,True,(text_colour))
screen.blit(text,[x+w/2-(text.get_rect().w/2),y+h/2-(text.get_rect().h/2)])
Минимальный рабочий пример:
import pygame
# --- constants ---
WIDTH = 640
HEIGHT = 480
FPS = 5
# --- functions ---
def action_button_click(x, y, w, h, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
if click[0] == 1 and action != None:
action()
def action_button_draw(x, y, w, h, ic, ac, text, text_colour):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(screen, ac,(x,y,w,h))
else:
pygame.draw.rect(screen, ic,(x,y,w,h))
font = pygame.font.SysFont("arial black",20)
text = font.render(text,True,(text_colour))
screen.blit(text,[x+w/2-(text.get_rect().w/2),y+h/2-(text.get_rect().h/2)])
def test_action():
print("clicked")
# --- main ---
# - init -
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen_rect = screen.get_rect()
# - mainloop -
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
# MOUSEBUTTONDOWN is created only once,
# when button changes state from "not-pressed" to "pressed"
# so it is better for this job than "pygame.mouse.get_pressed()"
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
action_button_click(100, 100, 100, 50, test_action)
# --- draws ----
screen.fill([0,0,0]) # clear screen
action_button_draw(100, 100, 100, 50, [255,0,0], [0,255,0], "Hello", [0,0,0])
pygame.display.flip()
# - FPS -
clock.tick(FPS)
# - end -
pygame.quit()
Эти две функции вы также можете поместить в класс и использовать класс, как в example-class.py
Оригинальная функция работает хорошо только в том случае, если выполненное действие удаляет кнопку из этого региона (т. Е. Удаляет меню и запускает игру), но имеет проблему, когда кнопка остается на том же месте после нажатия или вы помещаете новую кнопку в то же место (т.е. при переходе от меню к опциям, в которых кнопка находится там же)