Search code examples
pythonpython-3.xpygamemouseeventrect

Trouble updating rect object pygame


I am new to coding and am having trouble with my game. I am wanting the white rectangles to change to a new color when clicked on. If they are not white and they are clicked on they should not change colors. Right now they are just staying white so I am not sure if they are not updating or if my mouse click detection is wrong. Any help is highly appreciated, thanks!

# Color Matching Game
# Click a box when it is white to change it to a random color
# If the two colors match you gain a point

import pygame


# User-defined functions

def main():
   # initialize all pygame modules (some need initialization)
   pygame.init()
   # create a pygame display window
   pygame.display.set_mode((500, 400))
   # set the title of the display window
   pygame.display.set_caption('Color Match')   
   # get the display surface
   w_surface = pygame.display.get_surface() 
   # create a game object
   game = Game(w_surface)
   # start the main game loop by calling the play method on the game object
   game.play() 
   # quit pygame and clean up the pygame window
   pygame.quit() 


# User-defined classes

class Game:
   # An object in this class represents a complete game.

   def __init__(self, surface):
      # Initialize a Game.
      # - self is the Game to initialize
      # - surface is the display window surface object

      # Initializa game
      self.surface = surface
      self.bg_color = pygame.Color('black')
      
      self.FPS = 60
      self.game_Clock = pygame.time.Clock()
      self.close_clicked = False
      self.continue_game = True
      
      # Initialize game specific objects
      self.left_rect = Rect('white', (87.5, 100, 75, 200), self.surface)
      self.right_rect = Rect('white', (337.5, 100, 75, 200), self.surface)
      self.max_frames = 10000
      self.frame_counter = 0
      

   def play(self):
      # Play the game until the player presses the close box.
      # - self is the Game that should be continued or not.

      while not self.close_clicked:
         # play frame
         self.handle_events()
         self.draw()            
         if self.continue_game:
            self.decide_continue()
         self.game_Clock.tick(self.FPS) 
         
   def handle_events(self):
      # Handle each user event by changing the game state appropriately.
      # - self is the Game whose events will be handled

      events = pygame.event.get()
      for event in events:
         
         # Detects if user exits out
         if event.type == pygame.QUIT:
            self.close_clicked = True
         
         # Detects if the user clicks M1
         if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            self.mouse_pos = pygame.mouse.get_pos()
      
               
   def draw(self):
      # Draw all game objects.
      # - self is the Game to draw
      
      self.surface.fill(self.bg_color) # clear the display surface first
      self.left_rect.draw()
      self.right_rect.draw()
      pygame.display.update() # make the updated surface appear on the display

   def decide_continue(self):
      # Check and remember if the game should continue
      # - self is the Game to check
      
      if self.frame_counter > self.max_frames:
         self.continue_game = False


class Rect:
   # An object in this class represents a rect
   
   def __init__(self, rect_color, rect_center, surface):
      # Initialize a rect.
      # - self is the rect to initialize
      # - color is the pygame.Color of the rect
      # - center is a list containing the x and y int coords
      # - surface is the window's pygame.Surface object

      self.color = pygame.Color(rect_color)
      self.center = rect_center
      self.surface = surface
      self.colors = ['red', 'blue', 'green', 'yellow']
   
   def update(self, mouse_pos):
      # Updates rectangle to new colour if it is white and detects a mouse click
      if self.color == 'white' and self.rect.collidepoint(play.mouse_pos):
         self.color = pygame.Color(self.colors[randint(0, 3)])  
      
   
   def draw(self):
      # Draw the rect on the surface
      # - self is the rect
      
      pygame.draw.rect(self.surface, self.color, self.center)


main()

