跳到主要内容

无限酷跑游戏开发教程

· 阅读需 5 分钟
ahKevinXy
作者

无限酷跑是一类很适合练习前端游戏逻辑的小游戏:角色持续向前,障碍不断出现,玩家通过跳跃躲避障碍,并通过道具获得额外能力。

这次在游戏模块里新增了一个本地横版无限酷跑页面:/game/arcade/infinite-runner。它支持三连跳、护盾道具、短暂无敌、撞碎障碍、分数递增和最佳分记录。

更新日期:2026-07-06。

一、玩法规则

这个版本的无限酷跑规则如下:

  1. 点击舞台、按空格、上箭头或 W 键可以跳跃。
  2. 每次离地后最多可以连续跳 3 次。
  3. 落地后跳跃次数重置。
  4. 障碍物从右向左移动,碰到角色会结束游戏。
  5. 吃到护盾道具后进入短暂无敌状态。
  6. 无敌状态下撞到障碍不会失败,反而会撞碎障碍并奖励距离。
  7. 跑得越久速度越快,分数越高。

这个版本不依赖外部素材,角色、障碍、跑道和道具都用 CSS 绘制,方便在 Docusaurus 静态站点里直接运行。

二、核心实现思路

跑酷游戏有两种常见实现方式:

  1. 角色向右移动,镜头跟随角色。
  2. 角色固定在左侧,场景、障碍和道具向左移动。

这里采用第二种方式。角色的水平位置固定,只处理垂直方向的跳跃;障碍和道具不断向左移动。这样状态更少,也更适合写成简单的 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 动画实现,护盾用发光圈提示,道具用轻微上下浮动来增加可读性。

九、后续可以继续优化

这个版本已经具备基础跑酷玩法,后面可以继续扩展:

  1. 增加滑铲动作。
  2. 增加磁铁道具,自动吸收附近道具。
  3. 增加金币和商店升级。
  4. 增加不同地形和坑洞。
  5. 增加移动端虚拟按钮。
  6. 增加本地最高分持久化。
  7. 增加关卡主题切换。

如果要做更完整的版本,可以把游戏状态从 React state 移到 requestAnimationFrame 驱动的游戏循环里,再把 React 只作为 UI 层。这适合更高帧率、更复杂的动作游戏。

总结

无限酷跑的核心可以拆成 5 个模块:

  1. 跳跃物理:高度、速度、重力。
  2. 三连跳:离地期间最多触发 3 次跳跃。
  3. 场景滚动:障碍和道具向左移动。
  4. 碰撞检测:用矩形判断是否相交。
  5. 道具效果:护盾改变碰撞后的结果。

掌握这套结构后,就可以继续做更多横版动作小游戏,比如跳跃闯关、金币收集、横版射击和节奏躲避类游戏。