本文发表于入职啦(公众号: ruzhila) 大家可以访问入职啦学习更多的编程实战。
用100行代码的不同语言(Java、Python、Go、Javascript、Rust)实现项目,通过讲解项目的实现,帮助大家学习编程
我们会定期在群里分享最新的项目实战代码,包括不同语言的实现
老师还会详细讲解代码优化的思路,扫码加入实战群:
项目地址
代码已经开源, tetris-py 👏 欢迎Star
所有的项目都在github上开源:100-line-code 欢迎Star 👏
代码运行效果:
Python图形库实现游戏开发
Python 开发2d游戏,主要是通过pygame,这是一个基于SDL的游戏开发库,但是这个库有点大,所以我们用tkinter这个库来实现这个游戏。
tkinter是python自带的跨平台图形库,提供了最基本的绘制能力,我们可以通过这个库来实现这个游戏
整个代码的思路:
创建UI后通过两个事件处理来完成游戏逻辑:
- 定时器用来做UI的逻辑判断和绘制
- 键盘事件用来处理用户的输入,比如移动方块,旋转方块,然后渲染到UI上
俄罗斯方块游戏规则
俄罗斯方块有7种不同的形状,每种形状都可以旋转,玩家通过键盘控制方块的移动和旋转,当一行被填满时,这一行会消失,方块会继续下落,直到方块堆满或者游戏结束
绘制思路:
- 一个二维数组(board)来表示游戏区域,每个方块的状态,数组的值为0表示空,1表示方块
- 一个二维数组(shape)来表示运动方块的形状,每个方块的状态,数组的值为0表示空,1表示方块
游戏逻辑:
- 通过定时器来判断shape是否与board碰撞,如果碰撞就把shape的状态复制到board中,然后生成新的shape
- 如果出现一行被填满,就消除这一行,然后把上面的方块往下移动一行
- 当新生成的shape不能移动时,游戏结束
- 通过键盘事件来控制shape的移动和旋转
直接上代码
代码解析
数据结构抽象
在游戏开始之前,我们需要先设计不同方块的形状,前面绘制思路,我们可以得出不同的方块,其实就是多行的二维数组,每个数组的值为0表示空,1表示方块
比如四方形方块:
shape = [
[1, 1],
[1, 1]
]
或者J形方块:
shape = [
[1, 1, 1],
[0, 0, 1]
]
事件处理
我们实现了key_press的事件处理,这个函数会在用户按下键盘的时候触发,我们通过这个函数来控制方块的移动和旋转。
旋转
旋转的实现是通过list(zip(*reversed(self.shape))) 这样魔法一样的语法:
- 这段代码的作用是旋转一个二维列表, 比如:
shape = [[0, 1],
[1, 1],
[1, 0]]
- reversed(shape) 将 shape 的行反转,结果如下:
[[1, 0],
[1, 1],
[0, 1]]
- zip(*reversed(shape)) 使用 zip 函数将反转后的 shape 的列转换为行,结果如下:
[(1, 1, 0),
(0, 1, 1)]
- 最后,list(zip(*reversed(shape))) 将结果转换为列表,结果如下:
[[1, 1, 0],
[0, 1, 1]]
这样就可以将原始的shape旋转90度。
移动
移动的实现是通过修改self.x和self.y的值,然后重新绘制方块,在移动之前需要先判断是否可以移动self.can_move, 就是遍历shape的每一个元素,判断是否会碰到边界或者已经有方块:
这时候会用到一个很常用的enumerate函数,这个函数可以同时返回索引和值。
UI绘制
整个游戏的UI绘制是通过定时器来完成的,通过每秒重新计算shape的位置,判断是否可以消除或者Gameover, 然后重新绘制UI
绘制主流程
绘制UI和消除行
以下代码分别实现固定shape、消除行、绘制固定块(self.board)和移动块self.shape的逻辑:
总结
通过这个项目,我们可以学习到如何使用tkinter的使用,面向对象的编程思想,学习list、dict等常见的数据结构的使用
游戏开发是一个很好的学习编程的方式,这个代码并没太高深的算法,很多人觉得游戏很需要算法,其实不然,所以我们特意用100行代码实现了这个游戏
我们构建了一个100行代码项目的实战群,大家可以扫码加入,一起学习编程
也可以访问入职啦学习更多的编程实战
所有的代码都在github上开源:100-line-code 欢迎Star 👏