Created
January 18, 2014 18:52
-
-
Save caubry/8494585 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var TILEDMapClass = Class.extend({ | |
// This is where we store the full parsed | |
// JSON of the map.json file. | |
currMapData: null, | |
// tilesets stores each individual tileset | |
// from the map.json's 'tilesets' Array. | |
// The structure of each entry of this | |
// Array is explained below in the | |
// parseAtlasDefinition method. | |
tilesets: [], | |
// This is where we store the width and | |
// height of the map in tiles. This is | |
// in the 'width' and 'height' fields | |
// of map.json, respectively. | |
// The values 100 here are just set | |
// so these fields are initialized to | |
// something, rather than null. | |
numXTiles: 100, | |
numYTiles: 100, | |
// The size of each individual map | |
// tile, in pixels. This is in the | |
// 'tilewidth' and 'tileheight' fields | |
// of map.json, respectively. | |
// The values 64 here are just set | |
// so these fields are initialized to | |
// something, rather than null. | |
tileSize: { | |
"x": 64, | |
"y": 64 | |
}, | |
// The size of the entire map, | |
// in pixels. This is calculated | |
// based on the 'numXTiles', 'numYTiles', | |
// and 'tileSize' parameters. | |
// The values 64 here are just set | |
// so these fields are initialized to | |
// something, rather than null. | |
pixelSize: { | |
"x": 64, | |
"y": 64 | |
}, | |
// Counter to keep track of how many tile | |
// images we have successfully loaded. | |
imgLoadCount: 0, | |
// Boolean flag we set once our tile images | |
// has finished loading. | |
fullyLoaded: false, | |
//----------------------------------------- | |
// Load the json file at the url 'map' into | |
// memory. This is similar to the requests | |
// we've done in the past using | |
// XMLHttpRequests. | |
load: function (map) { | |
// Perform an XMLHttpRequest to grab the | |
// JSON file at url 'map'. | |
xhrGet(map, function (data) { | |
// Once the XMLHttpRequest loads, call the | |
// parseMapJSON method. | |
gMap.parseMapJSON(data.responseText); | |
}); | |
}, | |
//----------------------------------------- | |
// Parses the map data from 'mapJSON', then | |
// stores that data in a number of members | |
// of our 'TILEDMapClass' that are defined | |
// above. | |
parseMapJSON: function (mapJSON) { | |
// Call JSON.parse on 'mapJSON' and store | |
// the resulting map data | |
gMap.currMapData = JSON.parse(mapJSON); | |
var map = gMap.currMapData; | |
// Set 'numXTiles' and 'numYTiles' from the | |
// 'width' and 'height' fields of our parsed | |
// map data. | |
gMap.numXTiles = map.width; | |
gMap.numYTiles = map.height; | |
// Set the 'tileSize.x' and 'tileSize.y' fields | |
// from the 'tilewidth' and 'tileheight' fields | |
// of our parsed map data. | |
gMap.tileSize.x = map.tilewidth; | |
gMap.tileSize.y = map.tileheight; | |
// Set the 'pixelSize.x' and 'pixelSize.y' fields | |
// by multiplying the number of tiles in our map | |
// by the size of each tile in pixels. | |
gMap.pixelSize.x = gMap.numXTiles * gMap.tileSize.x; | |
gMap.pixelSize.y = gMap.numYTiles * gMap.tileSize.y; | |
// Loop through 'map.tilesets', an Array... | |
for(var i = 0; i < map.tilesets.length; i++) { | |
// ...loading each of the provided tilesets as | |
// Images... | |
var img = new Image(); | |
img.onload = function () { | |
// ...Increment the above 'imgLoadCount' | |
// field of 'TILEDMap' as each tileset is | |
// loading... | |
gMap.imgLoadCount++; | |
if (gMap.imgLoadCount === map.tilesets.length) { | |
// ...Once all the tilesets are loaded, | |
// set the 'fullyLoaded' flag to true... | |
gMap.fullyLoaded = true; | |
} | |
}; | |
// The 'src' value to load each new Image from is in | |
// the 'image' property of the 'tilesets'. | |
img.src = map.tilesets[i].image; | |
// This is the javascript object we'll create for | |
// the 'tilesets' Array above. First, fill in the | |
// given fields with the corresponding fields from | |
// the 'tilesets' Array in 'currMapData'. | |
var ts = { | |
"firstgid": gMap.currMapData.tilesets[i].firstgid, | |
// 'image' should equal the Image object we | |
// just created. | |
"image": img, | |
"imageheight": gMap.currMapData.tilesets[i].imageheight, | |
"imagewidth": gMap.currMapData.tilesets[i].imagewidth, | |
"name": gMap.currMapData.tilesets[i].name, | |
// These next two fields are tricky. You'll | |
// need to calculate this data from the | |
// width and height of the overall image and | |
// the size of each individual tile. | |
// | |
// Remember: This should be an integer, so you | |
// might need to do a bit of manipulation after | |
// you calculate it. | |
"numXTiles": Math.floor(gMap.currMapData.tilesets[i].imagewidth / gMap.tileSize.x), | |
"numYTiles": Math.floor(gMap.currMapData.tilesets[i].imageheight / gMap.tileSize.y) | |
}; | |
// After that, push the newly created object into | |
// the 'tilesets' Array above. Javascript Arrays | |
// have a handy method called, appropriately, 'push' | |
// that does exactly this. It takes the object | |
// we'd like to put into the Array as a parameter. | |
// | |
// YOUR CODE HERE | |
gMap.tilesets.push(ts); | |
} | |
}, | |
//----------------------------------------- | |
// Grabs a tile from our 'layer' data and returns | |
// the 'pkt' object for the layer we want to draw. | |
// It takes as a parameter 'tileIndex', which is | |
// the id of the tile we'd like to draw in our | |
// layer data. | |
getTilePacket: function (tileIndex) { | |
// We define a 'pkt' object that will contain | |
// | |
// 1) The Image object of the given tile. | |
// 2) The (x,y) values that we want to draw | |
// the tile to in map coordinates. | |
var pkt = { | |
"img": null, | |
"px": 0, | |
"py": 0 | |
}; | |
// The first thing we need to do is find the | |
// appropriate tileset that we want to draw | |
// from. | |
// | |
// Remember, if the tileset's 'firstgid' | |
// parameter is less than the 'tileIndex' | |
// of the tile we want to draw, then we know | |
// that tile is not in the given tileset and | |
// we can skip to the next one. | |
var tile = 0; | |
for(tile = gMap.tilesets.length - 1; tile >= 0; tile--) { | |
if(gMap.tilesets[tile].firstgid <= tileIndex) break; | |
} | |
// Next, we need to set the 'img' parameter | |
// in our 'pkt' object to the Image object | |
// of the appropriate 'tileset' that we found | |
// above. | |
pkt.img = gMap.tilesets[tile].image; | |
// Finally, we need to calculate the position to | |
// draw to based on: | |
// | |
// 1) The local id of the tile, calculated from the | |
// 'tileIndex' of the tile we want to draw and | |
// the 'firstgid' of the tileset we found earlier. | |
var localIdx = tileIndex - gMap.tilesets[tile].firstgid; | |
// 2) The (x,y) position of the tile in terms of the | |
// number of tiles in our tileset. This is based on | |
// the 'numXTiles' of the given tileset. Note that | |
// 'numYTiles' isn't actually needed here. Think about | |
// how the tiles are arranged if you don't see this, | |
// It's a little tricky. You might want to use the | |
// modulo and division operators here. | |
var lTileX = Math.floor(localIdx % gMap.tilesets[tile].numXTiles); | |
var lTileY = Math.floor(localIdx / gMap.tilesets[tile].numXTiles); | |
// 3) the (x,y) pixel position in our tileset image of the | |
// tile we want to draw. This is based on the tile | |
// position we just calculated and the (x,y) size of | |
// each tile in pixels. | |
pkt.px = (lTileX * gMap.tileSize.x); | |
pkt.py = (lTileY * gMap.tileSize.y); | |
return pkt; | |
}, | |
//----------------------------------------- | |
// Draws all of the map data to the passed-in | |
// canvas context, 'ctx'. | |
draw: function (ctx) { | |
// First, we need to check if the map data has | |
// already finished loading... | |
if(!gMap.fullyLoaded) return; | |
// ...Now, for every single layer in the 'layers' Array | |
// of 'currMapData'... | |
for(var layerIdx = 0; layerIdx < gMap.currMapData.layers.length; layerIdx++) { | |
// Check if the 'type' of the layer is "tilelayer". If it isn't, we don't | |
// care about drawing it... | |
if(gMap.currMapData.layers[layerIdx].type != "tilelayer") continue; | |
// ...Grab the 'data' Array of the given layer... | |
var dat = gMap.currMapData.layers[layerIdx].data; | |
// ...For each tileID in the 'data' Array... | |
for(var tileIDX = 0; tileIDX < dat.length; tileIDX++) { | |
// ...Check if that tileID is 0. Remember, we don't draw | |
// draw those, so we can skip processing them... | |
var tID = dat[tileIDX]; | |
if(tID === 0) continue; | |
// ...If the tileID is not 0, then we grab the | |
// packet data using getTilePacket. | |
var tPKT = gMap.getTilePacket(tID); | |
// Now we need to calculate the (x,y) position we want to draw | |
// to in our game world. | |
// | |
// We've performed a similar calculation in 'getTilePacket', | |
// think about how to calculate this based on the tile id and | |
// various tile properties that our TILEDMapClass has. | |
// | |
// YOUR CODE HERE | |
var dx = Math.floor(tileIDX % gMap.numXTiles) * gMap.tileSize.x; | |
var dy = Math.floor(tileIDX / gMap.numXTiles) * gMap.tileSize.y; | |
// Now, we're finally drawing the map to our canvas! The 'drawImage' | |
// method of our 'ctx' object takes nine arguments: | |
// | |
// 1) The Image object to draw, | |
// 2) The source x coordinate in our Image, | |
// 3) The source y coordinate in our Image, | |
// 4) The source width of our tile, | |
// 5) The source height of our tile, | |
// 6) The canvas x coordinate to draw to, | |
// 7) The canvas y coordinate to draw to, | |
// 8) The destination width, | |
// 9) The destination height | |
// | |
// Note that we don't want to stretch our tiles at all, so the | |
// source height and width should be the same as the destination! | |
// | |
// YOUR CODE HERE | |
ctx.drawImage(tPKT.img, tPKT.px, tPKT.py, gMap.tileSize.x, gMap.tileSize.y, dx, dy, gMap.tileSize.x, gMap.tileSize.y); | |
} | |
} | |
} | |
}); | |
var gMap = new TILEDMapClass(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment