I came across the Making Games with Python and Pygame textbook / e-book combo by Albert Sweigert. I've enjoyed the first few chapters so much that I want to add this to my bookshelf soon. I haven't read his section on Memory yet, but I decided to give it a try using what I know from sentdex's tutorials.
This game looks like this:
The player clicks on a white tile to expose its symbol. (Ints now, but those could be used as indices to an array of images.) The symbol is text drawn on a surface whose top left corner is lined up with the tile's. (I will center it later.) Each time a tile is revealed it is added to a list. When a tile was clicked on twice, it led to a nasty bug. But I think that's fixed with the check to see if the tile's index is in the list.
Here's the code:
import time
import random
import pygame
pad = 20
nsymb = 4
row,col = 4,4
ntiles = row*col
tile_h,tile_w = 100,100
white = (255,255,255)
disp_h = (row+1) * pad + row * tile_w
disp_w = (col+1) * pad + col * tile_h
disp = pygame.display.set_mode( (disp_h, disp_w) )
pygame.font.init()
font = pygame.font.Font('freesansbold.ttf',115)
clock = pygame.time.Clock()
class Tile:
def __init__(self,i,j,symb):
self.symb = symb
self.reveal = False
self.matched = False
x = (i+1) * pad + i*tile_w
y = (j+1) * pad + j*tile_h
self.rect = pygame.Rect(x,y,tile_w,tile_h)
def hide(self):
self.reveal = False
def show(self):
self.reveal = True
textSurf = font.render(self.__repr__(),True,(255,0,0))
disp.blit(textSurf,self.rect.topleft)
def __repr__(self):
return str(self.symb) if self.reveal else "*"
def refresh(tiles,start=False):
for tile in tiles:
if start or tile.reveal and not tile.matched:
tile.hide()
pygame.draw.rect(disp,white,tile.rect)
def keep(shown,tile,index):
shown.append(index)
tile.matched = True
def end():
pygame.quit()
quit()
def game_loop():
c,r,s = range(col),range(row),range(nsymb)
symbs = [i for i in s for j in range(int(ntiles/nsymb))]
random.shuffle(symbs)
tiles = [Tile(i,j,symbs[i+j*col]) for j in r for i in c]
shown = []
refresh(tiles,True)
while len(shown) < ntiles:
for event in pygame.event.get():
if event.type == pygame.QUIT:
end()
elif event.type == pygame.MOUSEBUTTONDOWN:
loc = event.__dict__['pos']
for i,tile in enumerate(tiles):
if tile.rect.collidepoint(loc):
tile.show()
pygame.display.update()
if i not in shown:
if len(shown) % 2 == 1:
j = shown.pop()
prev = tiles[j]
if tile.symb == prev.symb:
keep(shown,tile,i)
keep(shown,prev,j)
else:
time.sleep(2)
refresh(tiles)
else:
shown.append(i)
pygame.display.update()
clock.tick(30)
end()
game_loop()

No comments:
Post a Comment