Sven Sven - 3 months ago 6
Javascript Question

Why does this code seem to execute after the return statement?

Background info: I'm making a really basic 2D platformer with HTML5 canvas.
Inside my main gameloop, I iterate over all the objects to check if the player is standing on an object. If so, I end the execution of the function until the next loop.

In case an object and the player are colliding, before using

return
to exit the function (since we know the player is standing on that object), I set the player's velocity on the Y axis to 0, adjust his Y position slightly just to align him and the object properly, and set the player's property:
player.grounded
to true. This is where the main problem lies. It is a required boolean value that ties with the
player.isFalling
property. An update function checks if the player's Y velocity is higher than 0 and checks if he isn't grounded. In that case
player.isFalling
is true. The standingCheck helper function only executes if
isFalling
is true.

const standingCheckHandler = (player) => {
for(let i = 0; i < objects.length; i ++){
if(standingCheck(player, objects[i])){
player.pos.y = objects[i].pos.y - player.height;
player.velocity.y = 0;
player.grounded = true;
return;
}else{
player.grounded = false;
}
}
}


Now for the problem: even though I exit the function, or use
break
, the loop still continues iterating over the other objects. I'll log
player.grounded
and even after it is set to
true
(which means the function should quit itself, right?), it will go on to loop over the other objects and sets
player.grounded
to
false
, which causes dodgy movement in the game itself. (In theory it works, but the player keeps on bobbing up and down slightly which isn't really a nice sight).

I've tried all kinds of things. Use new properties, count the amount of objects the player could stand on, nothing seems to work. I feel like I'm overlooking something, but I'm not sure as to what that might be.

(sorry for the wall of text!)

Update: this is the standingCheck method:

const standingCheck = (a, b) => {
// a = player, b = object
if(a.isFalling){
if(!(a.pos.x > b.pos.x + b.width || a.pos.x + a.width < b.pos.x)){ //x
if(a.pos.y + a.height < b.pos.y && a.pos.y + a.height >= b.pos.y){ //y
return true;
}
}
}
}

Answer

I think I've found the answer. Although it did not fix the bug directly, I managed to work around the problem by introducing a new helper function:
groundedCheck is much the same as standingCheck. It basically only checks if the player is effectively still grounded (if the player.y + player.height equals to an object.y).

There might be definitely is a faster way to do it, but this works for now.

How I fixed it:

const standingCheckHandler = (player) => {
  for(let i = 0; i < objects.length; i ++){
    if(standingCheck(player, objects[i])){
      player.pos.y = objects[i].pos.y - player.height;
      player.velocity.y = 0;
      player.grounded = true;
      break;
    }
  }
  // this is new
  if(player.grounded){
    let len = objects.length;
    for(let j = 0; j < objects.length; j ++){
      if(!groundedCheck(player, objects[j])){
        len --;
      }
    }
    if(len <= 0){
      player.grounded = false;
    }
  }
}

// so is this
const groundedCheck = (a, b) => {
  // a = player, b = object
  if(!(a.pos.x > b.pos.x + b.width || a.pos.x + a.width < b.pos.x)){
    if(a.pos.y + a.height === b.pos.y){
      return true;
    }
  }
}