@makefully/platypus 4.1.10 → 4.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makefully/platypus",
3
- "version": "4.1.10",
3
+ "version": "4.1.11",
4
4
  "description": "2D tile-based HTML5 game engine with a component-based entity model",
5
5
  "license": "MIT",
6
6
  "contributors": [
@@ -7,6 +7,7 @@
7
7
  /* global platypus, setTimeout */
8
8
  import Data from './Data.js';
9
9
  import DataMap from './DataMap.js';
10
+ import PIXIAnimation from './PIXIAnimation.js';
10
11
  import {Assets} from 'pixi.js';
11
12
  import {arrayCache} from './utils/array.js';
12
13
 
@@ -58,6 +59,7 @@ export default class AssetManager {
58
59
  asset.src = '';
59
60
  }
60
61
  assets.delete(alias);
62
+ PIXIAnimation.invalidateTextureSources(alias);
61
63
  }
62
64
 
63
65
  return !counts[alias];
@@ -4,15 +4,74 @@ import {arrayCache, greenSlice} from './utils/array.js';
4
4
  import Data from './Data.js';
5
5
 
6
6
  const
7
- MAX_KEY_LENGTH_PER_IMAGE = 128,
8
7
  animationCache = {},
9
8
  textureSourceCache = {},
10
9
  doNothing = function () {},
11
10
  emptyFrame = Texture.EMPTY,
12
- regex = /[\[\]{},-]/g,
11
+ imageBasename = /([\w-\.]+)\.(\w+)$/,
12
+ hashString = function (value) {
13
+ const
14
+ str = typeof value === 'string' ? value : JSON.stringify(value);
15
+ let hash = 5381;
16
+
17
+ for (let i = 0; i < str.length; i++) {
18
+ hash = ((hash << 5) + hash) ^ str.charCodeAt(i);
19
+ }
20
+
21
+ return (hash >>> 0).toString(36);
22
+ },
23
+ getTextureCacheKey = function (path) {
24
+ return platypus.assetCache?.getFileId ? platypus.assetCache.getFileId(path) : path;
25
+ },
26
+ resolveTextureAsset = function (path) {
27
+ const
28
+ assetCache = platypus.assetCache;
29
+
30
+ if (!assetCache) {
31
+ return null;
32
+ }
33
+
34
+ let asset = assetCache.get(path);
35
+
36
+ if (asset) {
37
+ return asset;
38
+ }
39
+
40
+ const
41
+ basename = typeof path === 'string' ? path.match(imageBasename) : null;
42
+
43
+ if (basename) {
44
+ asset = assetCache.get(basename[1]);
45
+
46
+ if (asset) {
47
+ return asset;
48
+ }
49
+ }
50
+
51
+ return null;
52
+ },
53
+ getTextureSourceAliases = function (alias) {
54
+ const
55
+ aliases = arrayCache.setUp(alias),
56
+ basename = typeof alias === 'string' ? alias.match(imageBasename) : null;
57
+
58
+ if (platypus.assetCache?.getFileId) {
59
+ const
60
+ fileId = platypus.assetCache.getFileId(alias);
61
+
62
+ if (fileId !== alias) {
63
+ aliases.push(fileId);
64
+ }
65
+ }
66
+
67
+ if (basename) {
68
+ aliases.push(basename[1]);
69
+ }
70
+
71
+ return aliases;
72
+ },
13
73
  getTextureSources = function (images) {
14
74
  const
15
- assetCache = platypus.assetCache,
16
75
  bts = arrayCache.setUp();
17
76
 
18
77
  for (let i = 0; i < images.length; i++) {
@@ -20,17 +79,21 @@ const
20
79
  path = images[i];
21
80
 
22
81
  if (typeof path === 'string') {
23
- if (!textureSourceCache[path]) {
24
- const
25
- asset = assetCache.get(path);
82
+ const
83
+ cacheKey = getTextureCacheKey(path),
84
+ asset = resolveTextureAsset(path);
26
85
 
27
- if (!asset) {
28
- platypus.debug.warn(`PIXIAnimation: "${path}" is not a loaded asset.`);
29
- break;
30
- }
31
- textureSourceCache[path] = asset.source;
86
+ if (!asset) {
87
+ delete textureSourceCache[cacheKey];
88
+ platypus.debug.warn(`PIXIAnimation: "${path}" is not a loaded asset.`);
89
+ break;
90
+ }
91
+
92
+ if (textureSourceCache[cacheKey] !== asset.source) {
93
+ textureSourceCache[cacheKey] = asset.source;
32
94
  }
33
- bts.push(textureSourceCache[path]);
95
+
96
+ bts.push(textureSourceCache[cacheKey]);
34
97
  } else {
35
98
  bts.push(new TextureSource(path));
36
99
  }
@@ -49,9 +112,7 @@ const
49
112
  }
50
113
  }
51
114
 
52
- spriteSheet.id = JSON.stringify(spriteSheet).replace(regex, '');
53
-
54
- return spriteSheet.id;
115
+ return `ss-${hashString(spriteSheet)}`;
55
116
  },
