2

I have this game loop where I have a red rectangle and a yellow rectangle on top of it. When a player takes damage, the yellow rectangle's width decreases because it is based on player's life. When player's life reaches zero he loses the game and all animations are cancelled. The issue I am having is that because the loop is so quick, the yellow rectangle does not have time to lower the life to zero and a bit of it is left on the screen when the animations are cancelled. For that reason I need to add a bit of delay before cancelling the animations. Thanks guys.

// DECREASE PLAYER LIFE AND DELETE ENEMY IF IT COLIDES WITH PLAYER
    enemyArray.forEach(function(enemy) {
    if (collides(player, enemy)) {
        player.life += -10;
        enemy.delete();
    }
    });

      // ANIMATION LOOP

      function animate(currentTime) {
        const animation = requestAnimationFrame(animate);
        c.clearRect(0, 0, canvas.width, canvas.height);



        // PLAYER LIFE
        // RED REC
        c.beginPath();
        c.rect(20, 20, 150, 30);
        c.fillStyle = "red";
        c.fillRect(10, 30, 200, 20);
        // YELLOW REC
        c.beginPath();
        c.rect(20, 20, 150, 30);
        c.fillStyle = "yellow";
        c.fillRect(10, 30, player.life, 20);


        // END GAME

       //I need some delay here so that fillRect has time to decrease the yellow bar to 0;
        if (player.life <= 0) {
          console.log("You Lose");
          music.pause();
          paused = true;
          cancelAnimationFrame(animation);
        }
      }
      animate();

Image of player life bar when animations are canceled. There is a bit left still.

2
  • 1
    It might be that player.life is a non 0, something like a negative number which will cause a visible render. Add this line before cancelAnimationFrame, c.fillRect(10, 30, 0, 20); Commented Feb 8, 2019 at 0:52
  • Hi Burimi, player's life is a variable that I set to be equal 50 and for each hit player takes from enemies, it loses 10 life. So it will never be a negative number. I also logged player life to make sure there no weird thing going on and there isn't. Commented Feb 8, 2019 at 1:10

1 Answer 1

1

You haven't really explained what the game logic looks like. But I suspect perhaps all you need to do is to move the game logic that is causing damage to above the rendering, instead of after.

Edit: As mentioned in the comments, if player life is allowed to turn negative, it can also cause the image you are showing, in that case you can add a Math.max(value,0) to the render

 // ANIMATION LOOP

  function animate(currentTime) {
    const animation = requestAnimationFrame(animate);
    c.clearRect(0, 0, canvas.width, canvas.height);

    // Move game logic that decreases player life to here.

    // PLAYER LIFE
    // RED REC
    c.beginPath();
    c.rect(20, 20, 150, 30);
    c.fillStyle = "red";
    c.fillRect(10, 30, 200, 20);
    // YELLOW REC
    c.beginPath();
    c.rect(20, 20, 150, 30);
    c.fillStyle = "yellow";
    c.fillRect(10, 30, Math.max(player.life,0) , 20); // prevent negative value


    // Is game logic that decreases player life here?
    // END GAME

   //I need some delay here so that fillRect has time to decrease the yellow bar to 0;
    if (player.life <= 0) {
      console.log("You Lose");
      music.pause();
      paused = true;
      cancelAnimationFrame(animation);
    }
  }
  animate();

Typically you would organize your code something like this.

var paused=false;
  // Game Logic
function update()
{
  enemyArray.forEach(function(enemy) {
  if (collides(player, enemy)) {
      player.life += -10;
      enemy.delete();
  }
  });
  if (player.life <= 0) {
    console.log("You Lose");
    music.pause();
    paused = true;
  }
}
// Render
function draw()
{
  c.clearRect(0, 0, canvas.width, canvas.height);
  // PLAYER LIFE
  // RED REC
  c.beginPath();
  c.rect(20, 20, 150, 30);
  c.fillStyle = "red";
  c.fillRect(10, 30, 200, 20);
  // YELLOW REC
  c.beginPath();
  c.rect(20, 20, 150, 30);
  c.fillStyle = "yellow";
  c.fillRect(10, 30, Math.max(player.life,0) , 20); // prevent negative value
}
 
 // Animation Loop
function animate(currentTime) {
  update();
  draw();
  if (!paused)
    const animation = requestAnimationFrame(animate);
}
animate();

Sign up to request clarification or add additional context in comments.

2 Comments

Hello visibleman, below you can see the logic that damages player on collision with enemy (enemies don't shoot at players yet). Since it is a forEach, I don't think I can put it inside the loop. I am going to try though. By the way, is there a way to delay this animation cancelling like I asked? (code doesnt look good here, I will add it to my question.
@RandalAndrade, I updated with an example of how you can reorganize your game loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.