Solution

  • You missed to call the update method:

    class Game:
        # [...]
    
        def handle_events(self):
          # Handle each user event by changing the game state appropriately.
          # - self is the Game whose events will be handled
    
          events = pygame.event.get()
          for event in events:
             
             # [...]
             
             # Detects if the user clicks M1
             if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                self.mouse_pos = pygame.mouse.get_pos()
                self.left_rect.update(self.mouse_pos)                         # <----
                self.right_rect.update(self.mouse_pos)                        # <----
    

    You need to compare the color to a white color rather than to the string 'white':

    self.color == 'white'

    self.color == pygame.Color('white')
    

    collidepoint is a method of pygame.Rect. Hence you need to create a pygame.Rect object:

    import random
    
    class Rect:
        # [...]
    
        def update(self, mouse_pos):
          # Updates rectangle to new colour if it is white and detects a mouse click
          rect = pygame.Rect(self.center)
          if self.color == pygame.Color('white') and rect.collidepoint(mouse_pos):
             self.color = pygame.Color(self.colors[random.randint(0, 3)])  
    

    Complete code:

    # Color Matching Game
    # Click a box when it is white to change it to a random color
    # If the two colors match you gain a point
    
    import pygame
    import random
    
    # User-defined functions
    
    def main():
       # initialize all pygame modules (some need initialization)
       pygame.init()
       # create a pygame display window
       pygame.display.set_mode((500, 400))
       # set the title of the display window
       pygame.display.set_caption('Color Match')   
       # get the display surface
       w_surface = pygame.display.get_surface() 
       # create a game object
       game = Game(w_surface)
       # start the main game loop by calling the play method on the game object
       game.play() 
       # quit pygame and clean up the pygame window
       pygame.quit() 
    
    
    # User-defined classes
    
    class Game:
       # An object in this class represents a complete game.
    
       def __init__(self, surface):
          # Initialize a Game.
          # - self is the Game to initialize
          # - surface is the display window surface object
    
          # Initializa game
          self.surface = surface
          self.bg_color = pygame.Color('black')
          
          self.FPS = 60
          self.game_Clock = pygame.time.Clock()
          self.close_clicked = False
          self.continue_game = True
          
          # Initialize game specific objects
          self.left_rect = Rect('white', (87.5, 100, 75, 200), self.surface)
          self.right_rect = Rect('white', (337.5, 100, 75, 200), self.surface)
          self.max_frames = 10000
          self.frame_counter = 0
          
    
       def play(self):
          # Play the game until the player presses the close box.
          # - self is the Game that should be continued or not.
    
          while not self.close_clicked:
             # play frame
             self.handle_events()
             self.draw()            
             if self.continue_game:
                self.decide_continue()
             self.game_Clock.tick(self.FPS) 
             
       def handle_events(self):
          # Handle each user event by changing the game state appropriately.
          # - self is the Game whose events will be handled
    
          events = pygame.event.get()
          for event in events:
             
             # Detects if user exits out
             if event.type == pygame.QUIT:
                self.close_clicked = True
             
             # Detects if the user clicks M1
             if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                self.mouse_pos = pygame.mouse.get_pos()
                self.left_rect.update(self.mouse_pos)
                self.right_rect.update(self.mouse_pos)
          
                   
       def draw(self):
          # Draw all game objects.
          # - self is the Game to draw
          
          self.surface.fill(self.bg_color) # clear the display surface first
          self.left_rect.draw()
          self.right_rect.draw()
          pygame.display.update() # make the updated surface appear on the display
    
       def decide_continue(self):
          # Check and remember if the game should continue
          # - self is the Game to check
          
          if self.frame_counter > self.max_frames:
             self.continue_game = False
    
    
    class Rect:
       # An object in this class represents a rect
       
       def __init__(self, rect_color, rect_center, surface):
          # Initialize a rect.
          # - self is the rect to initialize
          # - color is the pygame.Color of the rect
          # - center is a list containing the x and y int coords
          # - surface is the window's pygame.Surface object
    
          self.color = pygame.Color(rect_color)
          self.center = rect_center
          self.surface = surface
          self.colors = ['red', 'blue', 'green', 'yellow']
       
       def update(self, mouse_pos):
          # Updates rectangle to new colour if it is white and detects a mouse click
          rect = pygame.Rect(self.center)
          if self.color == pygame.Color('white') and rect.collidepoint(mouse_pos):
             self.color = pygame.Color(self.colors[random.randint(0, 3)])  
          
       
       def draw(self):
          # Draw the rect on the surface
          # - self is the rect
          
          pygame.draw.rect(self.surface, self.color, self.center)
    
    main()