如何在Flame中实现类老虎机的无限列表滚动效果?
Flame 老虎机无限滚动实现方案
1. 封装可复用的 SlotColumn 组件
把单列的滚动、组件管理逻辑封装成独立组件,彻底解决多列重复代码的问题。创建三列只需要实例化三次,传不同位置参数即可。
import 'dart:math'; import 'package:flame/components.dart'; import 'package:flame/game.dart'; class SlotColumn extends PositionComponent { final List<Sprite> sprites; final Vector2 gemSize; double scrollSpeed; // 滚动速度(像素/秒),支持动态调整 final List<GemComponent> _currentGems = []; SlotColumn({ required this.sprites, required this.gemSize, required this.scrollSpeed, required super.position, }) : super(size: gemSize); @override Future<void> onLoad() async { super.onLoad(); // 初始化填充足够宝石,覆盖可视区域+预加载2行避免空白 _fillColumn(); } void _fillColumn() { final neededCount = (game.size.y / gemSize.y).ceil() + 2; while (_currentGems.length < neededCount) { final randomSprite = sprites[Random().nextInt(sprites.length)]; final lastGemY = _currentGems.isEmpty ? 0 : _currentGems.last.position.y + gemSize.y; final newGem = GemComponent( gemSprite: randomSprite, gemSize: gemSize, gemPosition: Vector2(0, lastGemY), ); _currentGems.add(newGem); add(newGem); } } @override void update(double dt) { super.update(dt); // 处理整体滚动偏移 position.y += scrollSpeed * dt; // 移除完全滚出屏幕顶部的组件 _currentGems.removeWhere((gem) { final gemGlobalY = gem.position.y + position.y; if (gemGlobalY < -gemSize.y) { gem.removeFromParent(); return true; } return false; }); // 补充新组件到列底部,保持无限滚动 _fillColumn(); } } // 假设你的GemComponent实现如下(可根据实际调整) class GemComponent extends SpriteComponent { GemComponent({ required Sprite gemSprite, required Vector2 gemSize, required Vector2 gemPosition, }) : super( sprite: gemSprite, size: gemSize, position: gemPosition, ); }
2. 在游戏类中快速创建多列
现在创建三列只需要几行代码,完全不需要重复逻辑:
class SlotMachineGame extends FlameGame { late List<Sprite> _sprites; final Vector2 gemSize = Vector2(100, 100); final double baseScrollSpeed = 250; @override Future<void> onLoad() async { super.onLoad(); // 加载宝石精灵资源 _sprites = await Future.wait([ Sprite.load('gem_red.png'), Sprite.load('gem_blue.png'), Sprite.load('gem_green.png'), ]); // 创建三列,设置不同x轴位置 add(SlotColumn( sprites: _sprites, gemSize: gemSize, scrollSpeed: baseScrollSpeed, position: Vector2(60, 0), )); add(SlotColumn( sprites: _sprites, gemSize: gemSize, scrollSpeed: baseScrollSpeed, position: Vector2(220, 0), )); add(SlotColumn( sprites: _sprites, gemSize: gemSize, scrollSpeed: baseScrollSpeed, position: Vector2(380, 0), )); } }
关键逻辑说明
- 复用性:SlotColumn封装了单列所有核心逻辑,多列仅需传递不同位置参数,彻底消除重复代码。
- 替代MoveEffect:放弃MoveEffect改用
update方法手动控制滚动,不仅能灵活调整速度,还能同步处理组件的增删,更适合无限滚动场景。 - 无限滚动核心:
_fillColumn自动判断组件数量,不足时补充新宝石;update中移除出界组件,保持列的持续填充。 - 扩展性:如果需要实现老虎机拉杆后的减速停止效果,只需给SlotColumn添加
targetSpeed变量,在update中逐步把scrollSpeed过渡到0即可。
内容的提问来源于stack exchange,提问作者matti peterbull
相关产品推荐
相关产品推荐

