0
\$\begingroup\$

I am creating an implementation of Snakes and ladders and I run into some issues.The game is updating too fast and I want to limit the framerate kinda,or make a pause so that the move is actually visible.I tried using Thread.sleep() but that created issues of its own.Have you solved any similar problems that could point me to the right direction? I have to point out that run method is in an abstract class and my actual game extends this abstract class

This is the game loop :

public void run() {
    init();
    this.requestFocus();
    long lastTime = System.nanoTime();
    double amountOfTicks = 60.0;
    double ns = 1000000000 / amountOfTicks;
    double delta = 0;
    long timer = System.currentTimeMillis();
    int updates = 0;
    int frames = 0;
    while (running) {
      long now = System.nanoTime();
      delta = delta + (now - lastTime) / ns;
      lastTime = now;
      while (delta >= 1) {
        update();
        updates++;
        delta--;
      }
      render();
      frames++;
      if (System.currentTimeMillis() - timer > 1000) {
        timer = timer + 1000;
        if (this.FPSLOG)
          System.out.println("FPS: " + frames + " " + "Ticks: " + updates);
        frames = 0;
        updates = 0;
      }
    }
    stop();
  }

The render method :

private void render() {
    BufferStrategy bs = this.getBufferStrategy();
    if (bs == null) {
      this.createBufferStrategy(3);
      return;
    }
    Graphics g = bs.getDrawGraphics();
    g.setColor(background);
    g.fillRect(0, 0, getWidth(), getHeight());
    draw(g);
    g.dispose();
    bs.show();
  }

The game implementation of those methods:

@Override
    public void init() {
        setBackground(Color.black);
        board = new Board();
        player = new Player(Color.cyan,board.getTiles()[0]);
        dice = new Random();
    }

    @Override
    public void draw(Graphics g) {
        board.draw(g);
        player.draw(g);
    }


    @Override
    public void update() {
        for (int i = 0; i < dice.nextInt(7)+1; i++) {
            player.move();
        }
    }
public void move(){
        this.currentTile = this.currentTile.getNext() == null ? this.currentTile : this.currentTile.getNext();
        this.xPos = this.currentTile.getxPos();
        this.yPos = this.currentTile.getyPos();
    }
\$\endgroup\$
  • \$\begingroup\$ The most important code is missing: how do you update the player? \$\endgroup\$ – Alexandre Vaillancourt Apr 30 at 1:41
  • \$\begingroup\$ Its kinda irrelevant but ill update it.The player is standing on a Tile object,the Tile object has a pointer to its next Tile so the move just moves the player to the next tile. \$\endgroup\$ – Yosoku Denkai Apr 30 at 3:08
  • \$\begingroup\$ It looks like you are trying to call update() once per second. Is that what is happening? \$\endgroup\$ – Jay Apr 30 at 3:49
  • \$\begingroup\$ Yes,i update once per second and I render as much as I can.I copied this game loop from a source I cant recall.What I want to do is :The dice is thrown->The player moves(But way slower that it does now)->When the player finishes moving then the dice is rethrown.One kinda-fix i implemented is a button for throwing the dice,so the player doesnt just go to the finish line,but he needs to rehit the button to throw the dice.That didnt solve my problem with the player moving too fast tho \$\endgroup\$ – Yosoku Denkai Apr 30 at 4:05
  • \$\begingroup\$ Hmm, that's odd, this looks to me like it's updated 60 times per second... Maybe I'm too tired to think. \$\endgroup\$ – Alexandre Vaillancourt Apr 30 at 4:19
0
\$\begingroup\$

The variable double amountOfTicks = 60.0; seems to be what's controlling your update rate. You might want to reduce that, this will update your logic less often, while keeping the same render rate.

Also, there is an issue with the update() function: each time you call the dice.nextInt(7) method, you generate a new value, changing the upper bound of your loop every iteration. I'm not sure this is what you expect. Also, you move your player many times per frame, which does not help your situation (all the loop iterations are performed in the same frame).

// The iterations of this loop 
for (int i = 0; i < dice.nextInt(7)+1; i++) {
    player.move();
}

// will look like this:
i = 0; dice.nextInt(7)+1 = 8; i < number? true
i = 1; dice.nextInt(7)+1 = 5; i < number? true
i = 2; dice.nextInt(7)+1 = 4; i < number? true
i = 3; dice.nextInt(7)+1 = 2; i < number? false

It is very unlikely that i will ever reach 7.

I suggest you add a new movesLeftThisTurn variable to your player, as well as a famesTillNextRoll variable. Once you roll the dice, you stick the value in movesLeftThisTurn, and you decrement it by one each frame that you move. Once it gets to 0, set the other variable to 5, and decrease it by one each frame. Once it gets to 0, roll the dice for movesLeftThisTurn and start over again.

Here is something like what I have in mind:

public void update() {
    if (player.movesLeftThisTurn > 0) {
        player.move();
        player.movesLeftThisTurn -= 1;

        if (player.movesLeftThisTurn == 0)
          player.famesTillNextRoll = 5; // This will pause the player at the current tile for 5 frames
    }
    else {
        if (player.famesTillNextRoll > 0)
            player.famesTillNextRoll -= 1; // Do nothing...

        if (player.famesTillNextRoll == 0)
            player.movesLeftThisTurn = dice.nextInt(7) + 1;
    }
}
\$\endgroup\$
  • \$\begingroup\$ That was a pretty nice notice I never realised about the for loop.I kinda see what you're going with here but I am not quite sure I have the full grasp of it.I will implement what I think you are going with and let you know with the results. \$\endgroup\$ – Yosoku Denkai Apr 30 at 4:22
  • \$\begingroup\$ Sure :) I'll update that tomorrow morning! \$\endgroup\$ – Alexandre Vaillancourt Apr 30 at 4:23
  • \$\begingroup\$ So the solution I thought you proposed didn't have any results,probably the implementation wasn't your exact thought.I tried this: I reduced amountOfTicks (in run) which is how many updates are done per second.I reduced that to 5 and the results were what I wanted.The player takes slow steps and everyone is happy.I dont need that many updates for a Snakes and ladders.I have another question tho,was that bad practice?What is the difference between FPS and updates in a game?I ask you because I saw you are involved a lot in gamedev.Its not part of my job but I like making games in my spare time \$\endgroup\$ – Yosoku Denkai Apr 30 at 4:44
  • \$\begingroup\$ Sometimes the FPS is linked to the "step" or "tick" or "update": one simulation step/tick/update -> one frame rendered. This is often the most simple way of programming games. In those cases, there is no real distinction between the "update" and the "render", meaning that "FPS" will apply to both. If you disconnect both concept, then you'll have to agree with your team what is a "frame". Is it a simulation frame, or a rendering frame? If it adds confusion, then keep "frame" for the rendering, and "tick" or "step" or "update" for the game logic (including the physics). \$\endgroup\$ – Alexandre Vaillancourt May 2 at 0:15
  • \$\begingroup\$ @YosokuDenkai I have updated my answer. Maybe it makes more sense to you now :) \$\endgroup\$ – Alexandre Vaillancourt May 2 at 0:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.