英文:
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'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('Next Level'),
),
],
),
);
}
//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'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 && timerRunning == true) {
global.timer -= .1;
}
});
});
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论