用pygame实现的一个类似于翻翻看的游戏,你需要安装python2.7(http://www.python.org/download/)和pygame(http://www.pygame.org/)才能运行它。代码受《Making Games with Python and Pygame》启发很大(http://inventwithpython.com/pygame/index.html)。
程序第一个版本是基于过程的,第二个版本基本上按照面向对象设计,但感觉boxs的设计不是很好,需要后续优化,另外一些Animiation做的不是很流畅,有锯齿的感觉,希望可以有人不吝赐教。
贴上主要源码,并附上下载链接:http://files.cnblogs.com/sayhellototheworld/MemoryPuzzle.rar
1 #coding=utf-8 2 from pygame.locals import * 3 from pygame import Surface 4 import pygame 5 import sys 6 import random 7 from memorypuzzle_constants import * 8 ''' 9 Things learned: 10 1. a surface rect's top and left value are the relative numbers to the surface on which it is blitted 11 ''' 12 class Game(): 13 BASICFONT = None 14 FPSCLOCK = None 15 boxs = None 16 lives = None 17 @staticmethod 18 def font_init(): 19 Game.BASICFONT = pygame.font.Font(FONTPATH, BASICFONTSIZE) 20 @staticmethod 21 def clock_init(): 22 Game.FPSCLOCK = pygame.time.Clock() 23 @staticmethod 24 def boxs_init(): 25 Game.boxs = [] 26 for i in range(NUMBOXHORIZONTAL): 27 vert_boxs = [] 28 x = BOXMARGINWIDTH 29 x += i * (BOXWIDTH + GAPBETBOXS) 30 for j in range(NUMBOXVERTIVAL): 31 y = BOXMARGINHEIGHT 32 y += j * (BOXHEIGHT + GAPBETBOXS) 33 box = Box(x,y,BOXWIDTH,BOXHEIGHT) 34 box.boxx = i 35 box.boxy = j 36 vert_boxs.append(box) 37 Game.boxs.append(vert_boxs) 38 39 40 @staticmethod 41 def game_init(): 42 pygame.init() 43 Game.font_init() 44 Game.clock_init() 45 Game.boxs_init() 46 Game.lives = LIVES 47 48 @staticmethod 49 def shuffle_boxs_color(): 50 global ALLCOLORS 51 num_colors_need = NUMBOXHORIZONTAL * NUMBOXVERTIVAL / 2 52 assert num_colors_need == NUMBOXHORIZONTAL * NUMBOXVERTIVAL / 2.0 53 colors = ALLCOLORS[:] 54 random.shuffle(colors) 55 colors = colors[:num_colors_need] 56 colors = colors * 2 57 random.shuffle(colors) 58 for i in range(NUMBOXHORIZONTAL): 59 for j in range(NUMBOXVERTIVAL): 60 Game.boxs[i][j].color = colors[0] 61 Game.boxs[i][j].surf.fill(colors[0]) 62 del colors[0] 63 @staticmethod 64 def draw_boxs(DISPLAYSURF): 65 for i in range(NUMBOXHORIZONTAL): 66 for j in range(NUMBOXVERTIVAL): 67 if Game.boxs[i][j].is_revealed == True: 68 DISPLAYSURF.blit(Game.boxs[i][j].surf,(XRBW(Game.boxs[i][j].x),YRBW(Game.boxs[i][j].y))) 69 @staticmethod 70 def draw_covers(DISPLAYSURF,coverage): 71 for i in range(NUMBOXHORIZONTAL): 72 for j in range(NUMBOXVERTIVAL): 73 if Game.boxs[i][j].is_revealed == False: 74 Game.boxs[i][j].set_surf_color(COVERCOLOR) 75 DISPLAYSURF.blit(Game.boxs[i][j].surf,(XRBW(Game.boxs[i][j].x),YRBW(Game.boxs[i][j].y))) 76 @staticmethod 77 def anim_reveal(surface,boxx,boxy): 78 i = boxx 79 j = boxy 80 Game.boxs[i][j].set_surf_color(Game.boxs[i][j].color) 81 for coverage in range(BOXWIDTH, -1, -REVEALSPEED): 82 if coverage >=0: 83 draw_a_cover(surface,Game.boxs, boxx, boxy, coverage) 84 @staticmethod 85 def anim_cover(surface,first_select,boxx,boxy): 86 for coverage in range(0, BOXWIDTH+1, REVEALSPEED): 87 if coverage >=0: 88 draw_a_cover(surface,Game.boxs, first_select.boxx, first_select.boxy, coverage) 89 draw_a_cover(surface,Game.boxs, boxx, boxy, coverage) 90 @staticmethod 91 def reset(): 92 Game.lives = LIVES 93 for i in range(NUMBOXHORIZONTAL): 94 for j in range(NUMBOXVERTIVAL): 95 Game.boxs[i][j].is_revealed = False 96 @staticmethod 97 def wait(msec): 98 pygame.time.wait(msec) 99 100 class GameSurface(pygame.Surface): 101 def __init__(self,width,height,left,top,color): 102 super(GameSurface,self).__init__((width,height)) 103 self.left = left 104 self.top = top 105 self.color = color 106 def set_lefttop(self,left,top): 107 self.left = left 108 self.top = top 109 def get_lefttop(self): 110 return self.left, self.top 111 def draw_on(self,surface): 112 self.fill(self.color) 113 surface.blit(self,self.get_lefttop()) 114 def update(self): 115 Screen.update() 116 117 class Text(): 118 def __init__(self,text, color, bgcolor, left, top,BASICFONT): 119 self.text = text; self.color = color; self.bgcolor = bgcolor; self.top = top; self.left = left; self.BASICFONT = BASICFONT 120 self.text_surf = self.BASICFONT.render(self.text,True,self.color,self.bgcolor) 121 self.text_rect = self.text_surf.get_rect() 122 def make_text(self): 123 self.text_rect.topleft = (self.left,self.top) 124 return self.text_surf, self.text_rect 125 def change_text(self,new_text): 126 self.text = new_text 127 self.text_surf = self.BASICFONT.render(self.text,True,self.color,self.bgcolor) 128 def draw_on(self,surface): 129 surface.blit(self.text_surf,(self.left,self.top)) 130 131 class BarSurface(GameSurface): 132 dict_texts = {} 133 def add_text(self,text): 134 self.dict_texts[id(text)]=text.make_text() 135 def draw_on(self,surface): 136 self.fill(self.color) 137 for key in self.dict_texts: 138 self.blit(self.dict_texts[key][0],self.dict_texts[key][1]) 139 surface.blit(self,self.get_lefttop()) 140 141 142 class Screen(GameSurface): 143 def __init__(self): 144 pass 145 @staticmethod 146 def get_screen(): 147 return pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT)) 148 @staticmethod 149 def update(): 150 pygame.display.update() 151 152 class Box: 153 def __init__(self,x,y,width=BOXWIDTH,height=BOXHEIGHT,image=None): 154 self.x = x 155 self.y = y 156 self.width = width 157 self.height = height 158 self.image = image 159 self.surf = Surface((self.width,self.height)) 160 self.color = WHITE 161 self.surf.fill(self.color) 162 self.is_revealed = False 163 self.cover_color = COVERCOLOR 164 self.boxx = 0 165 self.boxy = 0 166 167 def set_cord(self,x,y): 168 self.x = x 169 self.y = y 170 171 def set_image(self,image): 172 self.image = image 173 174 def set_surf(self,surf): 175 self.surf = surf 176 def set_surf_color(self,color): 177 self.surf.fill(color) 178 179 180 def x_relative_board_to_window(x): 181 return x + BOARDLEFT 182 183 def y_relative_board_to_window(y): 184 return y + BOARDTOP 185 186 def XRBW(x): 187 return x_relative_board_to_window(x) 188 def YRBW(y): 189 return y_relative_board_to_window(y) 190 191 def draw_boxs(DISPLAYSURF,BOARD,boxs): 192 for i in range(NUMBOXHORIZONTAL): 193 for j in range(NUMBOXVERTIVAL): 194 if boxs[i][j].is_revealed == True: 195 DISPLAYSURF.blit(boxs[i][j].surf,(XRBW(boxs[i][j].x),YRBW(boxs[i][j].y))) 196 197 198 def get_box_pixel_topleft(boxs,mousex,mousey): 199 for i in range(NUMBOXHORIZONTAL): 200 for j in range(NUMBOXVERTIVAL): 201 box_rect = pygame.Rect(XRBW(boxs[i][j].x),YRBW(boxs[i][j].y),BOXWIDTH,BOXHEIGHT) 202 if box_rect.collidepoint(mousex,mousey): 203 return box_rect.top,box_rect.left 204 return None,None 205 206 def get_box_x_y(boxs,mousex,mousey): 207 for i in range(NUMBOXHORIZONTAL): 208 for j in range(NUMBOXVERTIVAL): 209 box_rect = pygame.Rect(XRBW(boxs[i][j].x),YRBW(boxs[i][j].y),BOXWIDTH,BOXHEIGHT) 210 if box_rect.collidepoint(mousex,mousey): 211 return (i,j) 212 return (None,None) 213 214 def anim_highlight_box(DISPLAYSURF,boxs,box_pixel_topleft): 215 top = box_pixel_topleft[0] 216 left = box_pixel_topleft[1] 217 pygame.draw.rect(DISPLAYSURF, HIGHLIGHTCOLOR, (left - 5, top - 5, BOXWIDTH + 10, BOXHEIGHT + 10), 4) 218 219 220 221 def init_boxs_pixel_x_y_relative_BOARD(): 222 boxs = [] 223 for i in range(NUMBOXHORIZONTAL): 224 vert_boxs = [] 225 x = BOXMARGINWIDTH 226 x += i * (BOXWIDTH + GAPBETBOXS) 227 for j in range(NUMBOXVERTIVAL): 228 y = BOXMARGINHEIGHT 229 y += j * (BOXHEIGHT + GAPBETBOXS) 230 box = Box(x,y,BOXWIDTH,BOXHEIGHT) 231 box.boxx = i 232 box.boxy = j 233 vert_boxs.append(box) 234 boxs.append(vert_boxs) 235 return boxs 236 237 def draw_covers(DISPLAYSURF,BOARD,boxs,coverage): 238 for i in range(NUMBOXHORIZONTAL): 239 for j in range(NUMBOXVERTIVAL): 240 if boxs[i][j].is_revealed == False: 241 boxs[i][j].set_surf_color(COVERCOLOR) 242 DISPLAYSURF.blit(boxs[i][j].surf,(XRBW(boxs[i][j].x),YRBW(boxs[i][j].y))) 243 244 245 246 def draw_a_cover(surface,boxs,boxx,boxy,coverage): 247 #要有动画效果的话,底层总是要先画一下 248 pygame.draw.rect(surface, boxs[boxx][boxy].color, (XRBW(boxs[boxx][boxy].x), YRBW(boxs[boxx][boxy].y), BOXWIDTH, BOXHEIGHT)) 249 pygame.draw.rect(surface, COVERCOLOR, (XRBW(boxs[boxx][boxy].x), YRBW(boxs[boxx][boxy].y), coverage, BOXHEIGHT)) 250 Screen.update() 251 Game.FPSCLOCK.tick(FPS) 252 253 254 def anim_reveal(surface,boxs,boxx,boxy): 255 i = boxx 256 j = boxy 257 boxs[i][j].set_surf_color(boxs[i][j].color) 258 for coverage in range(BOXWIDTH, -1, -REVEALSPEED): 259 if coverage >=0: 260 draw_a_cover(surface,boxs, boxx, boxy, coverage) 261 262 def anim_cover(surface,boxs,first_select,boxx,boxy): 263 for coverage in range(0, BOXWIDTH+1, REVEALSPEED): 264 if coverage >=0: 265 draw_a_cover(surface,boxs, first_select.boxx, first_select.boxy, coverage) 266 draw_a_cover(surface,boxs, boxx, boxy, coverage) 267 268 269 def is_won(boxs): 270 for i in range(NUMBOXHORIZONTAL): 271 for j in range(NUMBOXVERTIVAL): 272 if boxs[i][j].is_revealed == False: 273 return False 274 return True 275 276 277 def main(): 278 Game.game_init() 279 DISPLAYSURF = Screen.get_screen() 280 BOARD = GameSurface(BOARDWIDTH,BOARDHEIGHT,BOARDLEFT,BOARDTOP,GRAY) 281 BAR = BarSurface(BARWIDTH,BARHEIGHT,BARLEFT,BARTOP,BLACK) 282 LIVES_text = Text('LIVES:', GREEN, BLUE,20,0,Game.BASICFONT) #20 is a relative number cus the text is blit on BOARD,not DISPLAYSURF 283 BAR.add_text(LIVES_text) 284 lives_text = Text(str(Game.lives), GREEN, BLUE,80,0,Game.BASICFONT) 285 BAR.add_text(lives_text) 286 BAR.draw_on(DISPLAYSURF) 287 Game.shuffle_boxs_color() 288 mousex,mousey = 0,0 289 first_select = None 290 291 youwon_text = Text("You won", GREEN, BLUE,WINDOWWIDTH/2,WINDOWHEIGHT/2,Game.BASICFONT) 292 youlose_text = Text("You lose", GREEN, BLUE,WINDOWWIDTH/2,WINDOWHEIGHT/2,Game.BASICFONT) 293 294 while True: 295 BOARD.draw_on(DISPLAYSURF) 296 mouse_clicked = False 297 for event in pygame.event.get(): 298 if event.type == QUIT: 299 pygame.quit() 300 sys.exit() 301 elif event.type == MOUSEMOTION: 302 mousex, mousey = event.pos 303 elif event.type == MOUSEBUTTONUP: 304 mousex, mousey = event.pos 305 mouse_clicked = True 306 box_pixel_topleft = get_box_pixel_topleft(Game.boxs,mousex,mousey) 307 if box_pixel_topleft != (None,None): 308 anim_highlight_box(DISPLAYSURF,Game.boxs,box_pixel_topleft) 309 (boxx,boxy) = get_box_x_y(Game.boxs,mousex,mousey) 310 Game.draw_boxs(DISPLAYSURF) 311 Game.draw_covers(DISPLAYSURF,0) 312 if mouse_clicked == True and (boxx,boxy) != (None,None): 313 if Game.boxs[boxx][boxy].is_revealed != True: 314 Game.lives -= 1 315 lives_text.change_text(str(Game.lives)) 316 BAR.add_text(lives_text) 317 BAR.draw_on(DISPLAYSURF) 318 if first_select == None: 319 Game.boxs[boxx][boxy].is_revealed = True 320 first_select = Game.boxs[boxx][boxy] 321 Game.anim_reveal(DISPLAYSURF,boxx,boxy) 322 else: 323 Game.anim_reveal(DISPLAYSURF,boxx,boxy) 324 if first_select.color == Game.boxs[boxx][boxy].color: 325 Game.boxs[boxx][boxy].is_revealed = True 326 else: 327 Game.anim_cover(DISPLAYSURF,first_select,boxx,boxy) 328 first_select.is_revealed = False 329 Game.boxs[boxx][boxy].is_revealed = False 330 first_select = None 331 if is_won(Game.boxs): 332 youwon_text.draw_on(DISPLAYSURF) 333 Screen.update() 334 lives_text.change_text(str(LIVES)) 335 BAR.add_text(lives_text) 336 BAR.draw_on(DISPLAYSURF) 337 Game.wait(1000) 338 Game.reset() 339 if Game.lives <1: 340 youlose_text.draw_on(DISPLAYSURF) 341 Screen.update() 342 lives_text.change_text(str(LIVES)) 343 BAR.add_text(lives_text) 344 BAR.draw_on(DISPLAYSURF) 345 Game.wait(1000) 346 Game.reset() 347 Screen.update() 348 Game.FPSCLOCK.tick(FPS) 349 350 if __name__ == '__main__': 351 main()