Erik Rosolov
Erik Rosolov

Reputation: 61

Pygame How do you reveal an image under a tile?

So I was trying to cover a series of images with a cover image and reveal them upon clicking on the tile. However there is no change at all. I tried changing 'self.content' within a function but to no avail. This is my code so far:


import pygame,os,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('Memory V2')  
   # 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

      # === objects that are part of every game that we will discuss
      self.surface = surface
      self.bg_color = pygame.Color('black')
      self.timer=0
      self.FPS = 60
      self.game_Clock = pygame.time.Clock()
      self.close_clicked = False
      self.continue_game = True
      self.cover=pygame.image.load('image0.bmp')
      # === game specific objects
      self.board = []
      #4 x 4 grid
      self.board_size = 4
      self.create_board()
   def create_board(self):
      Tile.set_surface(self.surface)
      self.images=[]
      #concatenate the images twice         
      for image in os.listdir('images'):
         memory_images=pygame.image.load(image)#image is type surface, it becomes the surface
         self.images.append(memory_images)
         self.images.append(memory_images)
      random.shuffle(self.images)

      #reference for the size of images
      sample = pygame.image.load('image1.bmp')
      width = sample.get_width()
      height = sample.get_height()
      #count for all 16 images
      count=0
      #Create three rows containing 4 columns each
      for row_index in range(0, self.board_size):
         row = []
         #Create 4 images for row
         for col_index in range(0,self.board_size):
            x = width * col_index
            y = height * row_index
            tile = Tile(x,y,self.images[count])
            count=count+1
            row.append(tile)
         self.board.append(row)
   def draw_cover(self):
      pass


   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:  # until player clicks close box
         # play frame
         self.handle_events()
         self.draw()            
         if self.continue_game:
            self.update()
            self.decide_continue()
         self.game_Clock.tick(self.FPS) # run at most with FPS Frames Per Second
   def draw_timer(self):
      # 1. Set the color
      fg_color = pygame.Color('white')
      # 2.create the font object
      font = pygame.font.SysFont('',70)
      # 3 Create a text box by rendering the font
      text_string =  str(self.timer)
      text_box = font.render(text_string,True,fg_color,self.bg_color)
      # 4 Compute the location of the text box
      location = (430,0)
      # 5 Blit or pin the text box on the surface
      Tile.surface.blit(text_box,location) 


   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:
         if event.type == pygame.QUIT:
            self.close_clicked = True
         if event.type==pygame.MOUSEBUTTONUP:
            self.handle_mouse_up(event)
   def handle_mouse_up(self,event):
      for row in self.board:
         for tile in row:
            valid_click=tile.select(event.pos)
            if valid_click == True:
               self.content=self.images

   def draw(self):
      # Draw all game objects.
      # - self is the Game to draw
      self.draw_timer()
      self.surface.fill(self.bg_color) # clear the display surface first
      # Draw the tiles
      for each_row in self.board:
         for each_tile in each_row:
            each_tile.draw()
      pygame.display.update() # make the updated surface appear on the display

   def update(self):
      # Update the game objects for the next frame.
      # - self is the Game to update
      pass
   def decide_continue(self):
      # Check and remember if the game should continue
      # - self is the Game to check
      pass


class Tile:
   # An object in this class represents a Dot that moves
   # Shared Attrbutes or Class Attributes
   surface = None
   border_size = 10
   border_color = pygame.Color('black')
   @classmethod
   def set_surface(cls,game_surface):
      cls.surface = game_surface
   # Instance Methods
   def __init__(self,x,y,image):
      self.image = image
      width = self.image.get_width()
      height = self.image.get_height()
      self.rect = pygame.Rect(x,y,width,height)
      self.content=pygame.image.load('image0.bmp')
   def draw(self):
      # Draw the dot on the surface
      # - self is the Dot
      pygame.draw.rect(Tile.surface,Tile.border_color,self.rect,Tile.border_size)
      Tile.surface.blit(self.content,self.rect)
   def select(self, position):
      valid_click = False
      if self.rect.collidepoint(position):
         if self.content == pygame.image.load('image0.bmp'):
            valid_click=True

      return valid_click      

main()

Can somebody point out what's wrong in here? Am I really inputting the hidden images in the proper way?

Upvotes: 1

Views: 334

Answers (1)

Kingsley
Kingsley

Reputation: 14906

The code should just set the appropriate .image in Tile, then when the tile is re-painted, it can draw with the appropriate image, depending on whether the base-image is hidden or revealed. I like to set everything up in the __init()__, and then manipulate it depending on the "state" of the object.

The Tile.set_surface() kind-of goes about the operation indirectly because it takes a Tile Object and a Surface to work on. This is can be simplified a bit.

class Tile:
   # An object in this class represents a Dot that moves
   surface = None
   border_size = 10
   border_color = pygame.Color('black')

   def __init__( self, x, y, base_image, cover_image ):
      self.hidden   = base_image            # The hidden image
      self.cover    = cover_image           # The "covering" image
      self.image    = self.cover            # Start covered
      self.rect     = self.image.get_rect() # rect size of image
      self.rect.x   = x
      self.rect.y   = y
      self.revealed = False                 # Not revealed yet

   def reveal( self ):
       self.revealed = True
       cx, cy        = self.rect.center       # preserve image centre
       self.image    = self.base_image        # swap the base/cover image
       self.rect     = self.image.get_rect()
       # Re-position about the centre (in case the size is different)
       self.rect.center = ( cx, cy )

   def reset( self ):
       # Go back to un-revealed state (for whatever reason)
       self.revealed = False
       cx, cy        = self.rect.center      # preserve image centre
       self.image    = self.cover_image      # swap the base/cover image
       self.rect     = self.image.get_rect()
       # Re-position about the centre (in case the size is different)
       self.rect.center = ( cx, cy )

   def draw( self, screen ):
       # Draw the dot on the given surface
       pygame.draw.rect( screen, Tile.border_color, self.rect, Tile.border_size )
       screen.blit( self.image, self.rect )

   def select(self, position):
      # If the tile is clicked on, revel itself
      valid_click = False
      if self.rect.collidepoint( position ):
          if not self.revealed:
              self.reveal()        # Tile was clicked, reveal if not already
              valid_click = True   # Only a valid click if reveals something
      return valid_click       

Upvotes: 1

Related Questions