Flutter/Dart游戏开发:角色血量实时更新的数据流实现问询
解决方案
一、场景适配判断
你的场景不需要引入Bloc框架,用**简单的StreamController**就能实现需求,轻量且足够解决实时更新血量的问题。
二、具体实现步骤
1. 定义血量更新事件类
先创建一个用于传递更新信息的类,用来告诉UI哪个格子的血量发生了变化:
class HealthUpdate { final int row; final int col; final int newHealth; HealthUpdate(this.row, this.col, this.newHealth); }
2. 在棋盘State类中初始化StreamController
在棋盘页面的State类里,添加StreamController相关代码,用于管理血量更新的流:
class _BoardPageState extends State<BoardPage> { // 广播式控制器,支持多个监听者 final StreamController<HealthUpdate> _healthUpdateController = StreamController<HealthUpdate>.broadcast(); late List<List<CharacterModel>> board; int? selectedRow; int? selectedColumn; @override void dispose() { // 页面销毁时关闭控制器,避免内存泄漏 _healthUpdateController.close(); super.dispose(); } // 处理双击减血的逻辑 void damageModel(int row, int col) { if (board[row][col].currentHealth > 0) { final newHealth = board[row][col].currentHealth - 1; board[row][col].currentHealth = newHealth; // 发送更新事件到流中,通知UI刷新 _healthUpdateController.add(HealthUpdate(row, col, newHealth)); } } void modelSelected(int row, int col) { setState(() { selectedRow = row; selectedColumn = col; }); }
3. 修改棋盘的Build方法
用StreamBuilder监听流的变化,触发UI更新:
@override Widget build(BuildContext context) { return Scaffold( body: StreamBuilder<HealthUpdate>( // 初始数据避免页面加载时显示加载框 initialData: HealthUpdate(-1, -1, 0), stream: _healthUpdateController.stream, builder: (context, snapshot) { return GridView.builder( itemCount: 8 * 8, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 8), itemBuilder: (context, index) { int row = index ~/ 8; int col = index % 8; bool isSelected = selectedRow == row && selectedColumn == col; return Square( tile: board[row][col], isSelected: isSelected, onTap: () => modelSelected(row, col), // 传递当前格子的行列信息 onDoubleTap: () => damageModel(row, col), ); }, ); }, ), ); } }
4. 修复Square组件的问题
你的Square组件存在变量定义错误,同时无需额外传递currentHealth,直接使用tile内的属性即可:
Widget build(BuildContext context) { String selectedImage = tile!.imagePath; if (isSelected) { selectedImage = './lib/images/dungeon_tile_1.png'; } return GestureDetector( onDoubleTap: onDoubleTap, onTap: onTap, child: Stack( children: [ Container( child: tile != null ? Image.asset(selectedImage) : null, ), // 简化条件判断写法 if (tile!.currentHealth > 0) Align( alignment: Alignment.bottomRight, child: Padding( padding: EdgeInsets.all(10), child: Text( tile!.currentHealth.toString(), style: const TextStyle( color: Colors.red, fontWeight: FontWeight.bold, fontSize: 20, ), ), ), ), ], ), ); }
三、为什么不用Bloc?
Bloc适合复杂状态管理场景(比如多页面共享状态、多层业务逻辑拆分),你的需求只是单个页面内的格子血量更新,用StreamController完全足够,代码更简洁,不需要额外引入依赖。
内容的提问来源于stack exchange,提问作者Bisclavret
相关产品推荐
相关产品推荐

