返回
玩法拆解 · 代码 · Demo
射击解谜网格

泡泡龙 Bubble Shooter:瞄准即落点,连锁才得分

拆解这只泡泡龙的确定性设计:角度如何被折叠成列选择、八向连通如何提高消除密度、每 10 发压顶如何把倒计时改成可计算的步数压力,以及悬空 20 分为什么是技巧上限。文末附可试玩 demo。

2

玩法拆解

规则骨架
  • 14 行 × 8 列网格,开局随机填 5 行,蓝/绿/红三色泡泡
  • 瞄准角 ±80° 直接映射到目标列:泡泡挂在该列最低泡泡之下,空列则顶到天花板
  • 八向连通同色 ≥3 即消除,每颗 10 分;失去顶部锚点的泡泡整片下落,每颗 20 分
  • 每发射 10 次天花板整体下压一行;触底或列满判负,清空网格直接结算
行为循环
  • 读盘:看网格缺口 + 当前/下一颗颜色,决定这一发去哪一列
  • 按住拖动出瞄准线,松手发射(pointerDown 瞄准 / pointerUp 发射)
  • 命中 → 消除计分 → 悬空连锁下落 → 发射计数 +1
  • 计数满 10 发压顶一行,网格逼近底线形成倒计时感;结束进 result,可 Restart 或回菜单
实现要点
  • core/bubble-shooter 承载全部规则数据:bubbleGrid / currentBubble / nextBubble / score / comboCount
  • 渲染与交互走 core/scene-renderer 的 grid-shooter 模板(PIXI),__OV.Games.BubbleShooter.Game 只做薄封装注册 drawer
  • 消除用八向 flood fill,悬空检测用从顶行出发的 BFS 锚定标记
  • 状态机 boot → menu → gameplay → result 由 v2-kernel LogicGraph 驱动,按钮事件与迁移事件严格同名

关键代码

瞄准角折叠成列与挂靠落点(core/bubble-shooter)
js· 17 行
悬空检测:顶行出发的八向 BFS(core/bubble-shooter)
js· 24 行
玩法行为:本文属于「射击」母型瞄准、命中与资源管理形成闭环;核心是命中反馈与风险收益。
查看母型详解

Demo

点击 Play 开局;在网格区域按住拖动瞄准、松手发射,凑 3 颗同色消除,打掉支撑点可整片连锁下落;每 10 发天花板下压一行,别让泡泡触底。

泡泡龙 Bubble Shooter:瞄准即落点,连锁才得分 Demo
游戏加载中…

文章

泡泡龙 Bubble Shooter:瞄准即落点,连锁才得分

一句话本质

表面上是"瞄准射击",实质是一个确定性三消:瞄准角被折叠成列选择,每一发都可以提前算清后果。连锁下落(悬空 20 分/颗)是技巧上限,每 10 发压顶一行是节奏时钟——玩家永远知道自己输在哪一发。

泡泡龙是全民认知。这只样本值得拆的地方在于:它把原版"连续弹道 + 墙面反弹"换成离散落点,用极低的实现成本保住了"这发该打哪"的解谜感。

行为循环

  1. 读盘:扫网格缺口与颜色分布,再看当前泡泡和下一颗预览——两个信息一起决定目标列。
  2. 瞄准:在网格区域按住拖动,出现瞄准虚线;角度限制在 ±80°。
  3. 发射:松手即射。泡泡不做连续物理飞行,按角度映射到目标列,挂在该列最低泡泡之下;空列则顶到天花板。
  4. 结算消除:新泡泡与邻居做八向连通检查,同色 ≥3 整片消除,每颗 10 分。
  5. 连锁下落:消除后做顶部锚定扫描,失去连接的泡泡整片掉落,每颗 20 分——得分放大器。
  6. 压顶:发射计数满 10,天花板整体下压一行并补一行随机泡泡。触底、列满判负;清空网格则通关。
  7. 结算页:展示最终分数,Restart 重开,Menu 回菜单。

