「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」
本系列专栏将通过不断编写游戏的方式,带你夯实 Python 知识。
这篇博客的目的
本文继续为你补充 pygame 中的一些小知识点,后面开始写一个知名案例,较于其他博客,本篇博客拆解及其细致。
导入 pygame 中常用的常量 使用下述代码,可以导入 pygame 中常用的常量。
from pygame.locals import *
在 locals 中内置了如下常量。
['ACTIVEEVENT', 'ANYFORMAT', 'APPACTIVE', 'APPFOCUSMOUSE', 'APPINPUTFOCUS', 'ASYNCBLIT', 'AUDIODEVICEADDED', 'AUDIODEVICEREMOVED', 'AUDIO_ALLOW_ANY_CHANGE', ...]
总数可以通过下述代码获取,达到了 551 个。
import pygame
from pygame.locals import *
print(len(dir(pygame.locals)))
所以通过代码导入之后,此 551 个常量,不需要在通过 pygame.x 方式进行调用了,可以直接使用常量名称。
下面三种方式调用的数据是一致的。
print(pygame.BLEND_MAX)
print(pygame.locals.BLEND_MAX)
print(BLEND_MAX)
多应用自定义常量 pygame 进行游戏编写时,经常会遇到需要数字变量的时候,此时可以设置为下述内容:
WIDTH = 400
HEIGHT = 300
FPS = 30
熟练使用该形式代码,可以大幅度的增加代码的可读性。 对于部分字符串,也可以声明成常量,便于后续的使用。
SQUARE = 'square'
LINES = 'lines'
Memory Puzzle 记忆拼图 该案例来源自书籍中的案例,互联网已经有相关的完整代码,本阶段学习将对该案例进行拆解,重新梳理实现逻辑。
游戏主框架部分代码 本部分决定了游戏的一个主体结构,也是编写过程中最简单的点。
import pygame
import random
import sys
from pygame.locals import *
FPS = 30
WIDTH = 600
HEIGHT = 400
# 颜色常量
WHITE = (255, 255, 255)
TURQUOISE = (64, 224, 208)
# 场景颜色
BGCOLOR = TURQUOISE
# 游戏运行入口函数
def main():
# pygame 模块初始化
pygame.init()
# pygame 时钟初始化
FPSCLOCK = pygame.time.Clock()
# 设置游戏窗口
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
# 游戏窗口标题
pygame.display.set_caption("记忆拼图")
# 背景填充
SCREEN.fill(BGCOLOR)
# 游戏主循环
while True:
# 事件处理
for event in pygame.event.get():
# 按下 ESC 键或者点击关闭,退出程序
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
# 更新屏幕
pygame.display.update()
# 设置帧率
FPSCLOCK.tick(FPS)
if __name__ == '__main__':
main()
上述代码基于之前的博客内容实现,运行效果如下:
设置方块
方块目前参考案例给出的是 10 x 7 个,我们需要做的就是生成 70 个不同的形状与颜色的数据。本部分核心用到的代码在图后。
代码中主要的注释部分都已经提供,编写的时候从 main_board = get_random_board() 函数调用开始进行编写。
import pygame
import random
import sys
from pygame.locals import *
FPS = 30
WIDTH = 600
HEIGHT = 400
# 设置横向盒子的数量
BOARDWIDTH = 10
# 设置纵向盒子的数量
BOARDHEIGHT = 7
# 颜色常量
WHITE = (255, 255, 255)
TURQUOISE = (64, 224, 208)
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)
# 场景颜色
BGCOLOR = TURQUOISE
# 定义形状
DONUT = 'donut' # 甜甜圈
SQUARE = 'square' # 方形
DIAMOND = 'diamond' # 钻石
LINES = 'lines' # 多条线
OVAL = 'oval' # 椭圆
ALLCOLORS = (RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, CYAN)
ALLSHAPES = (DONUT, SQUARE, DIAMOND, LINES, OVAL)
# 游戏运行入口函数
def main():
# pygame 模块初始化
pygame.init()
# pygame 时钟初始化
FPSCLOCK = pygame.time.Clock()
# 设置游戏窗口
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
# 游戏窗口标题
pygame.display.set_caption("记忆拼图")
# ********************
# 游戏中的 board 数据生成
main_board = get_random_board()
# ********************
# 背景填充
SCREEN.fill(BGCOLOR)
# 游戏主循环
while True:
# 事件处理
for event in pygame.event.get():
# 按下 ESC 键或者点击关闭,退出程序
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
# 更新屏幕
pygame.display.update()
# 设置帧率
FPSCLOCK.tick(FPS)
# 游戏中的拼图数据生成函数主体
def get_random_board():
# 全列举所有的颜色和形状,进行组合之后的结果存在 icons 中
icons = []
for color in ALLCOLORS:
for shape in ALLSHAPES:
icons.append((shape, color))
# 列表乱序
random.shuffle(icons)
# 计算需要多少种的元素(也就是整个 BORDER 里所有 box(目前有 70 个) 的一半)
num_icons_used = int(BOARDWIDTH * BOARDHEIGHT / 2)
# 将上面得到的元素复制一份(得到的结果就可以两两配对)
icons = icons[:num_icons_used] * 2
# 再次打乱 icons 里的元素的顺序
random.shuffle(icons)
# 创建用来存放 board 数据的结构,将上面处理好的 icons 分组放入 board 中
board = []
for x in range(BOARDWIDTH):
# 列集合
column = []
for y in range(BOARDHEIGHT):
# 每次都添加第一个元素
# print(icons[0])
column.append(icons[0])
# 删除已经复制的元素
del icons[0]
board.append(column)
# print(board)
return board
if __name__ == '__main__':
main()
代码运行之后,生成的结构体如下,10 行 7 列,好像和一开始的设置有些出入,后面如果碰到问题,在进行修改。
[[('lines', (0, 255, 0)), ('square', (255, 255, 0)), ('donut', (0, 255, 0)), ('donut', (0, 255, 255)), ('square', (255, 128, 0)), ('diamond', (255, 128, 0)), ('square', (255, 255, 0))],
[('diamond', (0, 255, 255)), ('oval', (255, 0, 0)), ('donut', (255, 128, 0)), ('diamond', (255, 255, 0)), ('square', (0, 0, 255)), ('oval', (255, 128, 0)), ('oval', (255, 0, 0))],
[('oval', (255, 0, 255)), ('donut', (0, 255, 255)), ('donut', (255, 255, 0)), ('donut', (0, 0, 255)), ('square', (255, 0, 0)), ('square', (0, 255, 255)), ('diamond', (0, 255, 0))],
[('square', (255, 0, 255)), ('oval', (255, 128, 0)), ('oval', (255, 255, 0)), ('oval', (255, 255, 0)), ('oval', (0, 255, 255)), ('lines', (0, 255, 0)), ('lines', (255, 0, 0))],
[('lines', (255, 255, 0)), ('lines', (255, 255, 0)), ('lines', (0, 255, 255)), ('donut', (255, 0, 0)), ('donut', (0, 255, 0)), ('oval', (255, 0, 255)), ('lines', (255, 128, 0))],
[('diamond', (255, 0, 0)), ('donut', (255, 255, 0)), ('diamond', (0, 0, 255)), ('diamond', (255, 0, 255)), ('square', (0, 255, 255)), ('oval', (0, 0, 255)), ('diamond', (0, 255, 0))],
[('diamond', (0, 0, 255)), ('donut', (255, 0, 255)), ('oval', (0, 255, 0)), ('lines', (0, 255, 255)), ('square', (0, 0, 255)), ('square', (0, 255, 0)), ('oval', (0, 255, 255))],
[('donut', (0, 0, 255)), ('lines', (255, 0, 255)), ('diamond', (255, 255, 0)), ('square', (255, 0, 0)), ('oval', (0, 0, 255)), ('lines', (255, 0, 255)), ('square', (255, 0, 255))],
[('diamond', (255, 128, 0)), ('lines', (0, 0, 255)), ('lines', (0, 0, 255)), ('donut', (255, 0, 255)), ('donut', (255, 128, 0)), ('lines', (255, 0, 0)), ('lines', (255, 128, 0))],
[('oval', (0, 255, 0)), ('donut', (255, 0, 0)), ('square', (0, 255, 0)), ('square', (255, 128, 0)), ('diamond', (0, 255, 255)), ('diamond', (255, 0, 0)), ('diamond', (255, 0, 255))]]
本篇代码先到此为止,下篇继续完善。
本系列专栏将通过不断编写游戏的方式,带你夯实 Python 知识。
这篇博客的目的
今天的主要目标就是绘制 10*7 个小方块,最终实现的效果图如下所示。
逻辑实现
在界面上进行正方形绘制,主要搞定坐标即可,方块颜色白色,宽度设计为 40 像素。
核心函数调用为:
# 游戏开场动画
start_game_animation(main_board)
函数主体内容
# 游戏入场动画函数
def start_game_animation(board):
# 默认获取到的都是 False
covered_boxes = generate_revealed_boxes(False)
draw_board(board, covered_boxes)
该函数内部调用了 generate_revealed_boxes() 与 draw_board() 两个函数。
generate_revealed_boxes()
# 生成一个 10*7 的数组,用来存放 box 的状态
def generate_revealed_boxes(val):
revealed_boxes = []
for i in range(BOARDWIDTH):
revealed_boxes.append([val] * BOARDHEIGHT)
return revealed_boxes
该函数会返回一个 7x10 结构,值都为 False 的二维列表。
[[False, False, False, False, False, False, False],
[False, False, False, False, False, False, False],
……
draw_board() 该函数用于绘制白色方块。
# 绘制默认 box
def draw_board(board, revealed):
for boxx in range(BOARDWIDTH):
for boxy in range(BOARDHEIGHT):
left, top = lefttop_coords_box(boxx, boxy)
if not revealed[boxx][boxy]:
# 绘制一个被覆盖的box
pygame.draw.rect(SCREEN, BOXCOLOR, (left, top, BOXSIZE, BOXSIZE))
else:
pass
这里又出现了一个新的函数 lefttop_coords_box(boxx, boxy),函数用途是传入方块的 x 坐标和 y 坐标,绘制一个矩形。
坐标转换函数内容如下:
# 计算出 box 的左上角的像素坐标
def lefttop_coords_box(boxx, boxy):
# 将数字坐标转化成像素坐标
left = boxx * (BOXSIZE + GAPSIZE) + XMARGIN
top = boxy * (BOXSIZE + GAPSIZE) + YMARGIN
return (left, top)
用到的全局常量,具体设置参考下述代码,重点理解 XMARGIN 与 YMARGIN ,这两个值为的是将渲染出的整体区域进行居中展示。
FPS = 30
WIDTH = 640
HEIGHT = 480
# 设置横向盒子的数量
BOARDWIDTH = 10
# 设置纵向盒子的数量
BOARDHEIGHT = 7
# 设置box的大小
BOXSIZE = 40
# 设置box间的间隔
GAPSIZE = 10
# 计算距离 x 轴边缘的距离
XMARGIN = int((WIDTH - (BOARDWIDTH * (BOXSIZE + GAPSIZE))) / 2)
# 计算距离 y 轴边缘的距离
YMARGIN = int((HEIGHT - (BOARDHEIGHT * (BOXSIZE + GAPSIZE))) / 2)
本系列专栏属于番外篇,希望你能学到新知识。 有任何疑问,都可以联系橡皮擦进行解决,一起做游戏吧 本专栏每天的练习量大概在 1 小时左右,整篇博客节奏会比较快,毕竟咱们是有基础的人。