You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter游戏中即时检查全局游戏状态变量值?

解决Flutter游戏中点击操作即时触发状态检查的问题

你当前的问题核心在于:全局变量tapCount更新后,GameState组件没有收到状态变化通知,只有计时器触发setState时才会重新检查胜利条件。以下是两种可行的解决方法:

方法一:通过回调函数触发父组件状态更新

这种方法不需要修改全局变量的定义,通过给子组件添加回调,在点击时主动通知GameState刷新状态:

  1. 修改Dot组件,添加点击回调参数
class Dot extends StatefulWidget {
  final String itemText;
  final VoidCallback? onTapCallback; // 新增回调参数

  const Dot({super.key, required this.itemText, this.onTapCallback});

  @override
  State<Dot> createState() => _DotState();
}

class _DotState extends State<Dot> {
  bool tapped = false;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: increaseTap,
      child: tapped == false
          ? CircleAvatar(
              backgroundColor: randomColor(),
              radius: 10,
              child: Text(widget.itemText),
            )
          : const SizedBox(width: 20, height: 20),
    );
  }

  Color randomColor() {
    return Colors.primaries[Random().nextInt(Colors.primaries.length)];
  }

  void increaseTap() {
    global.tapCount++;
    setState(() {
      tapped = true;
    });
    widget.onTapCallback?.call(); // 点击时触发回调
  }
}
  1. 修改GameGrid组件,传递回调给每个Dot
class GameGrid extends StatelessWidget {
  final VoidCallback onTapCallback; // 新增回调参数

  const GameGrid({super.key, required this.onTapCallback});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Dot(itemText: '1', onTapCallback: onTapCallback),
            Dot(itemText: '2', onTapCallback: onTapCallback),
            Dot(itemText: '3', onTapCallback: onTapCallback),
            Dot(itemText: '4', onTapCallback: onTapCallback),
          ],
        ),
        // 其余Row中的Dot都按此方式添加onTapCallback参数
        // ...(省略重复代码)
      ],
    );
  }
}
  1. 在GameState中使用GameGrid时传入回调
    在getScreen方法里,返回GameGrid时传递触发setState的回调:
else if (timer > 0 && gameRunning == true) {
  return GameGrid(onTapCallback: () {
    setState(() {}); // 触发状态更新,重新检查胜利条件
  });
}

方法二:使用ValueNotifier管理全局状态(更优雅)

通过ValueNotifier可以让全局变量的变化自动通知UI更新,无需手动调用setState:

  1. 修改global.dart文件,用ValueNotifier替代普通变量
import 'package:flutter/foundation.dart';

final ValueNotifier<int> tapCount = ValueNotifier(0);
final ValueNotifier<int> timer = ValueNotifier(5);
  1. 修改Dot组件中的点击逻辑
void increaseTap() {
  global.tapCount.value++; // 更新ValueNotifier的值
  setState(() {
    tapped = true;
  });
}
  1. 修改GameState组件,监听变量变化
    用ValueListenableBuilder包裹页面内容,自动监听tapCount和timer的变化:
@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
        body: Container(
      color: Colors.black,
      child: Stack(
        children: [
          ValueListenableBuilder(
            // 合并多个监听对象,任意一个变化都会触发重建
            valueListenable: Listenable.merge([global.tapCount, global.timer]),
            builder: (context, _, __) {
              return getScreen(
                global.timer.value, 
                gameRunning, 
                global.tapCount.value
              );
            },
          ),
          debugWidget(),
        ],
      ),
    )),
  );
}
  1. 更新GameState中的变量操作逻辑
void setGameVarables() {
  setState(() {
    global.timer.value = 5;
    global.tapCount.value = 0;
    gameRunning = true;
    timerRunning = true;
  });
}

@override
void initState() {
  Timer.periodic(const Duration(seconds: 1), (Timer time) {
    if (gameRunning == true && timerRunning == true) {
      global.timer.value--; // 更新ValueNotifier的值
    }
  });
  SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
  super.initState();
}

效果说明

两种方法都能实现点击圆点后即时更新tapCount并检查胜利条件,一旦tapCount达到5,会立刻切换到下一级页面。方法一适合简单场景,方法二更适合需要全局状态管理的复杂游戏,代码更简洁易维护。

内容的提问来源于stack exchange,提问作者hefty_kat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:54:57