0

I am making a game where I have multiple tile objects stored in an array, and I am trying to call a function "update", to draw the tiles to the screen.

My script:

var canvas = document.getElementById("game canvas");
canvas.width = 600;
canvas.height = 300;
var g = canvas.getContext("2d");
var grass = new Image();
grass.src = "grass.png";
setInterval(draw,1000/60);

function tile(x,y,img) {
    this.x = x;
    this.y = y;
    this.img = img;
    this.update = function() {
        g.drawImage(this.img,this.x,this.y);
    }
}
var maps = {
    map1:{
        tiles:[
            new tile(0,0,grass),
            new tile(0,32,grass)
        ],

        update:function() {
            for (var i in this.tiles) {
                i.update();
            }
        }
    }
};

function draw() {
    maps.map1.update();
}

I also tried using an object instead of an array for the tile container, but it didn't work either. It outputs this error into the console:

TypeError: i.update is not a function
Juice
  • 1
  • try i.apply(null,update) – Bhojendra Rauniyar Nov 29 '14 at 18:48
  • Search for "JavaScript, iterate array" and "JavaScript, for in". – user2864740 Nov 29 '14 at 19:03
  • http://stackoverflow.com/questions/9329446/for-each-over-an-array-in-javascript/9329476#9329476 , http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea , http://stackoverflow.com/questions/3010840/loop-through-array-in-javascript/3010848#3010848 – user2864740 Nov 29 '14 at 19:03

1 Answers1

1

When you use a for...in loop, i is actually referring to the property name of the object. In this case, tiles is an array, so i can be thought of as an index into that array (Be careful though, Arrays in JS are basically just special objects with indices as property names).

HOWEVER as @jfriend00 pointed out in the comments, for..in will enumerate over all properties of an object and therefore can access some things that might not be what you expect, or objects that don't have an update() to call.

While you can do this:

update:function() {
    for (var i in this.tiles) {

        // get the current tile
        this.tiles[i].update();
    }
}

It is better to use either a forEach loop on your array, or use a standard for loop:

update:function() {

    // update each tile
    this.tiles.forEach(function(tile) {
        tile.update();
    }
}

or

update:function() {

    // normal for loop for safe indexing
    for (var i = 0; i < this.tiles.length; i++) {
        this.tiles[i].update();
    }
}

More info on for-in

SO Answer that talks about all types of iteration techniques

Community
  • 1
  • 1
theoperatore
  • 263
  • 2
  • 9
  • You should never use the structure `for (var i in this.tiles)` on an array. That iterates all enumerable properties of the array (which may include some properties of the object), not only array elements. You can safely use `for (var i = 0; i < this.tiles.length; i++)` or `this.tiles.forEach(...)` instead. – jfriend00 Nov 29 '14 at 19:07