f549c035335d6881a6f8d1d90929307820f4ccbe
cheat_panel replaces the level_skip autoload: a single small button in the top-right opens a panel holding the fly toggle and the level jump buttons, so nothing that looks like leftover debug UI is on screen. The fly is no longer gated behind OS.is_debug_build, so the easter egg works in exported builds too, and the 1/2/3 shortcuts only fire while the panel is open so they cannot be hit by accident. Space stays unbound and no gameplay content was touched.
平台闯关 · Pixel Platformer
一个用 Godot 4.7 制作的 2D 像素风平台跳跃游戏。
运行方式
- 用 Godot 4.7 打开本目录(选择
project.godot) - 按
F5运行
主场景:scenes/main.tscn
操作
| 按键 | 作用 |
|---|---|
A / D |
左右移动 |
空格 |
(当前已停用,输入映射里的 jump 键位为空) |
S 按住 |
显示投掷抛物线预览 |
S 松开 |
投出钥匙 |
W |
传送到扔出去的钥匙位置,并把它捡回来 |
Z |
消耗一个回血道具:回一颗心 + 5 秒无敌盾 |
F |
切换飞行(隐藏技能,藏在右上角「房★主★有★神★器★」面板里,见下方说明) |
R / Enter |
死亡后重新开始 |
玩法
- 生命值:共 3 颗心。碰到尖刺扣 1 颗心并被打回出生点,生命归零后进入死亡界面。
- 收集物:地图上有 3 个金色小球,走过去自动拾取,变成"回血道具"。
- 回血:按
Z消耗一个道具,回一颗心并获得 5 秒无敌盾。 - 钥匙:走过去自动捡起;按住
S时实时显示抛物线轨迹和落点;松开投出。按W可以直接瞬移到钥匙处并收回它。 - 弹簧:踩上去弹起约 57px(普通跳跃约 20px)。
- 隐藏通道:关卡里有几处"看着是石壁、其实能直接穿过去"的暗道。
对应作业要求
① 玩家移动控制代码
scripts/player_controller.gd
- 节点类型
CharacterBody2D,每帧结束调用move_and_slide() - 重力:
get_gravity(),只在not is_on_floor()时累加到velocity.y - 水平移动:
Input.get_axis("move_left", "move_right")取方向,用move_toward()做加速 / 减速插值,手感比直接赋值柔和 - 跳跃:
Input.is_action_just_pressed("jump")配合is_on_floor(),因此只有踩在地面上才能起跳,天然不会二段跳- ⚠️ 目前输入映射里的
jump没有绑定任何按键(空格被空置了),所以这段代码暂时不会触发。 想恢复:项目 → 项目设置 → 输入映射 → jump → 添加按键 → 空格,或者把project.godot里jump的"events"改回[Object(InputEventKey, ... "physical_keycode":32 ...)]。
- ⚠️ 目前输入映射里的
- 朝向:根据
velocity.x的正负翻转Sprite2D.flip_h
② 瓦片地图
- 用了 3 层
TileMapLayer:TerrainBase— 主体地形TerrainDetailsA/TerrainDetailsB— 前景装饰(z_index 1 / 2)
TileSet使用 18×18 的图集(assets/game/tilesets/),逐个图块配置了物理碰撞多边形;草地单向平台用one_way实现- 隐藏通道的做法:在地形层上用
erase_cell()把指定格子挖空,再在那个位置盖一张完全没有碰撞的Sprite2D(贴图借用旁边墙块),于是画面上仍然是完整石壁、人却能穿过去
③ 碰撞体的区别与使用场景
项目里四种碰撞方式都用到了:
| 类型 | 用在哪 | 为什么选它 |
|---|---|---|
CharacterBody2D |
玩家 | 需要主动移动、被地形阻挡、能踩在地面和箱子上 |
StaticBody2D |
木箱、弹簧、树干、路牌、传送箱 | 不动的实体障碍,玩家能站上去、撞得到 |
Area2D |
金币、尖刺、弹簧触发区、钥匙 | 只需要"碰到就触发",不产生物理推挤,所以能穿过去 |
TileMapLayer 物理层 |
大面积地面 | 重复地形太多,用瓦片自带碰撞最省事,不用摆几百个 CollisionShape2D |
碰撞层约定:
| 层号 | 用途 |
|---|---|
| 1 | 世界实体(地形、木箱、树干、路牌、弹簧、传送箱) |
| 2 | 玩家 |
| 4 | 危险物(尖刺) |
| 8 | 交互触发区(弹簧、传送箱的检测区) |
| 16 | 收集物(金币、宝石、钥匙) |
玩家的 collision_mask 只有 layer 1,所以只和"世界实体"发生物理碰撞,不会被金币、尖刺挡住。
④ 角色技能
技能 A —— 投掷钥匙 + 传送(scripts/key.gd)
- 走过去自动捡起钥匙
- 按住
S:用与玩家完全相同的碰撞掩码做抛物线模拟,实时画出轨迹和落点标记 - 松开
S:把钥匙按同样的初速度扔出去 - 按
W:瞬移到钥匙所在位置并收回它 - 因为预测和实际飞行调用的是同一个
simulate_trajectory()函数,"弧线显示能落到的地方"就等于"钥匙真正落到的地方"(实测偏差 0.000 px)
技能 B —— 飞行(隐藏技能)(player_controller.gd)
- 按
F切换飞行状态,方向键 ↑ / ↓ 控制升降(S也可以下降),A/D平移 - 屏幕上不会有任何提示,它是藏在右上角 「房★主★有★神★器★」 按钮里的彩蛋:
点开面板就能看到飞行开关和跳关按钮(键盘
1/2/3跳关,Esc关闭面板) - 这个面板由自动加载单例
scripts/cheat_panel.gd提供,三个关卡都有,正式版里也能用 - 如果想在导出版里也开放,把
fly_available()里的OS.is_debug_build()去掉即可:func fly_available() -> bool: return debug_fly
目录结构
├─ project.godot 引擎配置(输入映射、窗口、渲染)
├─ scripts/
│ ├─ player_controller.gd 玩家:移动、跳跃、生命值、投掷、飞行
│ ├─ key.gd 钥匙:拾取 / 飞行 / 落地、轨迹模拟
│ ├─ spring.gd 弹簧:踩上去弹起
│ ├─ hazard.gd 危险物:碰到扣血
│ ├─ collectible.gd 收集物:走过去拾取
│ ├─ hidden_passages.gd 隐藏通道:挖空地砖 + 盖假墙
│ ├─ hud.gd 左上角:心 + 道具数 + 护盾倒计时
│ └─ death_screen.gd 死亡界面:渐黑 + 重新开始
├─ scenes/
│ ├─ main.tscn 主场景(关卡)
│ ├─ player.tscn 玩家
│ ├─ hud.tscn 状态显示
│ ├─ death_screen.tscn 死亡界面
│ └─ prefabs/ 预制件:金币、钥匙、弹簧、尖刺、木箱、树、路牌
└─ assets/
├─ game/ 实际使用的素材
└─ kenney/ Kenney 原始素材库
素材来源
- 图形素材:Kenney — Pixel Platformer (1.2)
- 授权:CC0(可商用、可修改,无需署名)
- 来源:https://kenney.nl
- 详见
LICENSE_KENNEY.txt
版本控制
本项目使用 git 进行版本管理。
Description
Languages
GDScript
100%