Reputation: 370
I'm creating a button class for a game, and I'm using the pygame event loop to detect mouse clicks (specifically when the mouse is released) (I hear it is better the method of using pygame.mousemget_pressed()[0]
). However, the event loop seems to be slow, not responding and performing the buttons function when it is clicked. I think it may be because relate to how I created the event loop in a class, but I'm not sure. Here's a sample of my code:
class Button:
"""A Button class, built for all kinds of purposes"""
def __init__(self, window, rect, message, off_color, on_color, message_color, message_font_size):
pass # just a bunch of variables that use the parameters given
def in_button(self):
mouse_pos = pygame.mouse.get_pos()
if pygame.Rect(self.rect).collidepoint(mouse_pos):
return True
def clicked(self):
if self.in_button():
pygame.event.pump()
for e in pygame.event.get():
if e.type == pygame.MOUSEBUTTONUP:
return True
# I proceed to create 5 instances using this class.
I removed some unnecessary method information in my code. If you need anything more, please help me.
Upvotes: 1
Views: 816
Reputation: 20438
You have to implement the clicked
method in a different way, because there should be only one event loop in your application, not one in every button instance. pygame.event.get()
empties the event queue, so calling it multiple times per frame will cause problems.
I suggest to pass the events to the buttons. In this (very simple) example I pass the pygame.MOUSEBUTTONDOWN
events to the clicked
method and then check if the event.pos
(mouse position) of the event collides with the rect. If it returns True
, I do something in the event loop in the main function.
import pygame as pg
class Button:
def __init__(self, pos):
self.image = pg.Surface((100, 40))
self.image.fill(pg.Color('dodgerblue1'))
self.rect = self.image.get_rect(center=pos)
def clicked(self, event):
"""Check if the user clicked the button."""
# pygame.MOUSE* events have an `event.pos` attribute, the mouse
# position. You can use `pygame.mouse.get_pos()` as well.
return self.rect.collidepoint(event.pos)
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
button = Button((100, 60))
number = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEBUTTONDOWN:
# Pass the MOUSEBUTTONDOWN event to the buttons.
if button.clicked(event):
number += 1 # Do something.
print('clicked', number)
screen.fill((30, 30, 30))
screen.blit(button.image, button.rect)
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
If you want a button with several images, you can use something similar to the button class here (the first addendum) or search for more sophisticated Button classes for pygame.
Upvotes: 1