sijcdu 4a6f4862de Bring the jump back so the key warp can reach high ledges
Space is bound to jump again, exactly as before: same action name, same physical_keycode 32, same jump_velocity -190 and gravity 980, so the measured jump height is 20.07 px, identical to the reading taken before the binding was removed. Single jump only, no double jump. The debug flight goes back to Space for up and S for down like it used to, with the arrow keys kept as an extra. No gameplay content touched.
2026-10-07 23:14:52 +08:00

平台闯关 · Pixel Platformer

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


运行方式

  1. 用 Godot 4.7 打开本目录(选择 project.godot)
  2. 按 F5 运行

主场景:scenes/main.tscn


操作

按键 作用
A / D 左右移动
空格 跳跃(单段,空中不能二段跳)
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(),因此只有踩在地面上才能起跳,天然不会二段跳
  • 朝向:根据 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 进行版本管理。

S
Description
No description provided
Readme 227 KiB
Languages
GDScript 100%