# Loading tile maps from files on the fly in Crafty JS

I'm fairly new to Crafty and have been having problems loading large world maps.

So i have a world split up into multiple js files. They are represented by two arrays of tiles: one for background (which grass sprite to use) and one for detail (which cliff to use). When i start crafty I load the 3x3 surrounding files and render them like so:

for(var i = 0; i < Game.map_grid.map_entities.length; i ++){
if(Game.map_grid.map_entities.hasOwnProperty(i))
Game.map_grid.map_entities[i].keep = false;
}

//render background terrain
for (var i = 0; i < view_map["background"].length; i++) {

var tile_object = view_map["background"][i];
var tile = tile_object["type"];
var x = tile_object["x"] - view_map["xoffset"];
var y = tile_object["y"] - view_map["yoffset"];

if(Game.map_grid.map_entities.length && (tile+"_"+x+"_"+y) in this.map_grid.map_entities)
{
tile_ent.keep = true;
continue;
}

var tile_ent = Crafty.e("Actor", "spr_"+tile);
tile_ent.at(x, y);
tile_ent.z = 0;
tile_ent.keep = true;
this.map_grid.map_entities[tile+"_"+x+"_"+y] = tile_ent;
}

//render background terrain
for (var i = 0; i < view_map["detail"].length; i++) {

var tile_object = view_map["detail"][i];
var tile = tile_object["type"];
var x = tile_object["x"] - view_map["xoffset"];
var y = tile_object["y"] - view_map["yoffset"];

if(Game.map_grid.map_entities.length &&
(tile+"_"+x+"_"+y) in this.map_grid.map_entities)
{
tile_ent.keep = true;
continue;
}

var tile_ent = Crafty.e("Actor", "Solid", "spr_"+tile);
tile_ent.at(x, y);
tile_ent.shift(tile_object["xoffset"], tile_object["yoffset"]);
tile_ent.z = 1;
tile_ent.keep = true;
this.map_grid.map_entities[tile+"_"+x+"_"+y] = tile_ent;

}

for(var i = 0; i < Game.map_grid.map_entities.length; i ++){

//Check if the entities need to be moved

if(Game.map_grid.map_entities.hasOwnProperty(i) &&
!Game.map_grid.map_entities[i].keep)
{
Game.map_grid.map_entities[i].destroy();
delete Game.map_grid.map_entities[i];
}
}


I also use the view port to track the player, showing only a portion of the map.

When the player reaches edge of the 3x3 loaded map, I need to request new maps and render them instead. What i have been using is the "Moved" event to check where the player is near the edge. Once that triggers, all of the original tile entities are .destroyed()'ed (i know i can destroy only the ones i need). The above code is ran again to draw the new map and the player is shifted to keep consistent with the new 3x3 coordinates.

The problem is: it looks like the maps are loaded and rendered, but the destroyed ones don't seem to be refreshed and i think are still there. But also the player isn't being redrawn properly, the Moved events are still triggered but the animation isn't updated

My main question is: Is there a better approach to this?

• When you destroy() the entities, do you also remove them from the map_entities array? Also, if you can provide a link to the code in action that would help understand what was actually going wrong -- screenshots or a really specific description would also help! – starwed Aug 17 '13 at 17:37
• Yup, I destroy and then remove them from the array. Sorry about the code being messy but here it is game.js (pastebin.com/3iQshfVU), player.js (pastebin.com/qzMVbBpm). The code in action is a bit difficult to set up as it requires a running webserver, etc. But i can do that if really needed. Thanks a bunch! – Sash Aug 18 '13 at 9:36
• See it in action here 94.192.84.157:4004 (watch out for console output) – Sash Aug 18 '13 at 17:17
• I see some javascript errors in the console, and a plain green background. It's still not clear to me (a) what you expect to happen, and (b) what actually happens. – starwed Aug 18 '13 at 20:34
• I'm not sure why you aren't getting the content. What I expect to happen is something along the lines of: I store the world in multiple JSON files and load them as I need them. In the example it's a case of loading a 3x3 grid surrounding the player, but as the player gets closer to the 3x3 edge, new map files should be loaded and rendered. What actually happens is (and i have edited the code now to reuse the existing Crafty entities) when i try and load the new set of maps, the character disappears (maybe something goes wrong with the viewport) and the crafty entities don't seem to re-render. – Sash Aug 18 '13 at 22:34

I am not getting any response from the link that you provided. In any case, here is a blog post about dynamically loading tile maps using Crafty with an example.

Tile Maps of Unusual Size

It also shows recycling of tiles, which you should probably do instead of "destroy()" if you are worried about performance.

more details as requested...

Basically the large map is broken up into many small boxes with boundaries. Nine boxes should fit in the view area. Each box has a "isLoaded" flag. When the player moves, check if they have crossed a box boundary. If they have, clear all boxes three spaces from the new center box and load all boxes two or less spaces from the new center box.

When tiles are unloaded, do not "destroy()" them. Set their visibility to false and push them onto a tile cache (an array for that tile type). When a new tile of that type is needed, try popping it off the tile cache first before creating a new one.

With this method you should be able to support a more-or-less infinite map size. My blog entry contains example code and a link to an example application using CraftyJS.

• Sorry about the link, forgot to bring it back up – Sash Aug 19 '13 at 11:00