Critical Bug Squashed

For the longest time, very occasionally, the game would completely freeze during testing. I couldn’t find anything in the stack-trace and didn’t know how to use the debugger (until the day of this post), and I didn’t notice any patterns in when it happened, so I started to blame the platform itself and moved on.

Here’s what was going on: my spawn_entity_randomly function was supposed to pick a random set of coordinates in the play space, check to see if there was a player entity within 100 or so pixels, and if so, pick another set of random coordinates. Continue until the player is not too close to the new spawning enemy. My problem was that I was using a function to determine player distance that assumed the caller was one end of the line segment being measured, and in this case, the caller was an invisible object orchestrating the enemy waves, hiding in the upper left corner.

So, if the player happened to be within 100 pixels of that corner and a random enemy was being spawned anywhere, the while loop would engage, infinitely offering fresh random coordinates that would be ignored because the player was still within 100 pixels of the corner, not those coordinates. Oops.

I think I’ve found the issue that was causing random freezing: the spawn_entity_randomly function includes a safety option to avoid spawning the enemy next to the player. I caught a freeze while in debug mode and figured out how to get to the code-view to see where I was stuck. It turned out to be in the while loop responsible for picking new coordinates in the event that the target was too close.

What I figured out was that I was using the distance_to_object(obj_base_player) method and in the loop, I was randomizing _x and _y… but distance_to_object() couldn’t take those new coordinates into account. I was randomizing the values, but the distance from the calling object to the player instance would remain unchanged.

What I needed to do was use the point_distance(x1, y1, x2, y2) function instead so I could check on each iteration of the loop whether the newly proposed distance was still too small. I tested this with debug code and flying to where I knew a new object would appear (because the random seed in test mode is constant unless instructed otherwise), and it seems to be fixed.

This also explains why the bug happened more frequently when I was testing multiple ships—there were more chances to interact with obj_base_player on every spawn attempt.

Here’s the final code:

function spawn_entity_randomly(_object_name, _spawn_at_safe_distance = true, _safety_target = obj_base_player) {
  var _x = random(room_width);
  var _y = random(room_height);

  if _spawn_at_safe_distance {
    while (point_distance(_safety_target.x, _safety_target.y, _x, _y) < 100) {
      _x = random(room_width)
      _y = random(room_height)
    }
  }

  return spawn_entity(_x, _y, _object_name);
}