56
117
  getDefaultAnimation = function (length, textures) {
57
118
  const
@@ -397,6 +458,29 @@ const
397
458
  };
398
459
  }
399
460
 
461
+ /**
462
+ * Removes cached texture sources for an unloaded asset alias.
463
+ *
464
+ * @method platypus.PIXIAnimation.invalidateTextureSources
465
+ * @param {*} alias Asset alias or path used when the texture was cached.
466
+ */
467
+ static invalidateTextureSources (alias) {
468
+ const
469
+ aliases = getTextureSourceAliases(alias),
470
+ cacheKey = getTextureCacheKey(alias);
471
+ let i = aliases.length;
472
+
473
+ if (aliases.indexOf(cacheKey) === -1) {
474
+ aliases.push(cacheKey);
475
+ }
476
+
477
+ while (i--) {
478
+ delete textureSourceCache[aliases[i]];
479
+ }
480
+
481
+ arrayCache.recycle(aliases);
482
+ }
483
+
400
484
  /**
401
485
  * This method formats a provided value into a valid PIXIAnimation Sprite Sheet. This includes accepting the EaselJS spec, strings mapping to Platypus sprite sheets, or arrays of either.
402
486
  *
@@ -406,7 +490,6 @@ const
406
490
  */
407
491
  static formatSpriteSheet (spriteSheet) {
408
492
  const
409
- imageParts = /([\w-\.]+)\.(\w+)$/,
410
493
  addAnimations = function (source = {}, destination, speedRatio, firstFrameIndex, id) {
411
494
  const
412
495
  keys = Object.keys(source),
@@ -458,7 +541,6 @@ const
458
541
  ));
459
542
  }
460
543
  },
