diff --git a/CHANGELOG b/CHANGELOG index 0a20099afd..2db55747fa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Version History --------------- 0.9.8 +* Renderable : added ShoeBox Packed Texture Support (see `me.TextureAtlas`) 0.9.7 * General : melonJS now uses Grunt, the task manager, for the build system diff --git a/examples/platformer/data/gfx/shoebox.json b/examples/platformer/data/gfx/shoebox.json new file mode 100644 index 0000000000..4a907759d9 --- /dev/null +++ b/examples/platformer/data/gfx/shoebox.json @@ -0,0 +1,153 @@ +{"frames": [ + { + "filename": "coin.png", + "frame": {"x":258,"y":196,"w":35,"h":35}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":35}, + "sourceSize": {"w":35,"h":35} + }, + { + "filename": "fly_dead.png", + "frame": {"x":0,"y":196,"w":69,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":69,"h":32}, + "sourceSize": {"w":69,"h":32} + }, + { + "filename": "fly_fly.png", + "frame": {"x":71,"y":196,"w":69,"h":31}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":69,"h":31}, + "sourceSize": {"w":69,"h":31} + }, + { + "filename": "fly_normal.png", + "frame": {"x":142,"y":196,"w":69,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":69,"h":32}, + "sourceSize": {"w":69,"h":32} + }, + { + "filename": "slime_dead.png", + "frame": {"x":0,"y":230,"w":54,"h":8}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":54,"h":8}, + "sourceSize": {"w":54,"h":8} + }, + { + "filename": "slime_normal.png", + "frame": {"x":213,"y":196,"w":43,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":43,"h":28}, + "sourceSize": {"w":43,"h":28} + }, + { + "filename": "slime_walk.png", + "frame": {"x":213,"y":226,"w":43,"h":26}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":43,"h":26}, + "sourceSize": {"w":43,"h":26} + }, + { + "filename": "walk0001.png", + "frame": {"x":77,"y":0,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0002.png", + "frame": {"x":77,"y":98,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0003.png", + "frame": {"x":154,"y":0,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0004.png", + "frame": {"x":154,"y":98,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0005.png", + "frame": {"x":308,"y":0,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0006.png", + "frame": {"x":231,"y":98,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0007.png", + "frame": {"x":308,"y":98,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0008.png", + "frame": {"x":0,"y":0,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0009.png", + "frame": {"x":0,"y":98,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0010.png", + "frame": {"x":231,"y":0,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + { + "filename": "walk0011.png", + "frame": {"x":77,"y":0,"w":75,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":75,"h":96}, + "sourceSize": {"w":75,"h":96} + }, + {"EOL":"true"} +], +"meta": { + "app": "ShoeBox", + "exporter": "melonJS", + "size": {"w":512,"h":256} +} +} \ No newline at end of file diff --git a/examples/platformer/data/gfx/shoebox.png b/examples/platformer/data/gfx/shoebox.png new file mode 100644 index 0000000000..06ee4c20b2 Binary files /dev/null and b/examples/platformer/data/gfx/shoebox.png differ diff --git a/examples/platformer/main.js b/examples/platformer/main.js index e4104909f1..f438f18819 100644 --- a/examples/platformer/main.js +++ b/examples/platformer/main.js @@ -23,6 +23,9 @@ var game = { // texturePacker {name: "texture", type: "tps", src: "data/gfx/texture.json"}, {name: "texture", type:"image", src: "data/gfx/texture.png"} + // ShoeBox + //{name: "texture", type: "tps", src: "data/gfx/shoebox.json"}, + //{name: "texture", type:"image", src: "data/gfx/shoebox.png"} ], /* --- diff --git a/media/shoebox_JSON_export.sbx b/media/shoebox_JSON_export.sbx new file mode 100644 index 0000000000..45ef72e1c2 --- /dev/null +++ b/media/shoebox_JSON_export.sbx @@ -0,0 +1 @@ +::ShoeBox:shoebox.plugin.createSpriteSheet::PluginCreateSpriteSheet:{"texPowerOfTwo":true,"fileGenerate2xSize":false,"texPadding":2,"scale":1,"texMaxSize":2048,"texExtrudeSize":1,"useCssOverHack":false,"fileFormatLoop":"\\t{\\n\\t\\t\"filename\": \"@id\",\\n\\t\\t\"frame\": {\"x\":@x,\"y\":@y,\"w\":@w,\"h\":@h},\\n\\t\\t\"rotated\": false,\\n\\t\\t\"trimmed\": true,\\n\\t\\t\"spriteSourceSize\": {\"x\":@fx,\"y\":@fy,\"w\":@fw,\"h\":@fh},\\n\\t\\t\"sourceSize\": {\"w\":@fw,\"h\":@fh}\\n\\t},\\n","renderDebugLayer":false,"animationFrameIdStart":0,"texSquare":false,"fileName":"shoebox.json","texCropAlpha":false,"animationMaxFrames":100,"animationNameIds":"@name_###.png","fileFormatOuter":"{\"frames\": [\\n@loop\\t{\"EOL\":\"true\"}\\n],\\n\"meta\": {\\n\\t\"app\": \"ShoeBox\",\\n\\t\"exporter\": \"melonJS\",\\n\\t\"size\": {\"w\":@W,\"h\":@H}\\n}\\n}"} diff --git a/src/renderable/texturepacker.js b/src/renderable/texturepacker.js index 3ab5e2ac91..59b23914a9 100644 --- a/src/renderable/texturepacker.js +++ b/src/renderable/texturepacker.js @@ -14,7 +14,10 @@ var nhPI = -(Math.PI / 2); /** - * A Texture atlas object. + * A Texture atlas object
+ * Currently support :
+ * - [TexturePacker]{@link http://www.codeandweb.com/texturepacker/} : through JSON export
+ * - [ShoeBox]{@link http://renderhjs.net/shoebox/} : through JSON export using the melonJS setting [file]{@link https://github.com/melonjs/melonJS/tree/master/media/shoebox_JSON_export.sbx} * @class * @extends Object * @memberOf me @@ -53,16 +56,28 @@ * @ignore */ init : function(atlas, texture) { - if (atlas && atlas.meta && atlas.meta.app.contains("texturepacker")) { - this.format = "texturepacker"; - // set the texture - if (texture===undefined) { - var name = me.utils.getBasename(atlas.meta.image); - this.texture = me.loader.getImage(name); - if (this.texture === null) { - throw "melonjs: Atlas texture '" + name + "' not found"; + if (atlas && atlas.meta) { + // Texture Packer + if (atlas.meta.app.contains("texturepacker")) { + this.format = "texturepacker"; + // set the texture + if (texture===undefined) { + var name = me.utils.getBasename(atlas.meta.image); + this.texture = me.loader.getImage(name); + if (this.texture === null) { + throw "melonjs: Atlas texture '" + name + "' not found"; + } + } else { + this.texture = texture; } - } else { + } + // ShoeBox + if (atlas.meta.app.contains("ShoeBox")) { + if (!atlas.meta.exporter || !atlas.meta.exporter.contains("melonJS")) { + throw "melonjs: ShoeBox requires the JSON exporter : https://github.com/melonjs/melonJS/tree/master/media/shoebox_JSON_export.sbx"; + } + this.format = "ShoeBox"; + // set the texture this.texture = texture; } // initialize the atlas @@ -81,20 +96,23 @@ initFromTexturePacker : function (data) { var atlas = {}; data.frames.forEach(function(frame) { - atlas[frame.filename] = { - frame: new me.Rect( - new me.Vector2d(frame.frame.x, frame.frame.y), - frame.frame.w, frame.frame.h - ), - source: new me.Rect( - new me.Vector2d(frame.spriteSourceSize.x, frame.spriteSourceSize.y), - frame.spriteSourceSize.w, frame.spriteSourceSize.h - ), - // non trimmed size, but since we don't support trimming both value are the same - //sourceSize: new me.Vector2d(frame.sourceSize.w,frame.sourceSize.h), - rotated : frame.rotated===true, - trimmed : frame.trimmed===true - }; + // fix wrongly formatted JSON (e.g. last dummy object in ShoeBox) + if (frame.hasOwnProperty("filename")) { + atlas[frame.filename] = { + frame: new me.Rect( + new me.Vector2d(frame.frame.x, frame.frame.y), + frame.frame.w, frame.frame.h + ), + source: new me.Rect( + new me.Vector2d(frame.spriteSourceSize.x, frame.spriteSourceSize.y), + frame.spriteSourceSize.w, frame.spriteSourceSize.h + ), + // non trimmed size, but since we don't support trimming both value are the same + //sourceSize: new me.Vector2d(frame.sourceSize.w,frame.sourceSize.h), + rotated : frame.rotated===true, + trimmed : frame.trimmed===true + }; + } }); return atlas; },