Search code examples
flutterandroid-studiodarterror-handlingflutter-layout

jumping speed keeps increasing in flutter


I was building a flutter project ( a small game) where my container(player) can jump when barriers came to it I was able to make a jump using the code below but every time pressed jump it keeps getting faster and faster I don't think the issue is with variables I can't figure out what is happening (there were no errors in the code)

the jump part of code is made bold to make it easy to find for you

import 'dart:async';

import 'package:Buckly/extensions/player.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:Buckly/extensions/neu_box.dart';

import 'extensions/Arrow_button.dart';

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

  @override
  State<lvl_one> createState() => _lvl_oneState();
}

class _lvl_oneState extends State<lvl_one> {
  //player variable
  static double positionx = 0;
  static double positiony = 1;
  double time = 0;
  double height = 0;
  double vel = 0;
  int duration = 50;
  double initial_height = positiony;

  void moveleft() {
    setState(() {
      if (positionx - 0.1 < -1) {
        //nothing
      } else {
        positionx -= 0.1;
      }
    });
  }

  void moveright() {
    setState(() {
      if (positionx + 0.1 > 1) {
        //nothing
      } else {
        positionx += 0.1;
      }
    });
  }

  void prejump() {
    time = 0;
    positiony = 1;
    height = 0;
    initial_height = 1;
    duration = 50;
  }

  **void jump() {
    setState(() {
      prejump();
    });
    Timer.periodic(Duration(milliseconds: duration), (timer) {
      time += 0.05;
      height = -5 * time * time + 5 * time;
      if (initial_height - height > 1) {
        setState(() {
          positiony = 1;
        });
      } else {
        setState(() {
          positiony = initial_height - height;
          print("time is ${time}");
        });
      }
    });
    setState(() {
      prejump();
    });
  }**

  @override
  Widget build(BuildContext context) {
    double size = MediaQuery
        .of(context)
        .size
        .width;
    return SafeArea(
      child: Column(
        children: [
          Expanded(flex: 3,
              child: Container(
                width: size, color: Colors.purple,
                child: Stack(
                  children: [
                    player(positionx: positionx, positiony: positiony,),
                  ],
                ),
              )),
          Container(height: 10, color: Colors.blueGrey,),
          Expanded(flex: 1,
              child: Container(
                width: size, color: Colors.pink,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    SizedBox(height: 50,
                        width: 50,
                        child: NeuBox(
                          child: Icon(Icons.arrow_left), function: moveleft,)),
                    SizedBox(height: 50,
                        width: 50,
                        **child: NeuBox(child: Icon(Icons.arrow_drop_up_outlined),
                          function: jump,)),**
                    SizedBox(height: 50,
                        width: 50,
                        child: NeuBox(child: Icon(Icons.arrow_right_outlined),
                          function: moveright,)),
                  ],
                ),
              )),
        ],
      ),
    );
  }
}

Solution

  • Because you use Timer.periodic(.. inside your void jump() function and it will create a new timer every time you call it.

    You can try to print something like this inside the callback function:

    Timer.periodic(Duration(milliseconds: duration), (timer) {
      print("time is ${time}");
      time += 0.05;
      ...
    

    You will soon figure out that the time += 0.5 which should be call one in every 50 milliseconds become called twice (or more).

    One way is move the Timer.periodic into the initial state and use prejump to jump.

      @override
      void initState() {
        Timer.periodic(Duration(milliseconds: duration), (timer) {
          print("time is ${time}");
          time += 0.05;
          height = -5 * time * time + 5 * time;
          if (initial_height - height > 1) {
            setState(() {
              positiony = 1;
            });
          } else {
            setState(() {
              positiony = initial_height - height;
            });
          }
        });
        super.initState();
      }
    
    
      void prejump() {
        time = 0;
        positiony = 1;
        height = 0;
        initial_height = 1;
        duration = 50;
      }
    
      void jump() {
        setState(() {
          prejump();
        });
      }