Reputation: 100
I'm having an issue with pygame. I've set up a window that randomly places circles across the screen very quickly, just for testing purposes. There are also three buttons: play/pause (switches back and forth, stops circles from appearing) and an increase speed and decrease speed button. I'm not very experienced with python or pygame, but I've come up with this function to create a clickable button on the screen:
def makeButton(rect, color, hovercolor, text, textsize, textcolor):
clicked = False
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
clicked = True
mouse = pygame.mouse.get_pos()
rect = pygame.Rect(rect)
displaycolor = color
if rect.collidepoint(mouse):
displaycolor = hovercolor
buttonSurface = pygame.draw.rect(gameDisplay, displaycolor, rect, 0)
font = pygame.font.Font('freesansbold.ttf',textsize)
TextSurf = font.render(text, True, textcolor)
TextRect = TextSurf.get_rect()
TextRect.center = rect.center
gameDisplay.blit(TextSurf, TextRect)
if clicked:
return True
else:
return False
This function can definitely be shortened and simplified, but it has worked for me, up until now. I took out a big chunk of code that I realized was useless (having a completely different block of code to render the button when hovered, instead of just changing the display color). Now, whenever I click any of the three previously-mentioned buttons, it seems to pick a random one and return True, messing up the rest of the program. For example, the play button will increase the speed one time, pressing decrease speed will pause, etc. Sometimes it does do what it is supposed to, but it seems to be random.
Some extra info, if it's useful:
-This function is called three times every tick. It's inside a loop, and if it returns true, its corresponding actions are supposed to be performed (pause or play the game, increase/decrease speed)
-The play/pause button is one button that toggles between green with an 'play' arrow, and red with a pause symbol. They are two separate buttons and functions, and only one of them is executed at a time.
-I have almost zero experience with classes, so they may be way better at handling this situation.
-The only explanation I can think of for this problem is that the returned booleans are getting mixed up between the different places this function is used. I'm pretty sure the problem is within this chunk of code, but ask me and I will post the places it is called too.
Upvotes: 0
Views: 781
Reputation: 1321
"pygame.event.get()" takes one event at a time, and *clears it** from the list of events that need to be processed.
So, more specifically, pygame.event.get() returns each event only once.
Take a look at the following code:
clicked = False
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
clicked = True
After this is called, all of the events are removed. Here is an analysis of the code. Assume that there are currently two events that haven't been processed, the first being a key pressed down and the other being a mouse button that's been pressed down.
You should now have a better understanding of how Pygame processes events.
There are also many problems with the function you gave (makeButton). You should find a python tutorial to learn the rest. I suggest a book called "Hello World", by Carter and Warren Sande. The book is kind of out of date (teaches Python 2.5), but its code still works with Python 2.7, and it is one of the few decent Python books I've been able to find.
I have included the code to do what you are trying to do. I don't use Rect objects, but if you want them you can change the code to include them. I also didn't include the text, because I am short on time. Instead of placing random circles, this prints text (to the shell) when buttons are clicked.
import pygame, sys
pygame.init()
screen = pygame.display.set_mode([640,480])
clock = pygame.time.Clock()
buttons = []
#buttons = [[rect, color, hovercolor, hovering, clicked, msg]]
def makeButton(rect, color, hovercolor, text):
global buttons
buttons.append([rect, color, hovercolor, False, False, text])
makeButton([0,0,50,50], [0,127,0], [0,255,0], "Clicked Green")
makeButton([50,0,50,50], [190,190,0], [255,255,0], "Clicked Yellow")
makeButton([100,0,50,50], [0,0,127], [0,0,255], "Clicked Blue")
while 1:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
mousepos = event.pos
for a in range(len(buttons)):
if mousepos[0] >= buttons[a][0][0] and mousepos[0] <= buttons[a][0][0]+buttons[a][0][2] and mousepos[1] >= buttons[a][0][1] and mousepos[1] <= buttons[a][0][1]+buttons[a][0][3]:
buttons[3] = True
else:
buttons[3] = False
if event.type == pygame.MOUSEBUTTONDOWN:
mousepos = event.pos
for a in range(len(buttons)):
if mousepos[0] >= buttons[a][0][0] and mousepos[0] <= buttons[a][0][0]+buttons[a][0][2] and mousepos[1] >= buttons[a][0][1] and mousepos[1] <= buttons[a][0][1]+buttons[a][0][3]:
buttons[4] = True
else:
buttons[4] = False
for a in range(len(buttons)):
if buttons[3] == 0:
pygame.draw.rect(screen, buttons[1], buttons[0])
else:
pygame.draw.rect(screen, buttons[2], buttons[0])
if buttons[4] == 1:
buttons[4] = 0
print buttons[5]
pygame.display.flip()
I haven't had the opportunity to test out the code I just typed (using school computer), but it should work. If there are any problems with the code, just leave a comment and I'll fix it.
Also leave a comment if you don't understand something. Don't give up, you can do it!
Upvotes: 1