platformer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlatformer
平台游戏
A playbook for 2D platformers — the run/jump controller "feel", level structure, hazards,
and goals. This is a compositional skill: it wires an engine movement skill, a tilemap
skill, and design skills into a working game. It does not re-teach physics or tilemaps;
it tells you what to build and how to make jumping feel good.
一份2D平台游戏的开发指南——涵盖跑跳控制器的「手感」、关卡结构、危险元素以及目标设计。这是一项组合式技能:它将引擎移动技能、tilemap技能和设计技能整合为可运行的游戏。本指南不会重新讲解物理或tilemap知识;它会告诉你要构建什么,以及如何让跳跃手感更出色。
When to use
适用场景
- Use when building a side-scrolling or single-screen platformer, a "Mario-like" / "Celeste-like", or any game whose core verb is jump between surfaces.
- Use when a jump feels floaty, unresponsive, or "unfair" and you need feel fixes (coyote time, jump buffering, variable height, corner correction).
When not to use: top-down movement with no gravity → use the engine movement skill
directly. 3D first-person traversal → . Grid/turn movement → .
For the raw kinematic body API, use (or your engine's controller skill).
fps-shooterroguelikegodot-2d-movement- 适用于构建横向卷轴或单屏平台游戏、「类马里奥」/「类蔚蓝」游戏,或任何核心玩法为在平台间跳跃的游戏。
- 当跳跃手感显得漂浮、反应迟缓或「不合理」,需要进行手感修复(coyote time、jump buffering、可变高度、拐角修正)时使用。
不适用场景: 无重力的俯视视角移动 → 直接使用引擎移动技能。3D第一人称移动 → 使用技能。网格/回合制移动 → 使用技能。如需原始运动学物体API,请使用(或对应引擎的控制器技能)。
fps-shooterroguelikegodot-2d-movementCore loop
核心循环
Observe a gap/hazard → commit to a jump or move → land safely (or die) → reach the next
checkpoint/goal. A platformer lives or dies on the moment-to-moment feel of that single
jump, repeated thousands of times. Tighten the controller first; everything else is content.
观察缺口/危险元素 → 决定跳跃或移动 → 安全着陆(或死亡) → 到达下一个 checkpoint/目标。 平台游戏的成败取决于单次跳跃的即时手感,而这个动作会被重复数千次。优先优化控制器;其他一切都只是内容。
Must-have systems
必备系统
- Run/jump controller — horizontal accel/decel, gravity, jump, with the feel aids below.
- Solid + one-way collision — ground, walls, and "jump-through" platforms.
- Level geometry — a tilemap or hand-placed colliders; the playable space.
- Hazards + death/respawn — spikes, pits, enemies; reset to the last checkpoint.
- Checkpoints / level goal — progress markers and a win condition (flag, door, exit).
- Camera — follows the player with a deadzone and look-ahead, clamped to level bounds.
- Juice — landing dust, squash/stretch, hit-stop, sound. Cheap, huge feel payoff.
- 跑跳控制器 —— 水平加速/减速、重力、跳跃,搭配以下手感优化功能。
- 实体+单向碰撞 —— 地面、墙壁和「可跳跃穿过」的平台。
- 关卡几何结构 —— tilemap或手动放置的碰撞体;可游玩空间。
- 危险元素+死亡/重生 —— 尖刺、陷阱、敌人;重置到最近的checkpoint。
- Checkpoint / 关卡目标 —— 进度标记和胜利条件(旗帜、门、出口)。
- 相机 —— 跟随玩家,带有死区和前瞻功能,并限制在关卡边界内。
- 润色效果(Juice) —— 落地灰尘、挤压拉伸、击中停顿、音效。成本低,但对提升手感效果显著。
Design knobs (make the jump feel right)
设计调节项(优化跳跃手感)
Tune these by outcome (height in tiles, time to apex in seconds), not by raw numbers.
| Knob | Effect | Sane starting point |
|---|---|---|
| Max jump height | reach | 3–4 tiles |
| Time to apex | "weight"/snappiness | 0.30–0.40 s |
| Fall gravity multiplier | snappy, non-floaty fall | 1.5–2.0× rise gravity |
| Coyote time | jump just after leaving a ledge | 0.08–0.12 s (~5–7 frames @60) |
| Jump buffer | press just before landing still jumps | 0.10–0.15 s |
| Variable jump cut | tap = short hop, hold = full | cut upward velocity ×0.4–0.5 on release |
| Apex hang | brief float at the top for air control | reduce gravity ×0.5 near ` |
| Ground accel / friction | responsiveness vs. ice | reach top speed in 0.05–0.1 s |
| Corner correction | nudge past a ledge clipped by 1–2 px | nudge up to ~4 px sideways |
Derive gravity and jump velocity from the feel values rather than guessing — see Pattern 1.
通过结果(以瓦片为单位的高度,到达顶点的时间(秒))来调节这些参数,而非原始数值。
| 调节项 | 效果 | 合理起始值 |
|---|---|---|
| 最大跳跃高度 | 跳跃可达高度 | 3–4个瓦片 |
| 到达顶点时间 | 「重量感」/灵敏性 | 0.30–0.40 秒 |
| 下落重力乘数 | 让下落更灵敏、不漂浮 | 上升重力的1.5–2.0倍 |
| Coyote time | 刚离开边缘时仍可跳跃 | 0.08–0.12秒(60帧下约5–7帧) |
| Jump buffer | 落地前提前按下跳跃键仍可触发跳跃 | 0.10–0.15秒 |
| 可变跳跃高度 | 轻按=短跳,按住=满跳 | 松开按键时将上升速度乘以0.4–0.5 |
| 顶点悬浮 | 在跳跃顶点短暂悬浮以提升空中控制 | 当` |
| 地面加速/摩擦力 | 响应速度 vs 冰面效果 | 在0.05–0.1秒内达到最高速度 |
| 拐角修正 | 推动玩家越过被1–2像素卡住的边缘 | 最多横向推动约4像素 |
从「手感」值推导重力和跳跃速度,而非凭空猜测——请参见模式1。
Patterns
模式
1. Solve jump physics from height + time (not magic numbers)
1. 从高度+时间推导跳跃物理(而非魔法数值)
python
undefinedpython
undefinedPseudocode. Pick the FEEL you want, then derive the physics. y-axis points DOWN.
伪代码。先确定你想要的手感,再推导物理参数。y轴向下。
From kinematics: h = (g * t^2) / 2 and v0 = g * t.
来自运动学公式:h = (g * t^2) / 2 以及 v0 = g * t。
JUMP_HEIGHT = 3.5 * TILE # how high, in world units
TIME_TO_APEX = 0.35 # seconds to reach the top
gravity = (2 * JUMP_HEIGHT) / (TIME_TO_APEX ** 2) # rising gravity
jump_velocity = -(2 * JUMP_HEIGHT) / TIME_TO_APEX # negative = upward
fall_gravity = gravity * 1.8 # heavier on the way down → less floaty
undefinedJUMP_HEIGHT = 3.5 * TILE # 跳跃高度,以世界单位计
TIME_TO_APEX = 0.35 # 到达顶点的时间(秒)
gravity = (2 * JUMP_HEIGHT) / (TIME_TO_APEX ** 2) # 上升阶段重力
jump_velocity = -(2 * JUMP_HEIGHT) / TIME_TO_APEX # 负值表示向上
fall_gravity = gravity * 1.8 # 下落阶段重力更大 → 减少漂浮感
undefined2. Coyote time + jump buffer + variable height (the feel core)
2. Coyote time + Jump buffer + 可变高度(手感核心)
python
undefinedpython
undefinedPseudocode in the per-frame update. dt = seconds since last frame.
每帧更新中的伪代码。dt = 距上一帧的时间(秒)。
Timers count DOWN; refresh coyote while grounded, buffer on a fresh press.
计时器倒计时;在地面时刷新coyote计时器,按下跳跃键时刷新缓冲计时器。
if on_floor:
coyote_timer = COYOTE_TIME # 0.1
if jump_pressed_this_frame:
buffer_timer = JUMP_BUFFER # 0.12
coyote_timer -= dt
buffer_timer -= dt
if on_floor:
coyote_timer = COYOTE_TIME # 0.1
if jump_pressed_this_frame:
buffer_timer = JUMP_BUFFER # 0.12
coyote_timer -= dt
buffer_timer -= dt
A jump is allowed if we pressed recently AND were grounded recently.
当最近按下跳跃键且最近处于地面时,允许跳跃。
if buffer_timer > 0 and coyote_timer > 0:
velocity.y = jump_velocity
buffer_timer = 0
coyote_timer = 0 # consume both so we can't double-jump
if buffer_timer > 0 and coyote_timer > 0:
velocity.y = jump_velocity
buffer_timer = 0
coyote_timer = 0 # 消耗两个计时器,防止二段跳
Variable height: releasing jump early while still rising cuts the arc short.
可变高度:在上升阶段松开跳跃键会缩短跳跃轨迹。
if jump_released_this_frame and velocity.y < 0:
velocity.y *= 0.45
if jump_released_this_frame and velocity.y < 0:
velocity.y *= 0.45
Asymmetric gravity: snappier fall than rise.
非对称重力:下落比上升更灵敏。
g = fall_gravity if velocity.y > 0 else gravity
velocity.y += g * dt
undefinedg = fall_gravity if velocity.y > 0 else gravity
velocity.y += g * dt
undefined3. One-way platforms
3. 单向平台
Solid from above, pass-through from below. Most engines expose a "one-way collision" flag on
the tile/collider; enable it and let the player drop through by disabling that collision
for a few frames when the player holds Down + Jump. Do not re-implement collision math.
上方实体碰撞,下方可穿过。大多数引擎会在瓦片/碰撞体上提供「单向碰撞」标记;启用该标记,并在玩家按住向下键+跳跃键时,暂时禁用碰撞几帧,让玩家下落穿过平台。不要重新实现碰撞逻辑。
Pitfalls / failure modes
陷阱/失败模式
- Per-frame movement not scaled by → speed changes with frame rate. Every velocity integration and timer must use
dt. (Seedt.)physics-tuning - Floaty jumps → symmetric gravity. Make fall gravity heavier than rise gravity.
- "The jump didn't register" → no input buffering. Buffer presses for ~0.1 s before landing.
- "I fell off and couldn't jump" → no coyote time. Allow a jump for ~0.1 s after leaving ground.
- Sticking to walls / catching on tile seams → use a single capsule/box collider, not per-tile colliders, and add corner correction.
- Tunneling through floors at high speed → enable continuous collision / smaller fixed
timestep for fast bodies (see ).
physics-tuning - Camera snaps and induces nausea → smooth/lerp the follow, add a deadzone, clamp to bounds.
- Difficulty wall from bad teaching → introduce one mechanic per area before combining them.
- 每帧移动未按缩放 → 速度随帧率变化。所有速度积分和计时器都必须使用
dt。(参见dt。)physics-tuning - 漂浮感跳跃 → 对称重力。让下落重力大于上升重力。
- 「跳跃未触发」 → 没有输入缓冲。在落地前约0.1秒内缓冲按键。
- 「我掉下去了但没法跳」 → 没有coyote time。允许玩家离开地面后约0.1秒内仍可跳跃。
- 粘墙 / 卡在瓦片接缝处 → 使用单个胶囊/盒形碰撞体,而非每个瓦片一个碰撞体,并添加拐角修正。
- 高速下穿透地面 → 为快速移动的物体启用连续碰撞检测/更小的固定时间步长(参见)。
physics-tuning - 相机突然移动导致恶心 → 使用平滑插值跟随,添加死区,限制在边界内。
- 糟糕的教学导致难度陡增 → 在组合机制前,每个区域只引入一种机制。
Composition (build it from these skills)
组合方式(通过以下技能构建)
- Controller body: (Godot
godot-2d-movement); for other engines use the engine core + physics skill (CharacterBody2D,unity-physics,phaser-arcade-physics).pygame-core - Levels: /
godot-tilemapfor geometry;unity-tilemap-2dfor layout, pacing, and teaching order.level-design - Feel/physics: for timestep, CCD, and stability.
physics-tuning - Input: for buffering, rebinding, and gamepad support.
input-systems - Polish: for SFX/music; the engine animation skill for squash/stretch.
audio-design - Process: to greybox the controller before building content.
prototype-fast
- 控制器物体: (Godot的
godot-2d-movement);对于其他引擎,使用引擎核心+物理技能(CharacterBody2D、unity-physics、phaser-arcade-physics)。pygame-core - 关卡: 使用/
godot-tilemap构建几何结构;使用unity-tilemap-2d进行布局、节奏和教学顺序设计。level-design - 手感/物理: 用于时间步长、CCD和稳定性。
physics-tuning - 输入: 用于缓冲、重绑定和手柄支持。
input-systems - 润色: 用于音效/音乐;引擎动画技能用于挤压拉伸效果。
audio-design - 流程: 用于在构建内容前快速制作控制器原型。
prototype-fast
References
参考资料
- For jump math derivation, a full feel-tuning table, corner correction, moving/one-way
platforms, and camera follow, read .
references/feel-tuning.md
- 如需跳跃数学推导、完整的手感调节表、拐角修正、移动/单向平台以及相机跟随的相关内容,请阅读。
references/feel-tuning.md