2

With this code I expect the bird to fall down with minimum speed on colliding with the pillar but the bird falls down in the blink of an eye - it's too quick. Is there any way to resolve this issue?

console.log("welcome to flappygame.js 2023");
let canvas = document.getElementById("board");
let boardwidth = 700;
let boardheight = 640;
let speed = 0.6;
let score = 0;
let velocityX = -4;
let gravity = 0.4;
gameover = false;
let startgame = false;
let txt = 'press arrowup key or spacebar to start..'

canvas.width = boardwidth;
canvas.height = boardheight;
let context = canvas.getContext("2d");
let lastpainted = 0;
let pipearry = [];
let keypressed = false;
let hit = false;
let pipe;

let bird = {
  X: boardwidth / 8,
  Y: boardheight / 2,
  width: 48,
  height: 40,
};

//load images
img_bird = new Image();
img_bird.src = "./flappybird.png";
img_bird.onload = function() {
  context.drawImage(img_bird, bird.X, bird.Y, 50, 40);
};

img_top = new Image();
img_top.src = "./toppipe.png";

img_btm = new Image();
img_btm.src = "./bottompipe.png";
let velocityY = 0;
//clear the canvas per interval to draw
function refresh() {
  window.requestAnimationFrame(refresh);
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.drawImage(img_bird, bird.X, bird.Y, 50, 40);

  //logic for bird on colliding with pillar
  if (gameover == true) {
    while (bird.Y < canvas.height / 1.2) {
      console.log(bird.Y)
      bird.Y += gravity;
    }

    pipearry.forEach((e) => {
      context.drawImage(e.img, e.X, e.Y, e.width, e.height);
    })
    context.fillText(score, 5, 45);
    return;
  }
  for (let i = 0; i < pipearry.length; i++) {
    pipe = pipearry[i];
    context.drawImage(pipe.img, pipe.X, pipe.Y, pipe.width, pipe.height);
    pipe.X += velocityX;

    if (pipe.passed == false && bird.X > pipe.X + pipe.width) {
      score += 1;
      pipe.passed = true;
    }

    if (detectcollision(bird, pipe)) {
      gameover = true;
    };
  }
  if (bird.Y > boardheight / 1.23) gameover = true;

  velocityY += gravity;
  if (keypressed == true) {
    bird.Y += velocityY;
  } else {
    bird.Y += velocityY;
  }

  context.fillstyle = "white";
  context.font = "45px sans-serif";
  context.fillText(score, 5, 45);
}

function animate(ctx) {
  window.requestAnimationFrame(animate);
  let painted = (ctx - lastpainted) / 1000;
  if (painted < 1 / speed) return;
  lastpainted = ctx;
  create_pipe();
}

//The initial torque to start the game
let data = setInterval(start_game, 500);

function start_game() {
  if (startgame == true) {
    window.requestAnimationFrame(refresh);
    window.requestAnimationFrame(animate);
    clearInterval(data);
  } else {
    context.fillstyle = "black";
    context.font = "20px sans-serif";
    context.fillText(txt, boardwidth / 9, boardheight / 2.5);
  }
}

function create_pipe() {
  let randomY = 0 - 512 / 2 - (Math.random() * 512) / 4;
  let gap = 110;
  let tpipe = {
    img: img_top,
    X: 700,
    Y: randomY,
    width: 64,
    height: 512,
    passed: false,
  };

  let bpipe = {
    img: img_btm,
    X: 700,
    Y: randomY + 512 + gap,
    width: 64,
    height: 512,
  };
  pipearry.push(tpipe, bpipe);
}

window.addEventListener("keydown", (e) => {
  if (e.code == "Space" || e.code == "ArrowUp") velocityY = -6;
  keypressed = true;
  startgame = true;
});

window.addEventListener("keyup", keyup)

function keyup() {
  keypressed = false;
};

window.addEventListener("touchstart", () => {
  keypressed = true;
});

window.addEventListener("touchend", () => {
  keypressed = false;
});

function detectcollision(b, p) {
  return b.X < p.X + p.width &&
    b.X + b.width > p.X &&
    b.Y < p.Y + p.height &&
    b.Y + b.height > p.Y;
}
Andy
  • 61,948
  • 13
  • 68
  • 95
Rahan Ajai
  • 87
  • 7

1 Answers1

2

I think your problem is here:

  if (gameover == true) {
    while (bird.Y < canvas.height / 1.2) {
      console.log(bird.Y)
      bird.Y += gravity;
    }

You are changing the bird position inside the while, without waiting for the next frame to load, so the bird is teleported to the bottom in a single frame. To avoid it, change the while(bird.Y < canvas.height / 1.2) {...} by this:

    if (bird.Y < canvas.height / 1.2) {
      console.log(bird.Y);
      velocityY += gravity;
      bird.Y += velocityY;
    }

Link with full code: stackblitz.com/edit/web-platform-v4qvxa?file=flappy.js

Mystery
  • 61
  • 4
  • Is there any way to solve it – Rahan Ajai Apr 23 '23 at 17:22
  • @RahanAjai I think you could change the while by an if and just skip to the next frame. And add another if to check when the bird hit the bottom of window, to then show the game over screen. If you could send your code on stackblitz it would be easier to test it. I tried to run it but I don't have the html or the images used. – Mystery Apr 23 '23 at 18:54
  • will soon provide you with the HTML and images in stack blitz – Rahan Ajai Apr 24 '23 at 14:23
  • here's the link https://stackblitz.com/edit/web-platform-ukhman?file=index.html – Rahan Ajai Apr 24 '23 at 14:44
  • 1
    @RahanAjai sorry for the delay, here is the stack blitz with the changes: https://stackblitz.com/edit/web-platform-v4qvxa?file=flappy.js – Mystery Apr 27 '23 at 16:42