3 Replies - 506 Views - Last Post: 30 July 2014 - 07:07 AM

#1 boba fett  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 18-August 13

Is this error something to worry about?

Posted 29 July 2014 - 10:57 AM

I'm creating a game using JS. In my game, if an object leaves the play area, I destroy it using splice. For example: a player's shot goes off screen, I wait til it's totally off, then I use this command
player.shot[i].splice(i,1);
I check each player shot each time the game loops and it checks one property of that shot, which no longer exists and get this error message when I view the dev console: "Uncaught TypeError: Cannot read property 'dir' of undefined"
dir being the direction the shot was going before it was spliced.

The game keeps working, but every shot eventually triggers one of these error messages in the console. The reason I splice them is to help prevent memory leakage. Should I even worry about this or what?

Is This A Good Question/Topic? 0
  • +

Replies To: Is this error something to worry about?

#2 ArtificialSoldier  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 441
  • View blog
  • Posts: 1,598
  • Joined: 15-January 14

Re: Is this error something to worry about?

Posted 29 July 2014 - 12:30 PM

You can check if it is undefined before trying to access the property. As a general rule you want to avoid producing error messages, there is always a way to do something that isn't going to cause an error.

if ((typeof player.shot[i]) != 'undefined')

This post has been edited by ArtificialSoldier: 29 July 2014 - 12:30 PM

Was This Post Helpful? 0
  • +
  • -

#3 Blindman67  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 128
  • View blog
  • Posts: 563
  • Joined: 15-March 14

Re: Is this error something to worry about?

Posted 29 July 2014 - 12:41 PM

I would say the your problem is that if you are doing the splice inside a loop the size of the array changes and you may end up referencing out side the array.

For example.
var len = player.shot.length;
for(var i = 0; i < len; i++){
    if(...reason to delete..){
         player.shot[i].splice(i,1); // the array is now one shorter then len
                                     // so when you get to the end of the loop
                                     // you will get an reference error.
    }
}



You can do it this way.
for(var i = 0; i < player.shot.length; i++){ // get the length each iteration
    if(...reason to delete..){
         player.shot[i].splice(i,1); 
         i-= 1;    // move i down as all the next items in the array have moved down 
                   // by one 
    }
}


or loop from top down.
for(var i = player.shot.length-1; i >= 0; i--){ 
    if(...reason to delete..){
         player.shot[i].splice(i,1); 
    }
}


In games, or any application the requires a fixed time interval between frames you should try to avoid adding and removing objects as this will trigger the garbage collection. Garbage Collection can not be controlled and can fire at any time (between call stack calls) and can cause momentary slowdowns in your code.

The method I use is to never delete anything during the main run cycle.
var shotArray = [];
function addShot(x,y){      // add a shot
    var len = shotArray.length;    // always get length outside the loop if speed is needed.
    // first check if an existing shot is avalibe to use
    for(var i = 0; i < len; i++){
          if(! shotArray[i].active){   // if a shot is no longer active. Activate it with 
              var shot = shotArray[i]; // the new data
              shot.x = x;
              shot.y = y;
              shot.active = true;
              return;                  // done return
          }
    }
    // the shotArray is full so add a new item
    shotArray.push({x:x,y:y,active:true});
}


// game logic
function doShots(){
    var len = shotArray.length;
    for(var i = 0; i < len; i++){
          if(shotArray[i].active){           // is the shot active??? 
                var shot = shotArray[i];     // get reference to shot.
                if(... out side screen ...){
                     shot.active = false;    // deactivate this shot so its free for another
                }
           }
     }
}

// Always separate out display from game logic. The game should be able to run without displaying.
// And you should be able to display the games without it having to do the logic
function displayShots(){
    var len = shotArray.length;
    for(var i = 0; i < len; i++){
          if(shotArray[i].active){   // is the shot active??? 
              ... code to display shot ...
          }
    }
}



This method may be a little slower than using splice but it runs a lot smoother especially if you have a large number of bullets, and FX. The shotArray will grow to a size that is the maximum number of bullets you will need and the code will run at a more consistent speed each frame, and you will not have to worry about GC (garbage collection) kicking in randomly and stealing frames and making the game gitter.

Only Delete at the end of the game.

You can optimize the above method if you have very large arrays (say 10,000 or more) bullets by tracking the lowest inactive bullets and the highest active bullet.
Was This Post Helpful? 1
  • +
  • -

#4 boba fett  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 18-August 13

Re: Is this error something to worry about?

Posted 30 July 2014 - 07:07 AM

Wow, that's a great idea! Thanks, Blindman67 :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1