如何立即检查游戏状态全局变量的值?

huangapple go评论75阅读模式
英文:

How to check game state globals for values instantly?

问题

我正在使用Flutter制作一个游戏。我有一些全局变量来跟踪玩家是否点击了一些点。但我意识到它只会与全局计时器一起更新全局值,并不会立即触发胜利条件或立即注册点击。

是否有办法让全局点击变量在点击时立即更新和检查,以便立即触发胜利条件?我也知道我的计时器有点问题,但目前它可以工作。

Player Grid(玩家网格)

import 'dart:math';

import 'package:flutter/material.dart';

import 'global.dart' as global;

class Dot extends StatefulWidget {
  final String itemText;

  const Dot({Key? key, required this.itemText});

  @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;
    });
  }
}

class GameGrid extends StatelessWidget {
  const GameGrid({Key? key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '1'),
            Dot(itemText: '2'),
            Dot(itemText: '3'),
            Dot(itemText: '4'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '5'),
            Dot(itemText: '6'),
            Dot(itemText: '7'),
            Dot(itemText: '8'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '9'),
            Dot(itemText: '10'),
            Dot(itemText: '11'),
            Dot(itemText: '12'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '13'),
            Dot(itemText: '14'),
            Dot(itemText: '15'),
            Dot(itemText: '16'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '17'),
            Dot(itemText: '18'),
            Dot(itemText: '19'),
            Dot(itemText: '20'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '21'),
            Dot(itemText: '22'),
            Dot(itemText: '23'),
            Dot(itemText: '24'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: const [
            Dot(itemText: '25'),
            Dot(itemText: '26'),
            Dot(itemText: '27'),
            Dot(itemText: '28'),
          ],
        ),
      ],
    );
  }
}

这是我开始构建游戏状态管理的地方。

Game State(游戏状态)

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'global.dart' as global;
import 'package:flutter/services.dart';
import 'gamegrid.dart';

class GameState extends StatefulWidget {
  const GameState({Key? key});

  @override
  _GameStateState createState() => _GameStateState();
}

class _GameStateState extends State<GameState> {
  //Game Loop Variables
  bool gameRunning = false;
  bool timerRunning = false;

  @override
  void initState() {
    Timer.periodic(const Duration(seconds: 1), (Timer time) {
      setState(() {
        if (gameRunning == true && timerRunning == true) {
          global.timer--;
        }
      });
    });

    // 隐藏Android状态栏
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);

    super.initState();
  }

  void setGameVariables() {
    setState(() {
      global.timer = 5;
      global.tapCount = 0;
      gameRunning = true;
      timerRunning = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          color: Colors.black,
          child: Stack(
            children: [
              getScreen(global.timer, gameRunning, global.tapCount),
              debugWidget(),
            ],
          ),
        ),
      ),
    );
  }

  //获取屏幕
  Widget getScreen(int timer, bool gameRunning, int tapCount) {
    if (timer > 0 && gameRunning == true && tapCount == 5) {
      return nextLevel();
    } else if (timer > 0 && gameRunning == true) {
      return const GameGrid();
    } else if (gameRunning == true && timer < 0 || timer == 0) {
      return gameOver();
    } else {
      return menu();
    }
  }

  //菜单
  Widget menu() {
    return Center(
      child: TextButton(
        style: TextButton.styleFrom(
          textStyle: const TextStyle(fontSize: 20),
        ),
        onPressed: setGameVariables,
        child: const Text('Play Glo'),
      ),
    );
  }

  //下一关屏幕
  Widget nextLevel() {
    setState(() {
      timerRunning = false;
    });

    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TextButton(
            style: TextButton.styleFrom(
              textStyle: const TextStyle(fontSize: 20),
            ),
            onPressed: setGameVariables,
            child: const Text('Next Level'),
          ),
        ],
      ),
    );
  }

  //游戏结束屏幕
  Widget gameOver() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text(
            'GAME OVER',
            style: TextStyle(fontSize: 20),
          ),
          TextButton(
            style: TextButton.styleFrom(
              textStyle: const TextStyle(fontSize: 20),
            ),
            onPressed: setGameVariables,
            child: const Text('Play Again'),
          ),
          TextButton(
            style: TextButton.styleFrom(
              textStyle: const TextStyle(fontSize: 20),
            ),
            onPressed: () {
              setState(() {
                gameRunning = false;
                timerRunning = false;
              });
            },
            child: const Text('Main Menu'),
          ),
        ],
      ),
    );
  }

  Widget debugWidget() {
    if (kDebugMode) {
      return Positioned(
        left: 

<details>
<summary>英文:</summary>

I am messing with a game in Flutter. I have a few global variables that keep track of if the player clicked some dots or not. But I realized that it only updates the global values in tandem with the global timer and doesn&#39;t trigger the win condition instantly or register a tap instantly. 

Is there a way for the global tap variable to update and check at time of tapping so that it triggers the win condition right away? I also know my timer is a little wonky but it works for now.

***Player Grid***

import 'dart:math';

import 'package:flutter/material.dart';

import 'global.dart' as global;

class Dot extends StatefulWidget {
final String itemText;

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

@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;
});
}
}

