本教程为我在b站投稿的视频教程av81480858 对应的文字版,项目最终效果见投稿简介部分,视频部分讲解的比较详细,觉得文字版不够详细的可以去看视频。
本项目最终代码已上传github: https://github.com/BigShuang/Tetris 的1_BASIC文件夹
。其中1234分别对应本项目教程每一部分的最终代码,所以想看完整代码直接看004.py就好。
本项目通过python自带库tkinter实现,无需安装第三方库
本项目基于python3版本开发(如果你的是python2.x,运行可能会有问题)
总目录
一、基础界面
二、界面动起来
三、生成、移动、固定、消除
四、消除与得分
======================= 大爽歌作,made by big shuang =======================
一、基础界面
1、搭建基础窗体
使用tkinter库实现基础窗体,不加入任何功能只需如下三行代码
import tkinter as tk
win = tk.Tk()
win.mainloop()
运行代码生成的窗口如下
接下来我们需要在窗体里面,添加一个画布容器用来“装”俄罗斯方块,就是让这个画布作为面板,俄罗斯方块的移动和绘制均在这个画板上实现。
这里我们设定一些俄罗斯方块游戏参数
- 行数为R(取20)
- 列数为C(取12)
- 俄罗斯方块的边长为cell_size(取30)
通过tkinger的画布类Canvas实现的代码如下
import tkinter as tk
cell_size=30
C = 12
R = 20
height = R*cell_size
width = C*cell_size
win = tk.Tk()
canvas = tk.Canvas(win, width=width, height=height)
canvas.pack()
win.mainloop()
此时界面的长宽就变成我们所需要的了
接下来在画板上绘制俄罗斯方块空白位
首先建立一个函数draw_cell_by_cr
,用于在画板上绘制单个俄罗斯方块
然后建立一个函数draw_blank_board
,用于在画板上绘制所有空白方块(也就是空白方块板,为了和背景区分,所以设置空白方块为轻灰色)
此时整体代码如下:
import tkinter as tk
cell_size = 30
C = 12
R = 20
height = R * cell_size
width = C * cell_size
def draw_cell_by_cr(canvas, c, r, color="#CCCCCC"):
"""
:param canvas: 画板,用于绘制一个方块的Canvas对象
:param c: 方块所在列
:param r: 方块所在行
:param color: 方块颜色,默认为#CCCCCC,轻灰色
:return:
"""
x0 = c * cell_size
y0 = r * cell_size
x1 = c * cell_size + cell_size
y1 = r * cell_size + cell_size
canvas.create_rectangle(x0, y0, x1, y1, fill=color, outline="white", width=2)
# 绘制空白面板
def draw_blank_board(canvas):
for ri in range(R):
for ci in range(C):
draw_cell_by_cr(canvas, ci, ri)
win = tk.Tk()
canvas = tk.Canvas(win, width=width, height=height, )
canvas.pack()
draw_blank_board(canvas)
win.mainloop()
此时运行代码生成的窗口如下
2、绘制o形俄罗斯方块
先从最简单的o型俄罗斯方块(即田字格,如下图)
我们先要记录每各形状所有格子的坐标
以格子所在行序号为纵坐标,所在列序号为横坐标
以田字格中点为原点,则o型俄罗斯方块的四个格子的坐标如下图所示
关于上方的坐标,有b站朋友私戳我,表示还是没看懂
所以这里进一步解释下, 以o型俄罗斯方块的右下小格为例,坐标为(0,0)所指的那个方格是第一行,第一列的。
由于python的列表是从0开始计数,所以坐标(0,0)中的第一个0是指c=0,表示在第一列;第二个0是指r=0,表示在第一行
如果还是觉得有点不懂,那就这么理解, 以格子左上角顶点的坐标,为格子坐标
用列表和元组记录为
[
(-1, -1),
(0, -1),
(-1, 0),
(0, 0)
]
我们将俄罗斯方块形状字符串和坐标列表的映射关系存到字典SHAPES里(映射关系这里可以理解为一一对应的关系)
同时建立一个字典SHAPESCOLOR,来记录俄罗斯方块形状字符串和颜色的一一对应关系。
由于一个形状可以看成多个方格组成的,所以我们可以新建函数draw_cells用来绘制这个形状
最后选择一个地方来绘制这个形状。
# 定义形状
SHAPES = {
"O": [(-1, -1), (0, -1), (-1, 0), (0, 0)],
}
# 定义形状的颜色
SHAPESCOLOR = {
"O": "blue",
}
def draw_cells(canvas, c, r, cell_list, color="#CCCCCC"):
"""
绘制指定形状指定颜色的俄罗斯方块
:param canvas: 画板
:param r: 该形状设定的原点所在的行
:param c: 该形状设定的原点所在的列
:param cell_list: 该形状各个方格相对自身所处位置
:param color: 该形状颜色
:return:
"""
for cell in cell_list:
cell_c, cell_r = cell
ci = cell_c + c
ri = cell_r + r
# 判断该位置方格在画板内部(画板外部的方格不再绘制)
if 0 <= c < C and 0 <= r < R:
draw_cell_by_cr(canvas, ci, ri, color)
# 下面这行代码放在draw_blank_board(canvas) 下面
# 任取一个位置,如(3,3)绘制一个o型俄罗斯方块,用于展示
draw_cells(canvas, 3, 3, SHAPES['O'], SHAPESCOLOR['O'])
# 上面这行代码放在win.mainloop()上面
此时运行代码生成的窗口如下
3、其他俄罗斯方块
俄罗斯方块主流分七种,除去上面的O型,其他六俄罗斯方块如图所示
对应的,要在SHAPES和SHAPESCOLOR中添加其他方块的坐标和颜色,添加后如下
SHAPES = {
"Z": [(-1, -1), (0, -1), (0, 0), (1, 0)],
"O": [(-1, -1), (0, -1), (-1, 0), (0, 0)],
"S": [(-1, 0), (0, 0), (0, -1), (1, -1)],
"T": [(-1, 0), (0, 0), (0, -1), (1, 0)],
"I": [(0, 1), (0, 0), (0, -1), (0, -2)],
"L": [(-1, 0), (0, 0), (-1, -1), (-1, -2)],
"J": [(-1, 0), (0, 0), (0, -1), (0, -2)]
}
SHAPESCOLOR = {
"O": "blue",
"Z": "Cyan",
"S": "red",
"T": "yellow",
"I": "green",
"L": "purple",
"J": "orange",
}
将原来绘制O型俄罗斯方块处的代码改成如下代码,将这七种俄罗斯方块绘制出来
draw_cells(canvas, 3, 3, SHAPES['O'], SHAPESCOLOR['O'])
draw_cells(canvas, 3, 8, SHAPES['S'], SHAPESCOLOR['S'])
draw_cells(canvas, 3, 13, SHAPES['T'], SHAPESCOLOR['T'])
draw_cells(canvas, 8, 3, SHAPES['I'], SHAPESCOLOR['I'])
draw_cells(canvas, 8, 8, SHAPES['L'], SHAPESCOLOR['L'])
draw_cells(canvas, 8, 13, SHAPES['J'], SHAPESCOLOR['J'])
draw_cells(canvas, 5, 18, SHAPES['Z'], SHAPESCOLOR['Z'])
本部分最终代码见https://github.com/BigShuang/Tetris/blob/master/1_BASIC/001.py, 绘制出来的效果如图