How to create a memory puzzle game with Python and Pygame (#006)

 Now, we are gonna develop our several missing functions. 

First,

import math
# check if player has clicked on the squares
# if player clicked on a square, return the square index such as (3,4)
# it takes the mouse's x and y pos and calculate the square index from it
# we calculate the distance between the (x,y) and each of all the square positions
# if there is a distance less than 25, that square index is returned, otherwise
# returns None
def check_click(x,y, square_pos):
      for i in range(6):
            for j in range(6):
                  distance = math.sqrt(
                        (square_pos[i][j][0]-x)**2+
                        (square_pos[i][j][1]-y)**2)
                  if distance <= 25:
                        return (i,j)
      return None

How do we check a valid click?

As you can see from the picture above, if we click within the black circle area, we will make a valid click. So as long as the distance between the click point and the center point of the green square is less than 25 pixels, we will return the board position. Because there 36 of them, so we need to check everyone of them to find the right position. If there is no such position in the square_pos list, it returns None.

How to calculate the distance between two points within the game screen?

If the click point is (x1, y1) and the center point of the square is (x2, y2), then the distance between two points is:

math.sqrt((x2-x1)**2 + (y2-y1)**2)

Second,

def compare_two_pos(pos1, pos2, board):
      if board[pos1[0]][pos1[1]] == board[pos2[0]][pos2[1]]:
            return True
      else:
            return False

In this function, we compare two positions' letters to each other, if letters matched, return True, otherwise return False.

Third,

def draw_pos_matched(pos, pos_to_compare, square_pos, board):
      # draw all the squares on the screen
      initialize_board(square_pos)
      
      for p in pos:
            s = text_font.render(board[p[0]][p[1]], True, WHITE)
            screen.blit(s,
                        (square_pos[p[0]][p[1]][0]-25, square_pos[p[0]][p[1]][1]-25)
                        )
      for p in pos_to_compare:
            s = text_font.render(board[p[0]][p[1]], True, WHITE)
            screen.blit(s,
                        (square_pos[p[0]][p[1]][0]-25, square_pos[p[0]][p[1]][1]-25)

With this function, we first draw all the green squares on the screen by just invoking the initialize_board() function.  

Then we draw all the patterns inside the pos_matched list and draw all the patterns inside the pos_to_compare_list if any.


s = text_font.render(board[p[0]][p[1]], True, WHITE)
screen.blit(s,(square_pos[p[0]][p[1]][0]-25, square_pos[p[0]][p[1]][1]-25))

Use our pre-defined text_font Font object to render all the letters to be drawn. Then use the blit() method of the Surface object namely screen to blit the text at the right place. 


(square_pos[p[0]][p[1]][0]-25, square_pos[p[0]][p[1]][1]-25)

As you can see, the second argument of the blit() method is a tuple of two elements representing the top-left corner coordinates of the square. Remember, the square_pos list contains the center point coordinates of the squares, you need to minus 25 to get the top-left corner coordinates.

In the end, the final code should look like this:


# puzzle game created by pete
# it is free to redistribute or modify the source code

import pygame, sys, random, math, time
from pygame.locals import *

def board(patterns):
      # create the data structure for the game board
      board = []
      c = 0
      for i in range(6):
            board.append([])
            for j in range(6):
                  board[i].append(patterns[c])
                  c += 1
      return board

def initialize_drawing_pos(start_p):
      # create the drawing coordinates data structure
      # coresponding to the game board
      # the starting drawing pos is (145, 65)
      # the square is a 50*50 pixels
      # the space between each boxes is 10 pixels
      starting_pos = start_p
      step = 60
      square_pos = []
      for i in range(6):
            square_pos.append([])
            for j in range(6):
                  square_pos[i].append((starting_pos[0]+25+60*j, starting_pos[1]+25+60*i))
      return square_pos


def initialize_board(square_pos):
      # draw all the squares on the screen
      for i in range(6):
            for j in range(6):
                  pygame.draw.rect(
                        screen, # surface to draw upon
                        (0,255,0), # square fill color
                        (square_pos[i][j][0]-25, square_pos[i][j][1]-25, 50, 50))# square rect


# check if player has clicked on the squares
# if player clicked on a square, return the square index such as (3,4)
# it takes the mouse's x and y pos and calculate the square index from it
# we calculate the distance between the (x,y) and each of all the square positions
# if there is a distance less than 25, that square index is returned, otherwise
# returns None
def check_click(x,y, square_pos):
      for i in range(6):
            for j in range(6):
                  distance = math.sqrt(
                        (square_pos[i][j][0]-x)**2+
                        (square_pos[i][j][1]-y)**2)
                  if distance <= 25:
                        return (i,j)
      return None

def compare_two_pos(pos1, pos2, board):
      if board[pos1[0]][pos1[1]] == board[pos2[0]][pos2[1]]:
            return True
      else:
            return False

def draw_pos_matched(pos, pos_to_compare, square_pos, board):
      # draw all the squares on the screen
      initialize_board(square_pos)
      
      for p in pos:
            s = text_font.render(board[p[0]][p[1]], True, WHITE)
            screen.blit(s,
                        (square_pos[p[0]][p[1]][0]-25, square_pos[p[0]][p[1]][1]-25)
                        )
      for p in pos_to_compare:
            s = text_font.render(board[p[0]][p[1]], True, WHITE)
            screen.blit(s,
                        (square_pos[p[0]][p[1]][0]-25, square_pos[p[0]][p[1]][1]-25)
                        )
      
pygame.init()

SCREEN_SIZE = (640,480)

# main screen set up
screen = pygame.display.set_mode(SCREEN_SIZE)
pygame.display.set_caption('Puzzle Game')

# color setup
WHITE = (255,255,255)
screen.fill(WHITE)

patterns = [chr(i) for i in range(65,65+18)]*2
random.shuffle(patterns)

# create Font object
text_font = pygame.font.SysFont('arial', 50)

# create a list that stores two pos that going to compare to each other
pos_to_compare_list = []
# create a list that stores all the pos that matched
pos_matched = []

starting_pos = (145,65)
board = board(patterns)
square_pos = initialize_drawing_pos(starting_pos)
initialize_board(square_pos)
#print(board)
# set backgroud color to white
while True:
      
      for event in pygame.event.get():
            if event.type == QUIT:
                  pygame.quit()
                  sys.exit()
            elif event.type == MOUSEBUTTONDOWN:
                  (x,y) = pygame.mouse.get_pos()
                  pos = check_click(x,y, square_pos)
                  if pos:
                        text_surface = text_font.render(board[pos[0]][pos[1]], True, WHITE)
                        if len(pos_to_compare_list) < 2:
                              if pos not in pos_to_compare_list:
                                    pos_to_compare_list.append(pos)

                              if len(pos_to_compare_list) == 2:
                                    res = compare_two_pos(pos_to_compare_list[0], pos_to_compare_list[1], board)
                                    if res:
                                          pos_matched.extend(pos_to_compare_list)
                                    
                  

      
                                           
      draw_pos_matched(pos_matched, pos_to_compare_list, square_pos, board)

      pygame.display.update()
      
      if len(pos_to_compare_list) == 2:
            time.sleep(1)
            pos_to_compare_list = []

Just run the code above, you could play the game right now. 





Comments

Popular posts from this blog

How to create a memory puzzle game with Python and Pygame (#005)

How to write a slide puzzle game with Python and Pygame (2020 tutorial)

Introduction to multitasking with Python #003 gevent (2020 tutorial)