Pytris (Python, Aditya Adiraju, 2021)
Pytris | |
---|---|
开发 | Aditya Adiraju |
游戏平台 | Python(Pygame) |
发行时间 | 2021年4月4日 |
游戏信息 | |
预览块数 | 0 |
场地大小 | 10 × 24 |
暂存 | 有(可在任意节点时刻发动) |
硬降 | 无(但有瞬降) |
旋转系统 | 专用 |
Pytris 是一款 Python 四连方块游戏。
该游戏有很多方块运动方面的漏洞,要尽量在开阔处操作才能正常游戏。
玩法
得分 = 总消行数 × 10。
重力恒定,方块每隔 0.1 秒自动下落一行。
死亡判定:重叠死亡。
触发死亡时,游戏程序终止。
操作
左右键横移,上键逆时针旋转,空格键瞬降,H 暂存。
这五个操作可以叠加长按,而且有以下四个特性:
- 叠加状态可跨块(也就可以实现 IRS)
- 暂存可在任意节点时刻发动(可被滥用),但插在旋转长按之后会失效
- 左右键叠加(或顶牢彩色砖格长按横移)可使方块不锁定
- 横移和瞬降叠加长按时,方块只会在低于天花板至少 4 行的边区瞬降
这个游戏每 0.1 秒取一次判定变化的节点时刻,各节点之间没有中间状态。
其关键参数在 main.py 第 214 行的 clock.tick() 当中,默认为 10。
每个节点时刻都伴随一次重力处理,所以方块不可能抵达场地的两个顶角位置。
而且,如果单点操作的压键时间恰好都不在节点时刻上,单点操作就会失败。
方块环境配置
基础数据设定
七种方块意在使用 SRS 配色,但 I 配成了淡水绿色(173, 216, 255)。
|
|
|
|
|
|
|
|
各方块的入场位置如上图所示。
其中,数字 4 的坐标为 (5,21)。
游戏中的七种方块都以“位宽高心色”五元数据表示,不设碰撞箱信息:
位(self.location):方块身上的四个格子所对应的四个坐标联合组成的列表数据。
宽和高(self.width、self.height):方块在 x 和 y 方向上的最大展幅数值。
心(self.center):先按入场位安排、后由具体变化算得的单一坐标列表数据。[注 1]
色(self.color):RGB 元组数据。
变心和碰撞
变心(reset_center)指心坐标值的变化方法:
- 时刻检查方块身上四个 x 坐标当中的极大和极小值(max_x、min_x),一旦发生变动,数据立刻刷新
- 心[x] = (min_x + max_x + 1) / 2
- 心[y] 也是用这个式子计算的,但它不在计算前刷新 max_y 和 min_y 的数据。
碰撞(collide)指方块目标位置与方块堆的重叠情况。
关键代码:if player.grid[i[0]][i[1]] != (0, 0, 0) and player.grid[i[0]][i[1]] != (255, 255, 255)
这一段代码是在按目标位置的格子颜色判断碰撞处理结果,如果不是黑或白(而是彩色的方块堆),碰撞就成立。
黑色格子代表空格(包括场外部分),场内部分显示为灰色是因为有一张“bg.png”灰格背景图叠了上去。
白色格子代表瞬降出来的假阴影块,在 main.py 第 60 行最后改成 ghost=True 时开启,其实质也是空格。
以旋转碰撞为例,方块旋转和场外格子碰撞时旋转失败、静止不动,换成和方块堆碰撞则会不正常地变形和穿越。
旋转的原理
Pytris (Python, Aditya Adiraju, 2021) 方块旋转的逻辑顺序如下:
- 对调宽和高的数值
- 旧位[yx] - 心[yx] = 临时位[yx]
- 新位 = [int(心[y] - 临时位[x]), int(心[x] + 临时位[y])]
- 判断碰撞情况
- 如果碰撞成立,前三步反序退回
- 如果碰撞不成立,就执行变心,心坐标减宽/高的一半,结果四舍五入
方块在实际游戏中旋转不正常的问题出在最后这两步上面:
第五步的退回次序按常理应是 321 却被写成了 231,而且 x 变成被减了两次心[x],返回了错误的宽高和坐标,方块会变形和穿越;
第六步的算式按两个极值为心[yx]取好了平均却继续按方块展幅缩减,心[x]每次计算都会有所亏损,所以方块越转越偏左。[注 2]
最后,这个游戏在 pygame 的按键事件中为“上键”(旋转)添加了三个条件来保证方块不会旋转出界:
- 心[y] + 半宽 < 24(高于场底)
- 心[x] + 半高 < 10(在场地右侧墙壁的左边)
- 心[x] - 半高 ≥ 0(在场地左侧墙壁的右边)