原语标注

  • Aim(angle) – 按住拖动调整瞄准角,实时更新瞄准线
  • Shoot(angle) – 松手发射当前泡泡
  • Attach(row, col, color) – 泡泡按列挂载进网格
  • Match(min=3) – 八向 flood fill 找同色连通块
  • Eliminate(cells) – 消除并计分(10 分/颗)
  • Cascade() – 顶行 BFS 锚定,未锚定泡泡整片下落(20 分/颗)
  • Advance(every=10) – 每 10 发天花板下压一行
  • CheckEnd() – 触底 / 列满 / 清空三向终局判定

参数速查表

| 参数 | 说明 | 默认值 | 单位 | |------|------|--------|------| | gridRows | 网格总行数 | 14 | 行 | | gridCols | 网格列数 | 8 | 列 | | initialRows | 开局填充行数 | 5 | 行 | | colorCount | 泡泡颜色数(蓝/绿/红) | 3 | 种 | | matchMin | 最小消除连通数 | 3 | 颗 | | popScore | 每颗消除得分 | 10 | 分 | | cascadeScore | 每颗悬空下落得分 | 20 | 分 | | advanceEvery | 压顶间隔(发射数) | 10 | 发 | | aimRange | 瞄准角度范围 | ±80 | 度 | | canvasRect | 发射交互区(设计坐标) | 75,180 / 600×540 | px |

设计取舍

  1. 角度折叠成列:连续弹道和反弹对触屏单手并不友好,落点预判也容易变成玄学。把 ±80° 直接映射到 8 列后,玩家下发前就能确定落点,解谜属性(spatial)才成立。代价是牺牲反弹炫技,换来每发都可复盘。
  2. 八向连通而非四向:斜对角也算连通,显著提高匹配概率。对入门难度这是对的——新手前几发就能打出消除;换四向,盘面会明显变"硬"。
  3. 压顶用步数而非秒表:每 10 发压一行,把倒计时翻译成可计算的步数压力。玩家能精确说出"我还有几发可以浪费",失败原因可解释,比秒表更适合解谜向玩家。
  4. 悬空 20 分 > 消除 10 分:双倍分差是最直白的行为引导——打支撑点比打散兵值钱。玩家会主动学习"找连接最细的那一格",技巧深度全藏在这个系数里。
  5. 三色而非四色:颜色越少,单发匹配期望越高,节奏越快;"清空网格"的胜利结局在 14×8 盘面上真实可达成,高手有"胜"的出口,而不只是比谁死得慢。

实现要点

  • 规则全部下沉到模块:core/bubble-shooter 管网格、挂载、匹配、连锁、压顶与终局判定,只暴露 reset / setAim / shoot 三个动作;蓝图 LogicGraph 里只有 onEnter reset、onEvent(aim/shoot) 调动作,没有散落的分支逻辑。
  • 渲染是模板而非定制:画面由 core/scene-renderer 的 grid-shooter 模板绘制(交错行布局、瞄准线、消除淡出、危险线),__OV.Games.BubbleShooter.Game 只是注册 drawer 的薄封装,换皮不用动渲染层。
  • 悬空检测的正确姿势:消除后从顶行 BFS 打锚定标记,没被标记的就是悬空,一次性整片清除。逐颗递归判断"是否还挂着"在级联场景下又慢又容易漏。
  • 压顶先判溢出再移动:下压前先查底行是否已有泡泡,有则直接 game.over,避免把泡泡推出网格。
  • 事件名即契约:皮肤按钮的 game.start / game.restart / game.menu 与状态机迁移事件严格同名,点击无需胶水代码;bubble.aim / bubble.shoot 由指针事件发出,payload 只带一个 angle。
  • 音频按事件挂:发射、挂载、消除、连锁、结束各挂一条 SFX,音效时机与规则事件天然对齐,表现层无需状态轮询。

"离散落点 + 八向匹配 + 步数压顶"是把街机泡泡龙改造成移动端解谜三消的最小配方。文中参数与判定都可以在文末 demo 里直接验证——它正是本文分析的那一份构建产物。