Flutter Flame同类型多对象碰撞管理:气泡射手局部消除实现
实现气泡射手的邻近同类型气泡消除功能
我正在开发一个包含鱼、狗、猫三种圆形气泡的气泡射手Demo,当前发射狗气泡时会消除屏幕上所有同类型气泡,希望改为仅消除被击中气泡邻近的同类型气泡(包括连锁相邻的)。现有碰撞处理代码如下:
@override void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) { super.onCollision(intersectionPoints, other); if (other is DogBubble) { if (position.distanceTo(other.position) <= radius + other.radius) { removeFromParent(); } } }
之前尝试过仅移除被击中的单个气泡,或是全量清除同类型气泡,都不符合需求,需要实现击中后消除所有连通的邻近同类型气泡。
核心思路
要实现连锁邻近消除,需要通过**广度优先搜索(BFS)**从被击中的气泡出发,遍历所有与之直接或间接相邻的同类型气泡,最后统一移除这些气泡。关键步骤是:
- 维护全局的气泡列表,方便查找和遍历所有屏幕上的气泡
- 碰撞触发时,启动BFS收集所有连通的同类型气泡
- 批量移除收集到的气泡
具体实现步骤
- 全局气泡管理
在游戏主类中维护一个所有气泡的列表,每次生成气泡时加入,移除时同步删除:
class BubbleShooterGame extends FlameGame { final List<BaseBubble> bubbles = []; // 添加气泡时调用 void addBubble(BaseBubble bubble) { add(bubble); bubbles.add(bubble); } // 移除气泡时调用 void removeBubble(BaseBubble bubble) { bubble.removeFromParent(); bubbles.remove(bubble); } }
- 修改碰撞处理逻辑
在发射的气泡类的onCollision方法中,触发邻近气泡的收集与移除:
@override void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) { super.onCollision(intersectionPoints, other); // 仅处理同类型气泡的碰撞,排除自身 if (other is DogBubble && other != this) { final game = this.game as BubbleShooterGame; // 收集所有连通的同类型气泡 final connectedBubbles = _findConnectedSameTypeBubbles(other, game.bubbles); // 批量移除目标气泡 for (final bubble in connectedBubbles) { game.removeBubble(bubble); } // 移除发射的气泡本身 removeFromParent(); } }
- 实现BFS遍历连通气泡
添加私有方法执行广度优先搜索,找出所有相邻的同类型气泡:
List<BaseBubble> _findConnectedSameTypeBubbles(BaseBubble startBubble, List<BaseBubble> allBubbles) { final connected = <BaseBubble>[]; final visited = <BaseBubble>{}; final queue = Queue<BaseBubble>(); queue.add(startBubble); visited.add(startBubble); while (queue.isNotEmpty) { final current = queue.removeFirst(); connected.add(current); // 遍历所有气泡,筛选未访问、同类型且相邻的气泡 for (final bubble in allBubbles) { if (!visited.contains(bubble) && bubble.runtimeType == startBubble.runtimeType && current.position.distanceTo(bubble.position) <= current.radius + bubble.radius) { visited.add(bubble); queue.add(bubble); } } } return connected; }
代码说明
- 全局气泡列表:确保能访问到屏幕上所有气泡,避免遗漏连锁相邻的目标
- BFS遍历:从被击中气泡开始逐层扩散,确保所有直接/间接相邻的同类型气泡都被收集(比如A碰B、B碰C,击中A时A、B、C都会被移除)
- 批量移除:统一处理移除操作,避免遍历过程中修改列表引发异常
内容的提问来源于stack exchange,提问作者Mateo
相关产品推荐
相关产品推荐