461
- createId = (images) => images.map((image) => (image.src ?? image).substring(0, MAX_KEY_LENGTH_PER_IMAGE)).join(','),
462
544
  format = function (source, destination) {
463
545
  const
464
546
  {
@@ -479,11 +561,8 @@ const
479
561
  firstImageIndex = dImages.length,
480
562
  firstFrameIndex = dFrames.length;
481
563
 
482
- // Set up id
483
- if (dID) {
484
- destination.id = `${dID};${sID ?? createId(sImages)}`;
485
- } else {
486
- destination.id = sID ?? createId(sImages);
564
+ if (sID) {
565
+ destination.id = dID ? `${dID};${sID}` : sID;
487
566
  }
488
567
 
489
568
  // Set up images array
@@ -546,7 +625,7 @@ const
546
625
  formatImages = function (name) {
547
626
  if (typeof name === 'string') {
548
627
  const
549
- match = name.match(imageParts);
628
+ match = name.match(imageBasename);
550
629
 
551
630
  if (match) {
552
631
  return match[1];
@@ -6,6 +6,176 @@ import {inflate} from 'pako';
6
6
  import TiledLoader from './TiledLoader.js';
7
7
 
8
8
  const
9
+ assertLevelPiece = function (piece, label) {
10
+ if (piece == null) {
11
+ throw new Error(`Level Builder: Level piece "${label}" is undefined. Check that it is defined in platypus.game.settings.levels or levelPieces.`);
12
+ }
13
+
14
+ if (typeof piece !== 'object') {
15
+ throw new Error(`Level Builder: Level piece "${label}" must be a level definition object, received ${typeof piece}.`);
16
+ }
17
+
18
+ if (piece.width == null) {
19
+ throw new Error(`Level Builder: Level piece "${label}" is missing width.`);
20
+ }
21
+
22
+ if (piece.height == null) {
23
+ throw new Error(`Level Builder: Level piece "${label}" is missing height.`);
24
+ }
25
+
26
+ if (piece.tilewidth == null) {
27
+ throw new Error(`Level Builder: Level piece "${label}" is missing tilewidth.`);
28
+ }
29
+
30
+ if (piece.tileheight == null) {
31
+ throw new Error(`Level Builder: Level piece "${label}" is missing tileheight.`);
32
+ }
33
+
34
+ if (piece.layers == null) {
35
+ throw new Error(`Level Builder: Level piece "${label}" is missing a layers array.`);
36
+ }
37
+
38
+ if (!Array.isArray(piece.layers)) {
39
+ throw new Error(`Level Builder: Level piece "${label}" layers must be an array.`);
40
+ }
41
+
42
+ return piece;
43
+ },
44
+ assertLevelTemplate = function (template) {
45
+ if (template == null) {
46
+ throw new Error(`Level Builder: levelTemplate is required but was not provided.`);
47
+ }
48
+
49
+ if (!Array.isArray(template)) {
50
+ throw new Error(`Level Builder: levelTemplate must be an array, received ${typeof template}.`);
51
+ }
52
+
53
+ if (template.length === 0) {
54
+ throw new Error(`Level Builder: levelTemplate cannot be empty.`);
55
+ }
56
+
57
+ let rowLength = null;
58
+
59
+ for (let i = 0; i < template.length; i++) {
60
+ const
61
+ row = template[i];
62
+
63
+ if (typeof row === 'string') {
64
+ if (!row) {
65
+ throw new Error(`Level Builder: levelTemplate[${i}] is an empty string.`);
66
+ }
67
+
68
+ if (rowLength != null && rowLength !== '1d') {
69
+ throw new Error(`Level Builder: levelTemplate is not rectangular: row 0 has ${rowLength} columns but row ${i} is a string.`);
70
+ }
71
+
72
+ rowLength = '1d';
73
+ } else if (Array.isArray(row)) {
74
+ if (row.length === 0) {
75
+ throw new Error(`Level Builder: levelTemplate row ${i} is empty.`);
76
+ }
77
+
78
+ if (rowLength === '1d') {
79
+ throw new Error(`Level Builder: levelTemplate is not rectangular: row 0 is a string but row ${i} is an array.`);
80
+ }
81
+
82
+ if (rowLength == null) {
83
+ rowLength = row.length;
84
+ } else if (rowLength !== row.length) {
85
+ throw new Error(`Level Builder: levelTemplate is not rectangular: row 0 has ${rowLength} columns but row ${i} has ${row.length}.`);
86
+ }
87
+
88
+ for (let j = 0; j < row.length; j++) {
89
+ if (typeof row[j] !== 'string') {
90
+ throw new Error(`Level Builder: levelTemplate[${i}][${j}] must be a piece id string, received ${typeof row[j]}.`);
91
+ }
92
+
93
+ if (!row[j]) {
94
+ throw new Error(`Level Builder: levelTemplate[${i}][${j}] is an empty string.`);
95
+ }
96
+ }
97
+ } else {
98
+ throw new Error(`Level Builder: levelTemplate[${i}] must be a string or array of strings, received ${typeof row}.`);
99
+ }
100
+ }
101
+
102
+ return template;
103
+ },
104
+ assertLevelPieces = function (pieces) {
105
+ if (pieces == null) {
106
+ return;
107
+ }
108
+
109
+ if (typeof pieces !== 'object' || Array.isArray(pieces)) {
110
+ throw new Error(`Level Builder: levelPieces must be an object, received ${Array.isArray(pieces) ? 'array' : typeof pieces}.`);
111
+ }
112
+
113
+ const
114
+ keys = Object.keys(pieces),
115
+ {length} = keys;
116
+
117
+ for (let i = 0; i < length; i++) {
118
+ const
119
+ key = keys[i],
120
+ value = pieces[key];
121
+
122
+ if (typeof value === 'string') {
123
+ if (!value) {
124
+ throw new Error(`Level Builder: levelPieces["${key}"] is an empty string.`);
125
+ }
126
+ } else if (Array.isArray(value)) {
127
+ if (value.length === 0) {
128
+ throw new Error(`Level Builder: levelPieces["${key}"] is an empty array. Provide at least one level piece id.`);
129
+ }
130
+
131
+ for (let j = 0; j < value.length; j++) {
132
+ if (typeof value[j] !== 'string') {
133
+ throw new Error(`Level Builder: levelPieces["${key}"][${j}] must be a string level id, received ${typeof value[j]}.`);
134
+ }
135
+
136
+ if (!value[j]) {
137
+ throw new Error(`Level Builder: levelPieces["${key}"][${j}] is an empty string.`);
138
+ }
139
+ }
140
+ } else {
141
+ throw new Error(`Level Builder: levelPieces["${key}"] must be a string or array of strings, received ${typeof value}.`);
142
+ }
143
+ }
144
+ },
145
+ resolveLevelPiece = function (piece, label) {
146
+ if (typeof piece === 'string') {
147
+ const
148
+ levelDefinitions = platypus.game.settings.levels,
149
+ transformIndex = piece.indexOf(':');
150
+ let levelDefinition = levelDefinitions?.[piece];
151
+
152
+ if (!levelDefinition && transformIndex >= 0) {
153
+ const
154
+ baseLabel = piece.substring(0, transformIndex),
155
+ transform = piece.substring(transformIndex + 1);
156
+
157
+ levelDefinition = levelDefinitions?.[baseLabel];
158
+
159
+ if (!levelDefinition) {
160
+ throw new Error(`Level Builder: Level piece "${baseLabel}" (from "${piece}") was not found in platypus.game.settings.levels.`);
161
+ }
162
+
163
+ if (transform === 'mirror') {
164
+ return levelDefinitions[piece] = mirrorSegment(assertLevelPiece(levelDefinition, baseLabel));
165
+ }
166
+
167
+ throw new Error(`Level Builder: Unknown transform "${transform}" in level piece "${piece}". Supported transforms: mirror.`);
168
+ }
169
+
170
+ if (!levelDefinition) {
171
+ throw new Error(`Level Builder: Level piece "${piece}" was not found in platypus.game.settings.levels.`);
172
+ }
173
+
174
+ return assertLevelPiece(levelDefinition, piece);
175
+ }
176
+
177
+ return assertLevelPiece(piece, label);
178
+ },
9
179
  maskXFlip = 0x80000000,
10
180
  decodeString = (str, index) => (((str.charCodeAt(index)) + (str.charCodeAt(index + 1) << 8) + (str.charCodeAt(index + 2) << 16) + (str.charCodeAt(index + 3) << 24 )) >>> 0),
11
181
  decodeArray = (arr, index) => ((arr[index] + (arr[index + 1] << 8) + (arr[index + 2] << 16) + (arr[index + 3] << 24 )) >>> 0),
@@ -25,7 +195,11 @@ const
25
195
 
26
196
  return arr;
27
197
  },
28
- decodeLayer = function (layer) {
198
+ decodeLayer = function (layer, label) {
199
+ if (layer == null) {
200
+ throw new Error(`Level Builder: Cannot decode layer${label ? ` in "${label}"` : ''}: layer is undefined.`);
201
+ }
202
+
29
203
  if (layer.encoding === 'base64') {
30
204
  layer.data = decodeBase64(layer.data, layer.compression);
31
205
  layer.encoding = 'csv'; // So we won't have to decode again.
@@ -81,8 +255,8 @@ const
81
255
  }
82
256
  return list;
83
257
  },
84
- mergeSegment = function (level, segment, mergeAxis) {
85
- segment = cloneLevelDefinition(segment);
258
+ mergeSegment = function (level, segment, mergeAxis, segmentLabel) {
259
+ segment = cloneLevelDefinition(assertLevelPiece(segment, segmentLabel ?? 'segment'));
86
260
 
87
261
  if (!level.tilewidth && !level.tileheight) {
88
262
  //set level tile size data if it's not already set.
@@ -107,9 +281,13 @@ const
107
281
  }
108
282
 
109
283
  for (let i = 0; i < segment.layers.length; i++) {
284
+ if (segment.layers[i] == null) {
285
+ throw new Error(`Level Builder: Level piece "${segmentLabel ?? 'segment'}" layer ${i} is undefined.`);
286
+ }
287
+
110
288
  if (!level.layers[i]) {
111
289
  //if the level doesn't have a layer yet, we're creating it and then copying it from the segment.
112
- decodeLayer(segment.layers[i]);
290
+ decodeLayer(segment.layers[i], segmentLabel);
113
291
 
114
292
  const
115
293
  layer = level.layers[i] = cloneLevelDefinition(segment.layers[i]);
@@ -126,7 +304,7 @@ const
126
304
  //if the level does have a layer, we're appending the new data to it.
127
305
  if (level.layers[i].data && segment.layers[i].data) {
128
306
  // Make sure we're not trying to merge compressed levels.
129
- decodeLayer(segment.layers[i]);
307
+ decodeLayer(segment.layers[i], segmentLabel);
130
308
 
131
309
  if (mergeAxis === 'horizontal') {
132
310
  level.layers[i].data = mergeData(level.layers[i].data, level.width, segment.layers[i].data, segment.width, level.height, mergeAxis);
@@ -169,7 +347,6 @@ const
169
347
  },
170
348
  mergeLevels = function (levelSegments) {
171
349
  const
172
- levelDefinitions = platypus.game.settings.levels,
173
350
  level = {
174
351
  height: 0,
175
352
  width: 0,
@@ -184,35 +361,25 @@ const
184
361
  layers: []
185
362
  };
186
363
 
364
+ if (!Array.isArray(levelSegments[i])) {
365
+ throw new Error(`Level Builder: mergeLevels row ${i} must be an array of level pieces, received ${typeof levelSegments[i]}.`);
366
+ }
367
+
187
368
  for (let j = 0; j < levelSegments[i].length; j++) {
188
- //Merge horizontally
189
- if (typeof levelSegments[i][j] === 'string') {
190
- const
191
- levelDefinitionLabel = levelSegments[i][j],
192
- transformIndex = levelDefinitionLabel.indexOf(':');
193
- let levelDefinition = levelDefinitions[levelDefinitionLabel];
194
-
195
- // check for transform
196
- if (!levelDefinition && (transformIndex >= 0)) {
197
- const transform = levelDefinitionLabel.substring(transformIndex + 1);
369
+ const
370
+ piece = levelSegments[i][j],
371
+ pieceLabel = typeof piece === 'string' ? piece : `row ${i}, column ${j}`;
198
372
 
199
- levelDefinition = levelDefinitions[levelDefinitionLabel.substring(0, transformIndex)];
200
- if (transform === 'mirror') {
201
- levelDefinition = levelDefinitions[levelDefinitionLabel] = mirrorSegment(levelDefinition);
202
- }
203
- }
204
- mergeSegment(row, levelDefinition, 'horizontal');
205
- } else {
206
- mergeSegment(row, levelSegments[i][j], 'horizontal');
207
- }
373
+ //Merge horizontally
374
+ mergeSegment(row, resolveLevelPiece(piece, pieceLabel), 'horizontal', pieceLabel);
208
375
  }
209
376
  //Then merge vertically
210
- mergeSegment(level, row, 'vertical');
377
+ mergeSegment(level, row, 'vertical', `row ${i}`);
211
378
  }
212
379
  return level;
213
380
  },
214
- mirrorSegment = function (segment) {
215
- segment = cloneLevelDefinition(segment);
381
+ mirrorSegment = function (segment, segmentLabel) {
382
+ segment = cloneLevelDefinition(assertLevelPiece(segment, segmentLabel ?? 'segment'));
216
383
 
217
384
  const
218
385
  newSegment = {
@@ -221,7 +388,11 @@ const
221
388
  width = segment.width * segment.tilewidth;
222
389
 
223
390
  for (let i = 0; i < segment.layers.length; i++) {
224
- decodeLayer(segment.layers[i]);
391
+ if (segment.layers[i] == null) {
392
+ throw new Error(`Level Builder: Level piece "${segmentLabel ?? 'segment'}" layer ${i} is undefined.`);
393
+ }
394
+
395
+ decodeLayer(segment.layers[i], segmentLabel);
225
396
 
226
397
  const
227
398
  fromLayer = segment.layers[i],
@@ -369,6 +540,8 @@ export default createComponentClass(/** @lends platypus.components.LevelBuilder.
369
540
  this.levelMessage.persistentData = data;
370
541
  this.levelTemplate = data?.levelTemplate ?? this.levelTemplate;
371
542
  this.useUniques = data?.useUniques ?? this.useUniques;
543
+ assertLevelPieces(piecesToCopy);
544
+
372
545
  this.levelPieces = {};
373
546
  if (piecesToCopy) {
374
547
  const
@@ -385,32 +558,26 @@ export default createComponentClass(/** @lends platypus.components.LevelBuilder.
385
558
  this.levelPieces[key] = [
386
559
  ...piecesToCopy[key]
387
560
  ];
388
- } else {
389
- throw ('Level Builder: Level pieces of incorrect type: ' + piecesToCopy[key]);
390
561
  }
391
562
  }
392
563
  }
393
564
 
394
565
  if (this.levelTemplate) {
395
- if (this.levelTemplate) {
396
- this.levelMessage.level = [];
397
- for (let i = 0; i < this.levelTemplate.length; i++) {
398
- const
399
- templateRow = this.levelTemplate[i];
400
-
401
- if (typeof templateRow === "string") {
402
- this.levelMessage.level[i] = this.getLevelPiece(templateRow);
403
- } else if (templateRow.length) {
404
- this.levelMessage.level[i] = [];
405
- for (let j = 0; j < templateRow.length; j++) {
406
- this.levelMessage.level[i][j] = this.getLevelPiece(templateRow[j]);
407
- }
408
- } else {
409
- throw ('Level Builder: Template row is neither a string or array. What is it?');
566
+ assertLevelTemplate(this.levelTemplate);
567
+
568
+ this.levelMessage.level = [];
569
+ for (let i = 0; i < this.levelTemplate.length; i++) {
570
+ const
571
+ templateRow = this.levelTemplate[i];
572
+
573
+ if (typeof templateRow === "string") {
574
+ this.levelMessage.level[i] = this.getLevelPiece(templateRow);
575
+ } else {
576
+ this.levelMessage.level[i] = [];
577
+ for (let j = 0; j < templateRow.length; j++) {
578
+ this.levelMessage.level[i][j] = this.getLevelPiece(templateRow[j]);
410
579
  }
411
580
  }
412
- } else {
413
- platypus.debug.warn('Level Builder: Template is not defined');
414
581
  }
415
582
  } else {
416
583
  platypus.debug.warn('Level Builder: There is no level template.');
@@ -452,6 +619,10 @@ export default createComponentClass(/** @lends platypus.components.LevelBuilder.
452
619
 
453
620
  methods: {// These are methods that are called by this component.
454
621
  getLevelPiece: function (type) {
622
+ if (type == null || type === '') {
623
+ throw new Error(`Level Builder: Template references an invalid piece id: ${type}.`);
624
+ }
625
+
455
626
  const
456
627
  pieces = this.levelPieces[type] ?? type;
457
628
 
@@ -178,11 +178,17 @@ export default createComponentClass(/** @lends platypus.components.RenderSprite.
178
178
 
179
179
  getAssetList (a, b, c) {
180
180
  const
181
- image = a?.image ?? b?.image ?? c?.image;
181
+ image = a?.image ?? b?.image ?? c?.image,
182
+ formatImageAsset = (src) => {
183
+ const
184
+ alias = platypus.assetCache?.getFileId ? platypus.assetCache.getFileId(src) : src;
185
+
186
+ return {
187
+ alias: [alias],
188
+ src
189
+ };
190
+ };
182
191
 
183
- return (image ? [image] : a?.images ?? b?.images ?? c?.images ?? []).map((src) => ({
184
- alias: [src],
185
- src
186
- }));
192
+ return (image ? [image] : a?.images ?? b?.images ?? c?.images ?? []).map(formatImageAsset);
187
193
  }
188
194
  });
@@ -489,12 +489,21 @@ export default createComponentClass(/** @lends platypus.components.RenderSprite.
489
489
 
490
490
  getAssetList: (function () {
491
491
  const
492
+ formatImageAsset = function (src) {
493
+ const
494
+ alias = platypus.assetCache?.getFileId ? platypus.assetCache.getFileId(src) : src;
495
+
496
+ return {
497
+ alias: [alias],
498
+ src
499
+ };
500
+ },
492
501
  getImages = function (ss, spriteSheets) {
493
502
  if (ss) {
494
503
  if (typeof ss === 'string') {
495
504
  return getImages(spriteSheets[ss], spriteSheets);
496
505
  } else if (ss.images) {
497
- return greenSlice(ss.images);
506
+ return greenSlice(ss.images).map(formatImageAsset);
498
507
  }
499
508
  }
500
509