In my code:
class text:
def __init__(self, size, message, color, position, button = False, action = None):
self.size = size
self.message = message
self.color = color
self.position = position
self.text_size = pygame.font.SysFont(None, int(size*displaywidth))
self.Textsurface = self.text_size.render(self.message, True, self.color)
Textrect = self.Textsurface.get_rect()
self.Textrect = Textrect
self.Textwidth = Textrect[2]
self.Textheight = Textrect[3]
self.second_x_pos = Textrect[2] + position[0]
self.second_y_pos = Textrect[3] + position[1]
self.button = button
self.action = action
def display(self):
self.Textrect.topleft = (self.position)
gameWindow.blit(self.Textsurface, self.Textrect)
if self.button == True:
self.Textrect.topleft = (self.position)
gameWindow.blit(self.Textsurface, self.Textrect)
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
if self.position[0] < event.pos[0] < self.second_x_pos and self.position[1] < event.pos[1] < self.second_y_pos:
print("yee")
self.color = white
self.Textsurface = self.text_size.render(self.message, True, self.color)
gameWindow.blit(self.Textsurface, self.Textrect)
else:
self.Textsurface = self.text_size.render(self.message, True, self.color)
if event.type == pygame.MOUSEBUTTONUP :
self.action()
# menu screen
def menu_screen():
global wine
global purple
menu = True
global displaywidth
global displayheight
global gameWindow
global compltely_red
global brown
global red
# Texts
menu_txt = text(0.2,"Timm", red, (displaywidth/2,displayheight/9))
Play_txt = text(0.04, "Play ", wine, (displaywidth/7, displayheight/1.5), True, game_loop)
parallel_button = displaywidth - (displaywidth/7) - Play_txt.Textwidth
Quit_txt = text(0.04, "Quit ", compltely_red, (parallel_button, displayheight/1.5), True, quit_Everything)
#loop
while menu == True:
#the loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_Everything()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quit_Everything()
if event.key == pygame.K_f:
displaywidth = 1920
displayheight = 1080
gameWindow = pygame.display.set_mode((displaywidth,displayheight), pygame.FULLSCREEN)
if event.key == pygame.K_g:
displaywidth = 960
displayheight = 960
gameWindow = pygame.display.set_mode((displaywidth,displayheight))
gameWindow.fill(green)
menu_txt.display()
Play_txt.display()
Quit_txt.display()
pygame.display.update()
The first button that I call (The "Play" button) works perfectly (I am not yet concerned about the actions, what matters to me at the moment is the hovering). But the second button is very glitchy (when I inverted the order of how I called the buttons, the first one being called always works perfectly)
First thing there: there is no pause between the "frames" - i.e. the checking of events in your program - so everything is done as fast as the computer can carry it, using 100% of CPU - worse choice. The correct thing is to wait some tens of milliseconds after the call to pygame.display.update
- place a call like pygame.time.delay(30)
immediately after that one.
The code you get there, though having a bad design, almost works, but for one thing - when you call pygame.event.get
it fetches all events on the queue. So, there is some race condition n which the call to get
on your mainloop pick all events - but due to the no-pausing nature of your code, some MOUSEMOTION events are picked by the second call, in the display
method for the first button.
When you place the pause I've advised above, even the hovering for the first button should stop - as it is works just by chance how it is, and the pause between frames will fix that chance.
Now, you have two options - if you want to keep checking events in the code in the objects, they should not call pygame.events.get
themselves - instead, make a single call to this on each frame, and assign the result to a variable - them pass that variable as parameter to all places events should be handled:
On the menu screen code do:
while menu: #
#the loop
events = pygame.event.get()
for event in events:
...
gameWindow.fill(green)
menu_txt.display(events)
Play_txt.display(events)
Quit_txt.display(events)
And on the text class:
def display(self, events):
...
if self.button: # Please, just stop checking truthiness doing "x == True"
self.Textrect.topleft = (self.position)
gameWindow.blit(self.Textsurface, self.Textrect)
for event in events:
if event.type == pygame.MOUSEMOTION:
That should fix your problem and a lot of things on your design. However, note that these will only highlight your text if the mouse actually moves - if it is hovering, but without moving, no MOUSEMOTION events will be generated.
So you might check if the mouse position itself is inside the button rect, instead of checking for events - you get the mouse position directly, instead of depending on an event. Also, while at it, you might prefer to use Pygame's rectangle calculation functions instead of the unpleasant to the eyes self.position[0] < event.pos[0] < self.second_x_pos and self.position[1] < event.pos[1] < self.second_y_pos
expression.
On __init__
:
self.rect = pygame.Rect(self.pos + tuple(Textrect[2:])
And on the if
to check if the pointer is inside the rect:
def display(self, events):
if self.button:
if self.rect.contains(pygame.mouse.get_pos() + (1,1)):
print("yee")
...