1. 游戲功能和流程圖 實現功能:翻開兩個一樣的牌子就顯示,全部翻開游戲結束,設置5種圖形,7種顏色,游戲開始提示隨機8個牌子 游戲流程圖 2. 游戲配置 配置游戲目錄 配置游戲(game_conf.py) 配置顏色(color.py) 配置形狀(shape.py) 3. 游戲使用工具函數(view ...
1. 游戲功能和流程圖
實現功能:翻開兩個一樣的牌子就顯示,全部翻開游戲結束,設置5種圖形,7種顏色,游戲開始提示隨機8個牌子
游戲流程圖
2. 游戲配置
配置游戲目錄
配置游戲(game_conf.py)
FPS=30 #游戲幀數
WINDOW_WIDTH=640 #視窗大小
WINDOW_HEIGHT=480
REVEAL_SPEAD=3 #箱子顯示的速度
BOX_SIZE=40 #箱子的大小寬高相等的正方形
GAP_SIZE=10 #箱子之間的間隔
BOARD_WIDTH=10 #圖標的列數
BOARD_HEIGHT=7 #圖標的行數
assert (BOARD_WIDTH*BOARD_HEIGHT)%2==0,'必須是偶數的棋盤' #檢查語句
X_MARGIN=int((WINDOW_WIDTH-(BOARD_WIDTH*(BOX_SIZE+GAP_SIZE)))/2) #x軸 邊緣空隙
Y_MARGIN=int((WINDOW_HEIGHT-(BOARD_HEIGHT*(BOX_SIZE+GAP_SIZE)))/2) #y軸 邊緣空隙
配置顏色(color.py)
'''游戲顏色'''
GRAY=(100,100,100)
NAVYBLUE=(60,60,100)
WHITE=(255,255,255)
RED=(255,0,0)
GREEN=(0,255,0)
BLUE=(0,0,255)
YELLOW=(255,255,0)
ORANGE=(255,128,0)
PURPLE=(255,0,255)
CYAN=(0,255,255)
配置形狀(shape.py)
DONUT='donut' #圓圈
SQUARE='square' #正方形
DIAMOND='diamond' #鑽石
LINES='lines'#線條
OVAL='oval' #橢圓形
3. 游戲使用工具函數(views.py)
3.1 工具和繪畫類使用模塊和常量
import random
import pygame
from pygame.locals import *
from conf.color import *
from conf.game_conf import *
from conf.shape import *
LIGHTBG_COLOR=GRAY #燈光顏色
BOX_COLOR=WHITE #盒子顏色
HIGHLIGHT_COLOR=BLUE #強調顏色
BG_COLOR=NAVYBLUE #背景顏色
ALL_COLORS=(RED,GREEN,BLUE,YELLOW,ORANGE,PURPLE,CYAN) #顏色元組
ALL_SHAPES=(DONUT,SQUARE,DIAMOND,LINES,OVAL) #形狀元組
3.2 生成游戲數據(游戲坐標,形狀,顏色)
def get_randomized_board():
'''生成所有盒子'''
icons=[]
#生成所有帶顏色的圖標,icons列表
for color in ALL_COLORS:
for shape in ALL_SHAPES:
icons.append((shape,color))
icon_use_number=int(BOARD_HEIGHT*BOARD_WIDTH/2) #所有圖標使用的數量
icons=icons[:icon_use_number]*2
random.shuffle(icons) # 打亂列表圖標
board=[]
#生成坐標
for x in range(BOARD_WIDTH):
column=[] #生成列數
for y in range(BOARD_HEIGHT):
column.append(icons[0]) #給每列添加圖標
del icons[0]
board.append(column)
return board
3.3 用戶的游戲列表(游戲坐標,初始都是空坐標)
def generate_revealed_boxes_data(val):
'''生成翻開盒子初始列表'''
revealed_boxes = []
for i in range(BOARD_WIDTH):
revealed_boxes.append([val] * BOARD_HEIGHT)
return revealed_boxes
3.4 將盒子列表坐標轉化為實際的像素坐標
def left_top_coords_of_box(box_x, box_y):
'''將盒子位置轉化為像素坐標
:param box_x 盒子x坐標
:param box_y 盒子y坐標
:return 返回屏幕坐標'''
left = box_x * (BOX_SIZE + GAP_SIZE) + X_MARGIN
top = box_y * (BOX_SIZE + GAP_SIZE) + Y_MARGIN
return (left, top)
3.5 根據坐標返回對應的形狀和顏色
def get_shape_and_color(board, box_x, box_y):
'''獲取對應坐標 形狀和顏色
:param board 游戲板塊坐標列表
:param box_x 盒子x坐標
:param box_y 盒子y坐標
:return 返回形狀,顏色'''
#board[box_x][box_y][0] 形狀,board[box_x][box_y][1]顏色
return board[box_x][box_y][0], board[box_x][box_y][1]
3.6 根據滑鼠坐標找到矩形列表坐標
def get_box_at_pixel(x,y):
'''根據滑鼠坐標找到矩形列表坐標
:param x 滑鼠x坐標
:param y 滑鼠y坐標
:return 返回列表坐標'''
for box_x in range(BOARD_WIDTH):
for box_y in range(BOARD_HEIGHT):
left,top=left_top_coords_of_box(box_x,box_y)
box_rect=pygame.Rect(left, top, BOX_SIZE, BOX_SIZE) #繪製所有坐標矩形
if box_rect.collidepoint(x,y): #矩形碰撞,判斷該滑鼠坐標是否在矩形內
return (box_x,box_y)
return (None,None)
3.7 列表分組
def split_into_group_of(group_size, the_list):
'''分組取值
:param group_size 需要分組的數量 最後一個有多少取多少
:param the_list 需要分組的列表'''
result = []
for i in range(0, len(the_list), group_size):
result.append(the_list[i:i + group_size]) #每組取n個
return result
3.8 檢查牌子是否都開啟了
def has_won(revealed_boxes):
'''檢查所有箱子是否都開啟了
:param revealed_boxes 反轉箱子的坐標'''
for i in revealed_boxes:
if False in i:
return False # return False if any boxes are covered.
return True
4 創建游戲繪畫類(views.py)
4.1 創建類的初始化
class puzzle(object):
def __init__(self,DISPLAY_SURF,FPS_CLOCK):
self.DISPLAY_SURF=DISPLAY_SURF #surf對象
self.FPS_CLOCK=FPS_CLOCK #fps鎖對象
self.main_board=get_randomized_board() #初始化盒子
self.revealed_boxes=generate_revealed_boxes_data(False) #初始化翻開的盒子列表
4.2 繪製游戲盒子(類方法)
def draw_board(self,board,revealed):
'''繪製游戲盒子
:param board 盒子坐標列表
:param revealed 被翻轉盒子坐標列表'''
for box_x in range(BOARD_WIDTH):
for box_y in range(BOARD_HEIGHT):
if not revealed[box_x][box_y]: #判斷該坐標是否被反轉
#繪製沒有翻開的盒子
self.draw_lid(box_x,box_y)
else:
#繪製已翻開的盒子
shape, color = get_shape_and_color(board, box_x, box_y)
self.draw_icon(shape, color, box_x, box_y)
4.3 繪製沒翻開的盒子
def draw_lid(self,box_x,box_y):
'''繪製沒翻開的盒子
:param box_x,box_y 盒子坐標'''
left, top = left_top_coords_of_box(box_x, box_y)
pygame.draw.rect(self.DISPLAY_SURF, BOX_COLOR, (left, top, BOX_SIZE, BOX_SIZE))
4.4 繪製已經翻開的盒子
def draw_icon(self,shape,color,box_x,box_y):
'''繪製翻開盒子的圖案
:param shape 形狀
:param color 形狀的顏色
:param box_x,box_y 盒子坐標'''
quarter=int(BOX_SIZE*0.25) #
half=int(BOX_SIZE*0.5) #
left,top=left_top_coords_of_box(box_x,box_y) #通過盒子坐標找到像素坐標
if shape==DONUT: #繪製甜甜圈形狀
pygame.draw.circle(self.DISPLAY_SURF,color,(left+half,top+half),half-5) #繪製 外圓 半徑離框5個像素
pygame.draw.circle(self.DISPLAY_SURF,BG_COLOR,(left+half,top+half),quarter-5) #繪製內圓 1/4之一個半徑
elif shape==SQUARE: #繪製正方形
pygame.draw.rect(self.DISPLAY_SURF,color,(left+quarter,top+quarter,BOX_SIZE-half,BOX_SIZE-half))
elif shape==DIAMOND: #繪製鑽石形狀
pygame.draw.polygon(self.DISPLAY_SURF,color,((left+half ,top),(left+BOX_SIZE-1,top+half),(left+half,top+BOX_SIZE-1),(left,top+half)))
elif shape==LINES: #繪製線條形
for i in range(0,BOX_SIZE,6): #步長控制密度越小密度越大
pygame.draw.line(self.DISPLAY_SURF,color,(left,top+i),(left+i,top)) #上往左邊的斜角線N條 一半
pygame.draw.line(self.DISPLAY_SURF,color,(left+i,top+BOX_SIZE-1),(left+BOX_SIZE-1,top+i)) #從下往右斜角線條N條 一半
elif shape==OVAL: #繪製橢圓
pygame.draw.ellipse(self.DISPLAY_SURF,color,(left,top+quarter,BOX_SIZE,half))
4.5 滑鼠懸停高亮顯示
def draw_hightlight_box(self,box_x, box_y):
'''繪製滑鼠懸停加亮顯示
:param box_x 盒子列表x坐標
:param box_y 盒子列表y坐標'''
left, top = left_top_coords_of_box(box_x, box_y)
pygame.draw.rect(self.DISPLAY_SURF,HIGHLIGHT_COLOR,(left-5,top-5,BOX_SIZE+10,BOX_SIZE+10),4) #繪畫外部高亮矩形
4.6 翻箱動畫
def reveal_boxes_animation(self,boxes_to_reveal):
'''翻箱子動畫
:param boxes_to_reveal 需要翻開的箱子坐標列表'''
for coverage in range(BOX_SIZE, (-REVEAL_SPEAD) - 1, -REVEAL_SPEAD): #從大到小繪製蓋板動畫 開蓋子
self.draw_box_covers(boxes_to_reveal, coverage)
4.7 合箱動畫
def cover_boxes_animation(self,boxes_to_cover):
'''蓋上箱子動畫
:param boxes_to_cover 需要蓋上的箱子坐標列表'''
for coverage in range(0, BOX_SIZE + REVEAL_SPEAD, REVEAL_SPEAD): #從小到大繪製蓋板動畫 關蓋子
self.draw_box_covers(boxes_to_cover, coverage)
4.8 動畫遮罩層
def draw_box_covers(self, boxes, coverage):
'''列印一次開/關 蓋子
:param boxes 需要操作的箱子列表
:param coverage 遮罩層的寬度'''
for box in boxes:
left, top = left_top_coords_of_box(box[0], box[1])
pygame.draw.rect(self.DISPLAY_SURF, BG_COLOR, (left, top, BOX_SIZE, BOX_SIZE)) #繪製背景
shape, color = get_shape_and_color(self.main_board, box[0], box[1])
self.draw_icon(shape, color, box[0], box[1]) #繪製形狀
if coverage > 0: # 如果遮罩層的寬度小於0就不繪製遮罩層了
pygame.draw.rect(self.DISPLAY_SURF, BOX_COLOR, (left, top, coverage, BOX_SIZE)) #繪製覆蓋層
pygame.display.update()
self.FPS_CLOCK.tick(FPS)
4.9 玩家勝利動畫
def game_won_animation(self):
'''玩家勝利顯示'''
covered_boxes = generate_revealed_boxes_data(True)
color1 = LIGHTBG_COLOR
color2 = BG_COLOR
for i in range(13):
color1, color2 = color2, color1 # 交替背景色
self.DISPLAY_SURF.fill(color1) #閃爍背景
self.draw_board(self.main_board, covered_boxes) #繪製所有顯示圖案
pygame.display.update()
pygame.time.wait(300) #每次閃爍間隔300毫秒
4.10 游戲開始動畫
def start_game_animation(self):
'''隨機展示8個盒子'''
cover_boxes = generate_revealed_boxes_data(False) #製造隨機翻開的盒子
boxes = []
for x in range(BOARD_WIDTH):
for y in range(BOARD_HEIGHT):
boxes.append((x, y))
random.shuffle(boxes) #隨機盒子坐標
box_groups = split_into_group_of(8, boxes) #隨機抽取8個盒子坐標
self.draw_board(self.main_board,cover_boxes) #繪製沒翻開板子的游戲界面
for box_group in box_groups: #迴圈翻板
self.reveal_boxes_animation(box_group)
self.cover_boxes_animation(box_group)
5. 游戲邏輯判斷(游戲核心Memory_Puzzle.py)
5.1 游戲使用模塊和常量
import sys,pygame
from pygame.locals import *
from conf.color import *
from conf.game_conf import *
from core import views
from conf.shape import *
BG_COLOR=NAVYBLUE #背景色
5.2 游戲邏輯判斷
def main():
pygame.init()
FPS_CLOCK=pygame.time.Clock()
DISPLAY_SURF=pygame.display.set_mode((WINDOW_WIDTH,WINDOW_HEIGHT))
Puzzle = views.puzzle(DISPLAY_SURF, FPS_CLOCK)
pygame.display.set_caption('My Game')
mouse_x=0 #滑鼠x坐標
mouse_y=0 #滑鼠y坐標
first_selection = None # 存儲第一個翻開的盒子
DISPLAY_SURF.fill(BG_COLOR)#繪製背景色
Puzzle.start_game_animation() #游戲開始提示
while True:
mouse_clicked=False #初始化滑鼠點擊
DISPLAY_SURF.fill(BG_COLOR) #迴圈掩蓋高亮顯示
Puzzle.draw_board(Puzzle.main_board,Puzzle.revealed_boxes)
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type==MOUSEMOTION: #獲取滑鼠懸停的像素坐標
mouse_x,mouse_y=event.pos
elif event.type==MOUSEBUTTONDOWN: #獲取滑鼠點擊的像素坐標
mouse_x,mouse_y=event.pos
mouse_clicked=True
box_x,box_y=views.get_box_at_pixel(mouse_x, mouse_y)
if box_x!=None and box_y!=None: #當滑鼠在一個框上的時候
if not Puzzle.revealed_boxes[box_x][box_y]: #沒有翻開的牌子高亮顯示
Puzzle.draw_hightlight_box(box_x,box_y)
if not Puzzle.revealed_boxes[box_x][box_y] and mouse_clicked: #沒有翻開牌子並且點擊的盒子顯示
Puzzle.reveal_boxes_animation([(box_x,box_y)]) #掀開動畫
Puzzle.revealed_boxes[box_x][box_y]=True #設置翻開坐標
if first_selection==None: #檢查是否第一次翻牌子
first_selection=(box_x,box_y)
else:
icon1_shape,icon1_color=views.get_shape_and_color(Puzzle.main_board, first_selection[0], first_selection[1])
icon2_shape,icon2_color=views.get_shape_and_color(Puzzle.main_board, box_x, box_y)
if icon1_shape != icon2_shape or icon1_color!=icon2_color: #判斷兩個方塊不相同
pygame.time.wait(1000)#等待一秒鐘
Puzzle.cover_boxes_animation([(first_selection[0], first_selection[1]), (box_x, box_y)])
Puzzle.revealed_boxes[first_selection[0]][first_selection[1]] = False
Puzzle.revealed_boxes[box_x][box_y]=False
elif views.has_won(Puzzle.revealed_boxes): #判斷游戲是否勝利
Puzzle.game_won_animation() #顯示獲勝界面
pygame.time.wait(200)
#初始化數據
Puzzle.main_board = views.get_randomized_board() #重置箱子
Puzzle.revealed_boxes = views.generate_revealed_boxes_data(False) #重置玩家翻開表
#顯示游戲界面
Puzzle.draw_board(Puzzle.main_board,Puzzle.revealed_boxes)
pygame.display.update()
pygame.time.wait(1000)
#游戲開始前的動畫
PURPLE.start_game_animation()
first_selection=None
pygame.display.update()
FPS_CLOCK.tick(FPS)
5.3 運行游戲
if __name__ == '__main__':
main()
python學習途徑
本游戲參考書本 <<Python和Pygame游戲開發>>
游戲源碼下載 http://invpy.com/memorypuzzle.py
友情推薦: 猿人學Python【https://www.yuanrenxue.com/】 由一群工作十餘年的老程式員結合實際工作經驗所寫的Python教程。