Object turns into undefined when passed to function as argument and method is called JavaScript

I’m currently learning some JavaScript for my web and I’m building a simple pong game. This is my main file (a canvas with its context, 4 objects that make the game and an animation function to update and draw them):

const canvas = document.getElementById("game_canvas");
const ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = canvas.width/2;
const table = new Table(canvas.width, canvas.height);
const ball = new Ball(canvas.width/2, canvas.height/2, canvas.width/200);
const pad1 = new Pad( canvas.width/20,  canvas.height/2, canvas.width/100, canvas.height/5, true);
const pad2 = new Pad(canvas.width*19/20, canvas.height/2, canvas.width/100, canvas.height/5);

animate();

function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  result = ball.update(canvas.width, canvas.height, pad1, pad2);
  pad1.update(canvas.height);
  pad2.update(canvas.height);
  ball.draw(ctx);
  pad1.draw(ctx);
  pad2.draw(ctx);
  table.draw(ctx);
  requestID = requestAnimationFrame(animate);
  switch (result) {
    case 1:
      cancelAnimationFrame(requestID);
      confirm("You lost!");
      break;
    case 2:
      cancelAnimationFrame(requestID);
      confirm("You won!");
      break;
  }
}

This works perfectly. The problem comes because I would like to let the player star over when the game ends, my solution is to put all of the definitions inside a function star_game() and pass the objects as arguments to the animate function:

start_game();

function start_game() {

  const canvas = document.getElementById("game_canvas");
  const ctx = canvas.getContext("2d");
  canvas.width = 600;
  canvas.height = canvas.width/2;
  const table = new Table(canvas.width, canvas.height);
  const ball = new Ball(canvas.width/2, canvas.height/2, canvas.width/200);
  const pad1 = new Pad( canvas.width/20,  canvas.height/2, canvas.width/100, canvas.height/5, true);
  const pad2 = new Pad(canvas.width*19/20, canvas.height/2, canvas.width/100, canvas.height/5);

  animate(canvas, ctx, table, ball, pad1, pad2);
}

function animate(canvas, ctx, table, ball, pad1, pad2) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  result = ball.update(canvas.width, canvas.height, pad1, pad2);
  pad1.update(canvas.height);
  pad2.update(canvas.height);
  ball.draw(ctx);
  pad1.draw(ctx);
  pad2.draw(ctx);
  table.draw(ctx);
  requestID = requestAnimationFrame(animate);
  switch (result) {
    case 1:
      cancelAnimationFrame(requestID);
      var again = confirm("You lost, play again?");
      break;
    case 2:
      cancelAnimationFrame(requestID);
      var again = confirm("You won, play again?");
      break;
  }
  if (again) start_game();
}

Now, for some reason I do not understand, I get this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'clearRect') at animate

And this happens with all of the objects.

I tried logging the ctx object in the console at the begining of the animate() function and something even weirder happens, the object is printed as normal and then as undefined:

logged ctx object followed by undefined

What’s going on?

>Solution :

I don’t see you passing any arguments to animate here:

requestAnimationFrame(animate)

You meant:

requestAnimationFrame(() => animate(canvas, ctx, table, ball, pad1, pad2))

Leave a Reply