Files
sijcdusmode/README.md
T
sijcdu f549c03533 Hide the debug fly and level skip behind a 房★主★有★神★器★ easter-egg panel
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.
2026-10-07 23:10:41 +08:00

6.5 KiB
Raw Blame History

平台闯关 · Pixel Platformer

一个用 Godot 4.7 制作的 2D 像素风平台跳跃游戏。


运行方式

  1. 用 Godot 4.7 打开本目录(选择 project.godot)
  2. 按 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 进行版本管理。