python 游戏(记忆拼图Memory_Puzzle)
程序员文章站
2022-05-29 12:03:54
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游戏开发>>
游戏源码下载
友情推荐: 猿人学python【】 由一群工作十余年的老程序员结合实际工作经验所写的python教程。
上一篇: JDBC day06