Skip to content
Browse files

Normal map and audio preloading

  • Loading branch information...
1 parent e0d5ac8 commit 2d44c30b0c0e21b4a20c05a2abd0629f69c820f4 @izb committed Jun 3, 2013
View
BIN resources/hitmaps/tile.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN resources/hitmaps/tile.psd
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
22 src/map/staggered-isometric.js
@@ -123,7 +123,7 @@ function(Tile, Bitmap, debug, js, clock) {
for (var i = 0; i < map.tilesets.length; i++) {
var ts = map.tilesets[i];
- preloader.add(ts.image, ts, storeTile);
+ preloader.addImage(ts.image, ts, storeTile);
}
var storeHitTest = function(image, name) {
@@ -132,7 +132,23 @@ function(Tile, Bitmap, debug, js, clock) {
}
if (name==='hit') {
- _this.hitTest = Bitmap.imageToRData(image);
+ _this.hitTest = []; /* Red channel shows distance from closest edge, and can be used to determine
+ * if a point lies on a tile. */
+ _this.edgeNormals = []; /* Green channel points away from the closest edge at 90 degrees. */
+ Bitmap.imageToRData(image, _this.hitTest, _this.edgeNormals);
+
+ /* Normals in vector form too. */
+ _this.edgeNormalsX = new Array(_this.edgeNormals.length);
+ _this.edgeNormalsY = new Array(_this.edgeNormals.length);
+ /* Convert normals to radians for convenience */
+ for (var i = _this.edgeNormals.length - 1; i >= 0; i--) {
+ var n = _this.edgeNormals[i];
+ n = (3*n*Math.PI)/180; /* Normal values are to the closes 3 degrees */
+ _this.edgeNormals[i] = n;
+ _this.edgeNormalsX[i] = Math.cos(n);
+ _this.edgeNormalsY[i] = Math.sin(n);
+ }
+
/* TODO: It should be noted in documentation that the hit test image
* should under no circumstances be re-saved with a colour profile attached. */
@@ -144,7 +160,7 @@ function(Tile, Bitmap, debug, js, clock) {
};
for(var testName in this.hitTests) {
- preloader.add(this.hitTests[testName], testName, storeHitTest);
+ preloader.addImage(this.hitTests[testName], testName, storeHitTest);
}
};
View
37 src/snaps.js
@@ -112,16 +112,18 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
this.PathFinder = PathFinder.bind(PathFinder, this);
settings = settings || {};
+
this.dbgShowMouse = !!settings.showMouse;
this.dbgShowCounts = !!settings.showCounts;
this.dbgShowMouseTile = !!settings.showMouseTile;
/* If regions is true, then the x,y is shown for tiles. If it's a comma-separated list
* then those property values are shown on each tile. */
this.dbgShowRegions = !!settings.showRegions;
this.dbgRegionProps = settings.showRegions&&settings.showRegions.length>0&&settings.showRegions!=='true'?
- settings.showRegions.split(','):[];
+ settings.showRegions.split(','):[];
this.imageCache = {};
+ this.audioCache = {};
this.spriteUpdaters = {};
this.colliders = {};
this.fxUpdaters = {};
@@ -262,12 +264,23 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
/* Add game-added images to the preloader */
if (typeof game.preloadImages === 'object') {
- var storePreloaded = function(image, tag){
+ var storePreloadedImage = function(image, tag){
_this.imageCache[tag] = image;
};
for(var pathName in game.preloadImages) {
- preloader.add(game.preloadImages[pathName], pathName, storePreloaded);
+ preloader.addImage(game.preloadImages[pathName], pathName, storePreloadedImage);
+ }
+ }
+
+ if (typeof game.sounds === 'object') {
+
+ var storePreloadedSound = function(sound, tag){
+ _this.audioCache[tag] = sound;
+ };
+
+ for(var pathName in game.sounds) {
+ preloader.addAudio(game.sounds[pathName], pathName, storePreloadedSound);
}
}
@@ -300,7 +313,7 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
};
for(var spriteName in _this.game.spriteDefs) {
- preloader.add(_this.game.spriteDefs[spriteName].path, spriteName, storeSpriteSheet);
+ preloader.addImage(_this.game.spriteDefs[spriteName].path, spriteName, storeSpriteSheet);
}
}
@@ -535,7 +548,6 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
/* Start the paint loop */
_this.halt = false;
- _this.overrideClock();
setTimeout(function(){loop(0);}, 0);
},
@@ -690,11 +702,10 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
this.map.tileDimensions(out);
if ((r&1)===0) {
out[0] = (c+1)*out[0] - (out[0]/2);
- out[1] = (r+1)*(out[1]/2);
} else {
out[0] = (c+1)*out[0];
- out[1] = (r+1)*(out[1]/2);
}
+ out[1] = (r+1)*(out[1]/2);
};
/** Get a tile property from a world position. Starts at the topmost
@@ -816,10 +827,8 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
if (opts.id===undefined) {
opts.id = uid();
- } else {
- if(_this.spriteMap.hasOwnProperty(opts.id)) {
- throw "Error: duplicate sprite id " + opts.id;
- }
+ } else if(_this.spriteMap.hasOwnProperty(opts.id)) {
+ throw "Error: duplicate sprite id " + opts.id;
}
var s = Sprite.construct(_this, defName, stateName, stateExt, x, y, h, opts);
@@ -843,10 +852,8 @@ function(SpriteDef, Sprite, Composite, Keyboard, Mouse, util, StaggeredIsometric
if (id===undefined) {
id = 'id'+uid();
- } else {
- if(_this.spriteMap.hasOwnProperty(id)) {
- throw "Warning: duplicate sprite (composite) id " + id;
- }
+ } else if(_this.spriteMap.hasOwnProperty(id)) {
+ throw "Warning: duplicate sprite (composite) id " + id;
}
var comp = new Composite(this, x, y, id, endCallback);
View
47 src/util/bitmap.js
@@ -12,9 +12,16 @@ define(function() {
* Extract the red channel from an image into an array.
* @function module:util/bitmap#imageToRData
* @param {DOMElement} image The source image
- * @return {Array} An array of byte values as a regular array
+ * @param {Array} [r] Output: An array that will be filled with the red channel
+ * bitmap data. Length will be reset.
+ * @param {Array} [g] Output: An array that will be filled with the green channel
+ * bitmap data. Length will be reset.
+ * @param {Array} [b] Output: An array that will be filled with the blue channel
+ * bitmap data. Length will be reset.
+ * @param {Array} [a] Output: An array that will be filled with the alpha channel
+ * bitmap data. Length will be reset.
*/
- imageToRData: function(image)
+ imageToData: function(image, r, g, b, a)
{
var w = image.width;
var h = image.height;
@@ -28,13 +35,41 @@ define(function() {
var rgba = ctx.getImageData(0,0,w,h).data;
- var r = new Array(rgba.length/4);
+ var len = rgba.length/4;
- for (var i = 0; i < r.length; i++) {
- r[i] = rgba[i*4];
+ if (r) {
+ r.length = len;
}
- return r;
+ if (g) {
+ g.length = len;
+ }
+
+ if (b) {
+ b.length = len;
+ }
+
+ if (a) {
+ a.length = len;
+ }
+
+ for (var i = 0; i < len; i++) {
+ if (r) {
+ r[i] = rgba[i*4];
+ }
+
+ if (g) {
+ g[i] = rgba[i*4+1];
+ }
+
+ if (b) {
+ b[i] = rgba[i*4+2];
+ }
+
+ if (a) {
+ a[i] = rgba[i*4+3];
+ }
+ }
}
};
View
75 src/util/preload.js
@@ -12,24 +12,58 @@ define(function() {
* @constructor module:util/preload.Preloader
*/
function Preloader() {
- this.batch = [];
+ this.imagebatch = [];
+ this.audiobatch = [];
this.errorstate = false;
}
+ var mimeTypesAudio = [
+ {ext:'.ogg', mime:'audio/ogg; codecs="vorbis"'},
+ {ext:'.mp3', mime:'audio/mpeg'}
+ ];
+
+ var audioExt;
+
+ /**
+ * Adds an audio file to the preloader. The correct file extension for the
+ * current browser will be determined. The extension will be either .ogg or .mp3
+ * @param {String} file The filename without extension. The extension will
+ * be added automatically. You should therefore have a
+ * range of file types available for different browsers.
+ * @param {[type]} tag [description]
+ * @param {[type]} fnStore [description]
+ * @return {[type]} [description]
+ */
+ Preloader.prototype.addAudio = function(file, tag, fnStore) {
+ if (audioExt===undefined) {
+ /* First time in, determine the audio type for the platform */
+ var s = new Audio();
+
+ for (var i = 0; i < mimeTypesAudio.length; i++) {
+ var t = mimeTypesAudio[i];
+ if (s.canPlayType(t.mime)) {
+ audioExt = t.ext;
+ break;
+ }
+ }
+ }
+ this.audiobatch.push({file:file+audioExt, tag:tag, fnStore:fnStore});
+ };
+
/**
- * Initialize the composite before use.
- * @method module:util/preload.Preloader#add
+ * Adds an image file to the preloader.
+ * @method module:util/preload.Preloader#addImage
* @param {String} file The file to load
- * @param {String} tag Some tag to help you identify the image when it's loaded
+ * @param {String} tag Some tag to help you identify the file when it's loaded
* @param {Function} [fnStore] A callback to receive the loaded image, in the form
* <pre>
* function(image, tag) {
* }
* </pre>
* Where the image is a loaded Image object.
*/
- Preloader.prototype.add = function(file, tag, fnStore) {
- this.batch.push({file:file, tag:tag, fnStore:fnStore});
+ Preloader.prototype.addImage = function(file, tag, fnStore) {
+ this.imagebatch.push({file:file, tag:tag, fnStore:fnStore});
};
/**
@@ -42,21 +76,26 @@ define(function() {
*/
Preloader.prototype.load = function(fnComplete, fnProgress, fnError) {
- var count = this.batch.length;
- var _this = this;
+ var count = this.imagebatch.length + this.audiobatch.length,
+ _this = this,
+ i, next;
fnProgress(0);
- function loadHandler(item, img) {
- return function() {
+ function loadHandler(item, ob) {
+ return function() { /* TODO: Use bind instead. */
if (_this.errorstate) {
return;
}
+
count--;
+
if (item.fnStore!==undefined) {
- item.fnStore(img, item.tag);
+ item.fnStore(ob, item.tag);
}
- fnProgress(1-count/_this.batch.length);
+
+ fnProgress(1-count/(_this.imagebatch.length + _this.audiobatch.length));
+
if (count===0) {
fnComplete();
}
@@ -70,15 +109,23 @@ define(function() {
}
}
- for (var i = 0; i < this.batch.length; i++) {
- var next = this.batch[i];
+ for (i = 0; i < this.imagebatch.length; i++) {
+ next = this.imagebatch[i];
var img = new Image();
img.onload = loadHandler(next, img);
img.onerror = error;
img.src = next.file;
}
+ for (i = 0; i < this.audiobatch.length; i++) {
+ next = this.audiobatch[i];
+
+ var snd = new Audio();
+ snd.oncanplaythrough = loadHandler(next, snd);
+ snd.onerror = error;
+ snd.src = next.file;
+ }
};
return Preloader;
View
BIN test/maps/hitmaps/tile.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2d44c30

Please sign in to comment.
Something went wrong with that request. Please try again.