class GameGrid extends StatelessWidget {
const GameGrid({super.key});

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '1'),
Dot(itemText: '2'),
Dot(itemText: '3'),
Dot(itemText: '4'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '5'),
Dot(itemText: '6'),
Dot(itemText: '7'),
Dot(itemText: '8'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '9'),
Dot(itemText: '10'),
Dot(itemText: '11'),
Dot(itemText: '12'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '13'),
Dot(itemText: '14'),
Dot(itemText: '15'),
Dot(itemText: '16'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '17'),
Dot(itemText: '18'),
Dot(itemText: '19'),
Dot(itemText: '20'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '21'),
Dot(itemText: '22'),
Dot(itemText: '23'),
Dot(itemText: '24'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Dot(itemText: '25'),
Dot(itemText: '26'),
Dot(itemText: '27'),
Dot(itemText: '28'),
],
),
],
);
}
}


This is where I started building the game state management
***Game State***

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'global.dart' as global;

import 'package:flutter/services.dart';
import 'gamegrid.dart';

class GameState extends StatefulWidget {
const GameState({super.key});

@override
// ignore: library_private_types_in_public_api
_GameStateState createState() => _GameStateState();
}

class _GameStateState extends State<GameState> {
//Game Loop Variables
bool gameRunning = false;
bool timerRunning = false;

@override
void initState() {
Timer.periodic(const Duration(seconds: 1), (Timer time) {
setState(() {
if (gameRunning == true && timerRunning == true) {
global.timer--;
}
});
});

//Hide android status bar
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
super.initState();

}

void setGameVarables() {
setState(() {
global.timer = 5;
global.tapCount = 0;
gameRunning = true;
timerRunning = true;
});
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
color: Colors.black,
child: Stack(
children: [
getScreen(global.timer, gameRunning, global.tapCount),
debugWidget(),
],
),
)),
);
}

//Get Screen
Widget getScreen(int timer, bool gameRunning, int tapCount) {
if (timer > 0 && gameRunning == true && tapCount == 5) {
return nextLevel();
} else if (timer > 0 && gameRunning == true) {
return const GameGrid();
} else if (gameRunning == true && timer < 0 || timer == 0) {
return gameover();
} else {
return menu();
}
}

//Menu
Widget menu() {
return Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: setGameVarables,
child: const Text('Play Glo'),
),
);
}

//Next Level Screen
Widget nextLevel() {
setState(() {
timerRunning = false;
});

return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: setGameVarables,
child: const Text(&#39;Next Level&#39;),
),
],
),
);

}

//GAME OVER SCREEN
Widget gameover() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'GAME OVER',
style: TextStyle(fontSize: 20),
),
TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: setGameVarables,
child: const Text('Play Again'),
),
TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
setState(() {
gameRunning = false;
timerRunning = false;
});
},
child: const Text('Main Menu'),
),
],
),
);
}

Widget debugWidget() {
if (kDebugMode) {
return Positioned(
left: 0,
top: 50,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
children: [
Text(
'Timer: ${global.timer}',
style: const TextStyle(fontSize: 32, color: Colors.white),
),
Text(
'Taps: ${global.tapCount}',
style: const TextStyle(fontSize: 32, color: Colors.white),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'GR: $gameRunning',
style: const TextStyle(fontSize: 32, color: Colors.white),
),
Text(
'TR: $timerRunning',
style: const TextStyle(fontSize: 32, color: Colors.white),
),
],
),
],
),
);
} else {
return Container();
}
}
}


I was expecting the state to update and check for update instantly.
</details>
# 答案1
**得分**: 0
Timer.periodic(const Duration(milliseconds: 100), (Timer time) {
setState(() {
if (gameRunning == true && timerRunning == true) {
global.timer -= .1;
}
});
});
<details>
<summary>英文:</summary>
For some reason I didn&#39;t realize/think that using a double for the timer and updating milliseconds would work. Facepalm moment
Timer.periodic(const Duration(milliseconds: 100), (Timer time) {
setState(() {
if (gameRunning == true &amp;&amp; timerRunning == true) {
global.timer -= .1;
}
});
});
</details>

huangapple
  • 本文由 发表于 2023年8月4日 02:40:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76830831.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定