0d2bccc3a9a3c7edcc159ab04f35ddc8111e19a7
Removed the stomp-kill from walker.gd: landing on an enemy now just costs a heart like any other contact, so the only way past is to weave through the pattern or use the key throw + W warp. Enemies fire a fan of bullets every fire_interval whose directions are computed only from the facing and the exported spread, never from the player, so every volley traces the identical path and can be memorised. Bullets are code-generated circles (no art needed), die on hitting terrain via a probe raycast, and are freed after their lifetime. New laser prefab cycles wait -> blinking warmup -> firing, and only damages during the firing phase.
平台闯关 · Pixel Platformer
一个用 Godot 4.7 制作的 2D 像素风平台跳跃游戏。
运行方式
- 用 Godot 4.7 打开本目录(选择
project.godot) - 按
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切换飞行状态,W/S控制升降,A/D平移 - 为了不影响正式玩法的难度平衡,只在编辑器 / 调试版生效(
OS.is_debug_build()),导出正式版按键无效 - 如果想在导出版里也开放,把
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%