I am playing around adapting the example code at Mozilla Dev Network: Square tilemaps implementation: Scrolling maps to fit with a server I wrote myself. There's a link to the original source code at the bottom of the page.
Instead of hard-coding the map (and its layers) into the js page, I can have a server call deliver the map data in a similar format (a 1-dimensional sequence of numbers up to 256). The way the server (and the js interface) is constructed, I first need to get the map Id from the game that is stored on the server and use that id to get (a section of) the map.
This is the function for doing the data fetch:
function LoadGame(gameid) {
$.getJSON('/api/game/' + gameid)
.done(function (game) {
if (game !== null) {
mapid = game.MapId;
map = AssetLoader.LoadMapSection(mapid, 0);
}
else
console.log("Could not load game with id: " + gameid);
})
.fail(function (jqXHR, status, error) {
console.log(error);
});
}
The LoadMapSection function looks like this:
AssetLoader.LoadMapSection = function (mapid, pos) {
if (!(mapid in this.maps)) {
this.status = statusEnum.LOADING;
console.log("Loading map section: " + mapid + " at: " + pos);
$.getJSON('/api/map/section/' + mapid + '/' + pos + '/32/24')
.done(function (map) {
AssetLoader.maps[mapid] = map;
this.status = statusEnum.DONE;
console.log("Loaded section of map: " + mapid);
}).fail(function (jqXHR, status, error) {
console.log(error);
this.status = statusEnum.ERROR;
});
}
return map;
}
Since the map data may take some time to arrive I am trying to use an AssetLoader, suggested by MDN, to fetch the map data as well as the spritesheets for displaying the map. So, upon game load, I construed this:
Game.load = function () {
return [
AssetLoader.LoadImage('atlas-elevation', 'assets/atlas/elevation.png'),
AssetLoader.LoadImage('atlas-landscape', 'assets/atlas/landscape.png'),
LoadGame(gameid),
];
};
To ensure the asynchronicity and wait for all data to be fetched, the following code has been left unchanged:
Game.run = function (context) {
this.ctx = context;
this._previousElapsed = 0;
var p = this.load();
Promise.all(p).then(function (loaded) {
this.init();
window.requestAnimationFrame(this.tick);
}.bind(this));
};
So the following init-call is supposed to happen after that:
Game.init = function () {
Keyboard.listenForEvents(
[Keyboard.LEFT, Keyboard.RIGHT, Keyboard.UP, Keyboard.DOWN]);
this.tileAtlas = AssetLoader.GetImage('atlas-elevation');
this.camera = new Camera(map, 512, 512);
};
However, I keep on running into situations where the map is still "undefined" as soon as the Camera code is hit:
function Camera(map, width, height) {
//if (map != null) {
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
this.maxX = map.Width * scale - width;
this.maxY = map.Height * scale - height;
//}
}
I did declare map at the top of the js file as global variable, so I am not sure where I am going wrong here.