Home > Software design >  How to set timer for maze_game package?
How to set timer for maze_game package?

Time:06-14

I'm using maze pub package : https://pub.dev/packages/maze. I want to create mini game that will be counting time from opening this screen until getting at the finish line. So I tried to setting timer at the begining, but when I wanted to save this data to share prefs, i got 00:00, instead of time I get displayed on the screen.

class MazeScreen extends StatefulWidget {
  const MazeScreen({Key? key}) : super(key: key);

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

class _MazeScreenState extends State<MazeScreen> {
  Duration duration = Duration();
  Timer? timer ;

  @override
  void initState() {
    super.initState();

    startTimer();
  }

  void reset() {
    setState(() {
      timer?.cancel();
    });
  }

  void addTime() {
    const addSeconds = 1;

    setState(() {
      final seconds = duration.inSeconds   addSeconds;
      duration = Duration(seconds: seconds);
    });
  }

  void startTimer() {
    timer = Timer.periodic(Duration(seconds: 1), (_) => addTime());
  }

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final minutes = twoDigits(duration.inMinutes.remainder(60));
    final seconds = twoDigits(duration.inSeconds.remainder(60));
    return Scaffold(
      body: Stack(children: <Widget>[
        Container(
          // Here the height of the container is 45% of our total height
          height: size.height * .35,
          decoration: const BoxDecoration(
            color: Color(0xFF3d405b),
          ),
        ),
        SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    MemoryCard("time", "$minutes:$seconds"),
                  ],
                ),
                Expanded(
                  flex: 2,
                  child: Container(
                    alignment: AlignmentDirectional.center,
                    padding: const EdgeInsets.all(10.0),
                    child: const Text(
                      'Maze game',
                      style: TextStyle(
                        color: Color(0xFFe07a5f),
                        fontSize: 25.0,
                        fontStyle: FontStyle.italic,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  flex: 9,
                  child: Stack(
                    children: [
                      Container(
                        margin: const EdgeInsets.symmetric(vertical: 20.0),
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(16.0),
                          color: const Color(0xFFf4f1de),
                        ),
                      ),
                      Maze(
                        player: MazeItem(
                          'assets/start.png',
                          ImageType.asset,
                        ),
                        columns: 7,
                        rows: 7,
                        wallThickness: 3.0,
                        wallColor: const Color(0xFF81b29a),
                        finish: MazeItem(
                          'assets/finish.png',
                          ImageType.asset,
                        ),
                        onFinish: () async {
                          reset();
                          final prefs = await SharedPreferences.getInstance();
                          await prefs.setString("mazeTimer", '$minutes:$seconds');
                        },
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ]),
    );
  }
}

When I do it like that I receive 00:00.

CodePudding user response:

You would need to handle minute / second in the state as variables like you handle duration, which is where they belong as they represent a state.

Calculate them every time duration gets updated. These calculated values can then be displayed or used in this call:

await prefs.setString("mazeTimer", ... );

The reason 00:00 gets saved is that the function onFinish: () gets initialized once at the beginning, when when the final values of minute and second are actually 00:00.

Try something like this:

class _MazeScreenState extends State<MazeScreen> {
  Duration duration = Duration();
  Timer? timer ;
  String minutes = '00'; // it may be better to store an int, not a String
  String seconds = '00'; // it may be better to store an int, not a String

  ...

  void addTime() {
    const addSeconds = 1;

    setState(() {
      final seconds = duration.inSeconds   addSeconds;
      duration = Duration(seconds: seconds);

      minutes = ... // ADD CALCULATION HERE
      seconds = ... // ADD CALCULATION HERE
    });
  }
}

A second approach would be to calculate minutes and seconds here, but you would end up with having minutes / seconds multiple times in the code, which is redundant:

onFinish: () async {  
  reset();
  final prefs = await SharedPreferences.getInstance();
  final min = ... // CALCULATE HERE
  final sec= ... // CALCULATE HERE
  await prefs.setString("mazeTimer", '$min:$sec');
}
  • Related