Skip to content

Commit c748530

Browse files
committed
Added Starling/Sparrow XML Texture Atlas format support.
1 parent c5ace72 commit c748530

16 files changed

Lines changed: 621 additions & 134 deletions

File tree

Phaser/Cache.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,20 @@ module Phaser {
8484
* @param key {string} Asset key for the texture atlas.
8585
* @param url {string} URL of this texture atlas file.
8686
* @param data {object} Extra texture atlas data.
87-
* @param data {object} Texture atlas frames data.
87+
* @param atlasData {object} Texture atlas frames data.
8888
*/
89-
public addTextureAtlas(key: string, url: string, data, jsonData) {
89+
public addTextureAtlas(key: string, url: string, data, atlasData, format) {
9090

9191
this._images[key] = { url: url, data: data, spriteSheet: true };
92-
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, jsonData);
92+
93+
if (format == Phaser.Loader.TEXTURE_ATLAS_JSON_ARRAY)
94+
{
95+
this._images[key].frameData = AnimationLoader.parseJSONData(this._game, atlasData);
96+
}
97+
else if (format == Phaser.Loader.TEXTURE_ATLAS_XML_STARLING)
98+
{
99+
this._images[key].frameData = AnimationLoader.parseXMLData(this._game, atlasData, format);
100+
}
93101

94102
}
95103

Phaser/Loader.ts

Lines changed: 132 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ module Phaser {
8282
*/
8383
public crossOrigin: string = '';
8484

85+
/**
86+
* TextureAtlas data format constants
87+
*/
88+
public static TEXTURE_ATLAS_JSON_ARRAY: number = 0;
89+
public static TEXTURE_ATLAS_JSON_HASH: number = 1;
90+
public static TEXTURE_ATLAS_XML_STARLING: number = 2;
91+
8592
/**
8693
* Reset loader, this will remove all loaded assets.
8794
*/
@@ -133,44 +140,92 @@ module Phaser {
133140
/**
134141
* Add a new texture atlas loading request.
135142
* @param key {string} Unique asset key of the texture atlas file.
136-
* @param url {string} URL of texture atlas file.
137-
* @param [jsonURL] {string} url of JSON data file.
138-
* @param [jsonData] {object} JSON data object.
143+
* @param textureURL {string} The url of the texture atlas image file.
144+
* @param [atlasURL] {string} The url of the texture atlas data file (json/xml)
145+
* @param [atlasData] {object} A JSON or XML data object.
146+
* @param [format] {number} A value describing the format of the data.
139147
*/
140-
public addTextureAtlas(key: string, url: string, jsonURL?: string = null, jsonData? = null) {
148+
public addTextureAtlas(key: string, textureURL: string, atlasURL?: string = null, atlasData? = null, format?:number = Loader.TEXTURE_ATLAS_JSON_ARRAY) {
141149

142150
if (this.checkKeyExists(key) === false)
143151
{
144-
if (jsonURL !== null)
152+
if (atlasURL !== null)
145153
{
146-
// A URL to a json file has been given
154+
// A URL to a json/xml file has been given
147155
this._queueSize++;
148-
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: jsonURL, jsonData: null, error: false, loaded: false };
156+
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, atlasURL: atlasURL, data: null, format: format, error: false, loaded: false };
149157
this._keys.push(key);
150158
}
151159
else
152160
{
153-
// A json string or object has been given
154-
if (typeof jsonData === 'string')
161+
if (format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
155162
{
156-
var data = JSON.parse(jsonData);
163+
// A json string or object has been given
164+
if (typeof atlasData === 'string')
165+
{
166+
atlasData = JSON.parse(atlasData);
167+
}
168+
157169
// Malformed?
158-
if (data['frames'])
170+
if (atlasData['frames'])
159171
{
160172
this._queueSize++;
161-
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: data['frames'], error: false, loaded: false };
173+
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, data: null, atlasURL: null, atlasData: atlasData['frames'], format: format, error: false, loaded: false };
162174
this._keys.push(key);
163175
}
176+
else
177+
{
178+
throw new Error("Phaser.Loader. Invalid Texture Atlas JSON given, missing frames block");
179+
}
164180
}
165-
else
181+
else if (format == Loader.TEXTURE_ATLAS_XML_STARLING)
166182
{
183+
// An xml string or object has been given
184+
if (typeof atlasData === 'string')
185+
{
186+
var tmp;
187+
var xml;
188+
189+
try
190+
{
191+
if (window['DOMParser'])
192+
{
193+
tmp = new DOMParser();
194+
xml = tmp.parseFromString(atlasData, "text/xml");
195+
}
196+
else
197+
{
198+
xml = new ActiveXObject("Microsoft.XMLDOM");
199+
xml.async = 'false';
200+
xml.loadXML(atlasData);
201+
}
202+
}
203+
catch (e)
204+
{
205+
xml = undefined;
206+
}
207+
208+
if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length)
209+
{
210+
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given");
211+
}
212+
else
213+
{
214+
atlasData = xml;
215+
}
216+
}
217+
167218
// Malformed?
168-
if (jsonData['frames'])
219+
if (atlasData.getElementsByTagName('TextureAtlas'))
169220
{
170221
this._queueSize++;
171-
this._fileList[key] = { type: 'textureatlas', key: key, url: url, data: null, jsonURL: null, jsonData: jsonData['frames'], error: false, loaded: false };
222+
this._fileList[key] = { type: 'textureatlas', key: key, url: textureURL, data: null, atlasURL: null, atlasData: atlasData, format: format, error: false, loaded: false };
172223
this._keys.push(key);
173224
}
225+
else
226+
{
227+
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given, missing <TextureAtlas> tag");
228+
}
174229
}
175230

176231
}
@@ -344,18 +399,27 @@ module Phaser {
344399
break;
345400

346401
case 'textureatlas':
347-
if (file.jsonURL == null)
402+
if (file.atlasURL == null)
348403
{
349-
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.jsonData);
404+
this._game.cache.addTextureAtlas(file.key, file.url, file.data, file.atlasData, file.format);
350405
}
351406
else
352407
{
353-
// Load the JSON before carrying on with the next file
408+
// Load the JSON or XML before carrying on with the next file
354409
loadNext = false;
355-
this._xhr.open("GET", file.jsonURL, true);
410+
this._xhr.open("GET", file.atlasURL, true);
356411
this._xhr.responseType = "text";
357-
this._xhr.onload = () => this.jsonLoadComplete(file.key);
358-
this._xhr.onerror = () => this.jsonLoadError(file.key);
412+
413+
if (file.format == Loader.TEXTURE_ATLAS_JSON_ARRAY)
414+
{
415+
this._xhr.onload = () => this.jsonLoadComplete(file.key);
416+
}
417+
else if (file.format == Loader.TEXTURE_ATLAS_XML_STARLING)
418+
{
419+
this._xhr.onload = () => this.xmlLoadComplete(file.key);
420+
}
421+
422+
this._xhr.onerror = () => this.dataLoadError(file.key);
359423
this._xhr.send();
360424
}
361425
break;
@@ -390,7 +454,7 @@ module Phaser {
390454
if (data['frames'])
391455
{
392456
var file = this._fileList[key];
393-
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames']);
457+
this._game.cache.addTextureAtlas(file.key, file.url, file.data, data['frames'], file.format);
394458
}
395459

396460
this.nextFile(key, true);
@@ -401,14 +465,59 @@ module Phaser {
401465
* Error occured when load a JSON.
402466
* @param key {string} Key of the error loading JSON file.
403467
*/
404-
private jsonLoadError(key: string) {
468+
private dataLoadError(key: string) {
405469

406470
var file = this._fileList[key];
407471
file.error = true;
408472
this.nextFile(key, true);
409473

410474
}
411475

476+
private xmlLoadComplete(key: string) {
477+
478+
var atlasData = this._xhr.response; // xml?
479+
var tmp;
480+
var xml;
481+
482+
try
483+
{
484+
if (window['DOMParser'])
485+
{
486+
tmp = new DOMParser();
487+
xml = tmp.parseFromString(atlasData, "text/xml");
488+
}
489+
else
490+
{
491+
xml = new ActiveXObject("Microsoft.XMLDOM");
492+
xml.async = 'false';
493+
xml.loadXML(atlasData);
494+
}
495+
}
496+
catch (e)
497+
{
498+
xml = undefined;
499+
}
500+
501+
if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length)
502+
{
503+
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given");
504+
}
505+
506+
// Malformed?
507+
if (xml.getElementsByTagName('TextureAtlas'))
508+
{
509+
var file = this._fileList[key];
510+
this._game.cache.addTextureAtlas(file.key, file.url, file.data, xml, file.format);
511+
}
512+
else
513+
{
514+
throw new Error("Phaser.Loader. Invalid Texture Atlas XML given, missing <TextureAtlas> tag");
515+
}
516+
517+
this.nextFile(key, true);
518+
519+
}
520+
412521
/**
413522
* Handle loading next file.
414523
* @param previousKey {string} Key of previous loaded asset.

Phaser/State.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,17 @@ module Phaser {
152152
public destroy() { }
153153

154154
/**
155-
* Call this method to see if one object collids another.
156-
* @return {boolean} Whether the given objects or groups collids.
157-
*/
158-
public collide(ObjectOrGroup1: Basic = null, ObjectOrGroup2: Basic = null, NotifyCallback = null): bool {
159-
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Collision.separate);
155+
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
156+
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
157+
* @param object1 The first GameObject or Group to check. If null the world.group is used.
158+
* @param object2 The second GameObject or Group to check.
159+
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
160+
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
161+
* @param context The context in which the callbacks will be called
162+
* @returns {boolean} true if the objects overlap, otherwise false.
163+
*/
164+
public collide(objectOrGroup1: Basic = null, objectOrGroup2: Basic = null, notifyCallback = null, context? = this.game.callbackContext): bool {
165+
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Collision.separate, context);
160166
}
161167

162168
}

Phaser/system/animation/AnimationLoader.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,32 @@ module Phaser {
9696

9797
}
9898

99+
public static parseXMLData(game: Game, xml, format: number): FrameData {
100+
101+
// Let's create some frames then
102+
var data: FrameData = new FrameData();
103+
104+
var frames = xml.getElementsByTagName('SubTexture');
105+
106+
var newFrame: Frame;
107+
108+
for (var i = 0; i < frames.length; i++)
109+
{
110+
var frame = frames[i].attributes;
111+
112+
newFrame = data.addFrame(new Frame(frame.x.nodeValue, frame.y.nodeValue, frame.width.nodeValue, frame.height.nodeValue, frame.name.nodeValue));
113+
114+
// Trimmed?
115+
if (frame.frameX.nodeValue != '-0' || frame.frameY.nodeValue != '-0')
116+
{
117+
newFrame.setTrim(true, frame.width.nodeValue, frame.height.nodeValue, Math.abs(frame.frameX.nodeValue), Math.abs(frame.frameY.nodeValue), frame.frameWidth.nodeValue, frame.frameHeight.nodeValue);
118+
}
119+
120+
}
121+
122+
return data;
123+
}
124+
99125
}
100126

101127
}

