无限酷跑游戏开发教程
无限酷跑是一类很适合练习前端游戏逻辑的小游戏:角色持续向前,障碍不断出现,玩家通过跳跃躲避障碍,并通过道具获得额外能力。
这次在游戏模块里新增了一个本地横版无限酷跑页面:/game/arcade/infinite-runner。它支持三连跳、护盾道具、短暂无敌、撞碎障碍、分数递增和最佳分记录。
更新日期:2026-07-06。
一、玩法规则
这个版本的无限酷跑规则如下:
- 点击舞台、按空格、上箭头或
W键可以跳跃。 - 每次离地后最多可以连续跳 3 次。
- 落地后跳跃次数重置。
- 障碍物从右向左移动,碰到角色会结束游戏。
- 吃到护盾道具后进入短暂无敌状态。
- 无敌状态下撞到障碍不会失败,反而会撞碎障碍并奖励距离。
- 跑得越久速度越快,分数越高。
这个版本不依赖外部素材,角色、障碍、跑道和道具都用 CSS 绘制,方便在 Docusaurus 静态站点里直接运行。
二、核心实现思路
跑酷游戏有两种常见实现方式:
- 角色向右移动,镜头跟随角色。
- 角色固定在左侧,场景、障碍和道具向左移动。
这里采用第二种方式。角色的水平位置固定,只处理垂直方向的跳跃;障碍和道具不断向左移动。这样状态更少,也更适合写成简单的 React 小游戏。
核心状态可以拆成几类:
type RunnerState = {
status: 'ready' | 'running' | 'crashed'
y: number
velocityY: number
jumpsUsed: number
distance: number
speed: number
invincibleMs: number
obstacles: Obstacle[]
powerUps: PowerUp[]
}
其中最重要的是:
y:角色离地高度。velocityY:垂直速度。jumpsUsed:当前离地后的跳跃次数。speed:障碍和道具向左移动的速度。invincibleMs:剩余无敌时间。
三、三连跳算法
跳跃不是简单地改一个高度,而是用一个小型物理模型:
y += velocityY * dt
velocityY -= gravity * dt
每一帧更新角色高度和速度。角色跳起来后,速度会因为重力逐渐变小,然后变成负数开始下落。
触发跳跃时,只要当前跳跃次数小于 3,就给角色一个向上的初速度:
if (jumpsUsed < 3) {
velocityY = baseJumpVelocity - jumpsUsed * 42
jumpsUsed += 1
}
后两跳略微降低初速度,是为了让三连跳有节奏感,不至于无限拔高。
落地时重置:
if (y <= 0) {
y = 0
velocityY = 0
jumpsUsed = 0
}
这个模型的好处是手感比较自然,也方便之后加入二段跳、滑翔、下坠加速等能力。
四、障碍生成
障碍物不是按固定时间生成,而是按“距离间隔”生成。每一帧都会把 nextObstacleIn 减去本帧移动的距离:
nextObstacleIn -= speed * dt
当它小于等于 0 时,就在舞台右侧生成一个新障碍:
if (nextObstacleIn <= 0) {
obstacles.push(makeObstacle(nextId))
nextObstacleIn = 330 + Math.random() * 310
}
这样做的好处是:即使速度越来越快,障碍之间的空间距离仍然可控,而不是因为帧率或计时误差导致障碍突然挤在一起。
五、道具和无敌护盾
道具同样从右向左移动。角色碰到护盾道具时,设置无敌时间:
if (collide(player, powerUp)) {
invincibleMs = 4200
}
每一帧让无敌时间递减:
invincibleMs = Math.max(0, invincibleMs - tickMs)
碰到障碍时,根据是否无敌决定结果:
if (collide(player, obstacle)) {
if (invincibleMs > 0) {
removeObstacle()
distance += 120
} else {
status = 'crashed'
}
}
这就是道具系统的核心:道具只改变玩家一段时间内的碰撞规则。
六、碰撞检测
这个游戏使用矩形碰撞,也就是 AABB 检测。
两个矩形相交的条件是:
function rectsOverlap(a, b) {
return (
a.left < b.right &&
a.right > b.left &&
a.top < b.bottom &&
a.bottom > b.top
)
}
角色、障碍、道具都会转换成矩形:
type Rect = {
left: number
right: number
top: number
bottom: number
}
为了让手感更友好,角色矩形会比视觉图形略小一点。这样玩家感觉“擦边而过”时不会被误判。
七、难度递增
无限酷跑的紧张感来自速度递增:
speed = Math.min(430, speed + 4.5 * dt)
速度有上限,避免后期不可玩。分数根据距离计算:
score = Math.floor(distance / 12)
这比直接按秒加分更合理,因为玩家吃到护盾撞碎障碍时会奖励距离,分数也会自然提升。
八、页面样式
舞台使用一个固定比例区域:
.runnerStage {
height: 340px;
width: 680px;
overflow: hidden;
position: relative;
}
角色、障碍和道具全部使用绝对定位:
.runnerAvatar,
.runnerObstacle,
.runnerPowerUp {
position: absolute;
}
角色跑动腿部用 CSS 动画实现,护盾用发光圈提示,道具用轻微上下浮动来增加可读性。
九、后续可以继续优化
这个版本已经具备基础跑酷玩法,后面可以继续扩展:
- 增加滑铲动作。
- 增加磁铁道具,自动吸收附近道具。
- 增加金币和商店升级。
- 增加不同地形和坑洞。
- 增加移动端虚拟按钮。
- 增加本地最高分持久化。
- 增加关卡主题切换。
如果要做更完整的版本,可以把游戏状态从 React state 移到 requestAnimationFrame 驱动的游戏循环里,再把 React 只作为 UI 层。这适合更高帧率、更复杂的动作游戏。
总结
无限酷跑的核心可以拆成 5 个模块:
- 跳跃物理:高度、速度、重力。
- 三连跳:离地期间最多触发 3 次跳跃。
- 场景滚动:障碍和道具向左移动。
- 碰撞检测:用矩形判断是否相交。
- 道具效果:护盾改变碰撞后的结果。
掌握这套结构后,就可以继续做更多横版动作小游戏,比如跳跃闯关、金币收集、横版射击和节奏躲避类游戏。