Phaser/system/animation/Frame.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,19 @@ module Phaser {
3838
* @type {number}
3939
*/
4040
public x: number;
41+
4142
/**
4243
* Y position within the image to cut from.
4344
* @type {number}
4445
*/
4546
public y: number;
47+
4648
/**
4749
* Width of the frame.
4850
* @type {number}
4951
*/
5052
public width: number;
53+
5154
/**
5255
* Height of the frame.
5356
* @type {number}
@@ -82,31 +85,37 @@ module Phaser {
8285
public trimmed: bool;
8386

8487
// The coordinates of the trimmed sprite inside the original sprite
88+
8589
/**
8690
* Width of the original sprite.
8791
* @type {number}
8892
*/
8993
public sourceSizeW: number;
94+
9095
/**
9196
* Height of the original sprite.
9297
* @type {number}
9398
*/
9499
public sourceSizeH: number;
100+
95101
/**
96102
* X position of the trimmed sprite inside original sprite.
97103
* @type {number}
98104
*/
99105
public spriteSourceSizeX: number;
106+
100107
/**
101108
* Y position of the trimmed sprite inside original sprite.
102109
* @type {number}
103110
*/
104111
public spriteSourceSizeY: number;
112+
105113
/**
106114
* Width of the trimmed sprite.
107115
* @type {number}
108116
*/
109117
public spriteSourceSizeW: number;
118+
110119
/**
111120
* Height of the trimmed sprite.
112121
* @type {number}
@@ -130,7 +139,7 @@ module Phaser {
130139
* @param destWidth {number} Destiny draw width.
131140
* @param destHeight {number} Destiny draw height.
132141
*/
133-
public setTrim(trimmed: bool, actualWidth, actualHeight, destX, destY, destWidth, destHeight, ) {
142+
public setTrim(trimmed: bool, actualWidth: number, actualHeight: number, destX: number, destY: number, destWidth: number, destHeight: number) {
134143

135144
this.trimmed = trimmed;
136145

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,12 @@ V0.9.6
106106
* Added the GameObjectFactory to Game. You now make Sprites like this: game.add.sprite(). Much better separation of game object creation methods now. But you'll have to update ALL code, sorry!
107107
* Added GameObjectFactory methods to add existing objects to the game world, such as existingSprite(), existingTween(), etc.
108108
* Added the GameObjectFactory to Phaser.State
109+
* Added new format parameter to Loader.addTextureAtlas defining the format. Currently supported: JSON Array and Starling/Sparrow XML.
109110

110111
* TODO: Check that tween pausing works with the new performance.now
111112
* TODO: Game.Time should monitor pause duration
112113
* TODO: Investigate bug re: tilemap collision and animation frames
113-
* TODO: Update tests that use arrow keys and include touch/mouse support
114+
* TODO: Update tests that use arrow keys and include touch/mouse support (FlxControlHandler style)
114115
* TODO: GameObject.clipRect
115116
* TODO: Polygon geom primitive
116117
* TODO: Move GameObject transforms to a single matrix

Tests/Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@
239239
<TypeScriptCompile Include="tilemap\get tile.ts" />
240240
<TypeScriptCompile Include="tilemap\collision.ts" />
241241
<TypeScriptCompile Include="tilemap\collide with tile.ts" />
242+
<TypeScriptCompile Include="sprites\starling texture atlas 1.ts" />
243+
<Content Include="sprites\starling texture atlas 1.js">
244+
<DependentUpon>starling texture atlas 1.ts</DependentUpon>
245+
</Content>
242246
<Content Include="tilemap\collide with tile.js">
243247
<DependentUpon>collide with tile.ts</DependentUpon>
244248
</Content>

Tests/assets/sprites/shoebot.png

117 KB
Loading

0 commit comments

Comments
 (0)