@makefully/platypus 4.1.10 → 4.1.13
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/CHANGELOG.md +34 -0
- package/lib/platypus.js +1 -1
- package/package.json +2 -2
- package/src/AssetManager.js +2 -0
- package/src/Messenger.js +12 -12
- package/src/PIXIAnimation.js +102 -23
- package/src/components/EntityContainer.js +45 -13
- package/src/components/LevelBuilder.js +219 -48
- package/src/components/Render.js +11 -5
- package/src/components/RenderSpine.js +0 -8
- package/src/components/RenderSprite.js +10 -1
- package/src/index.js +7 -7
- package/src/sayHello.js +5 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makefully/platypus",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.13",
|
|
4
4
|
"description": "2D tile-based HTML5 game engine with a component-based entity model",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"contributors": [
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"webpack-dev-server": "^5.2.2"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@esotericsoftware/spine-pixi-v8": "^4.3.
|
|
76
|
+
"@esotericsoftware/spine-pixi-v8": "^4.3.13",
|
|
77
77
|
"@pixi/sound": "github:Makefully-Studios/sound#feature/media-file",
|
|
78
78
|
"@tweenjs/tween.js": "^23.1.1",
|
|
79
79
|
"pako": "^2.1.0",
|
package/src/AssetManager.js
CHANGED
|
@@ -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];
|
package/src/Messenger.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
/* global
|
|
1
|
+
/* global performance, platypus */
|
|
2
2
|
import EventHandlerList from './EventHandlerList.js';
|
|
3
3
|
import {arrayCache, greenSlice} from './utils/array.js';
|
|
4
4
|
|
|
5
5
|
const
|
|
6
|
-
getPerfTools = () => typeof performance !== 'undefined' && performance.mark && performance.measure ? performance : null,
|
|
7
6
|
runBoth = function (f1, f2) {
|
|
8
7
|
return function () {
|
|
9
8
|
f1.apply(this, arguments);
|
|
@@ -57,8 +56,6 @@ class Messenger {
|
|
|
57
56
|
|
|
58
57
|
// Debug logging.
|
|
59
58
|
if (debugLogging || this.debug) {
|
|
60
|
-
const perfTools = getPerfTools();
|
|
61
|
-
|
|
62
59
|
for (let i = 0; i < this.loopCheck.length; i++) {
|
|
63
60
|
if (this.loopCheck[i] === event) {
|
|
64
61
|
debugCount += 1;
|
|
@@ -72,17 +69,13 @@ class Messenger {
|
|
|
72
69
|
|
|
73
70
|
this.loopCheck.push(event);
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
perfTools.mark("a");
|
|
77
|
-
}
|
|
72
|
+
performance.mark("a");
|
|
78
73
|
|
|
79
74
|
const
|
|
80
75
|
count = triggerEvent.apply(this, arguments);
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
perfTools.measure(this.type + ":" + event, 'a', 'b');
|
|
85
|
-
}
|
|
77
|
+
performance.mark("b");
|
|
78
|
+
performance.measure(this.type + ":" + event, 'a', 'b');
|
|
86
79
|
this.loopCheck.length = this.loopCheck.length - 1;
|
|
87
80
|
if (debugLogging) {
|
|
88
81
|
if (count) {
|
|
@@ -341,7 +334,14 @@ class Messenger {
|
|
|
341
334
|
key = methods[i];
|
|
342
335
|
|
|
343
336
|
if (key !== 'constructor') {
|
|
344
|
-
|
|
337
|
+
const
|
|
338
|
+
descriptor = Object.getOwnPropertyDescriptor(fromProto, key);
|
|
339
|
+
|
|
340
|
+
// Preserve accessors (e.g. `destroyed`); assigning fromProto[key] would
|
|
341
|
+
// evaluate getters and copy a stale value instead.
|
|
342
|
+
if (descriptor.get || descriptor.set) {
|
|
343
|
+
Object.defineProperty(toProto, key, descriptor);
|
|
344
|
+
} else if (Object.prototype.hasOwnProperty.call(toProto, key) || toProto[key]) {
|
|
345
345
|
toProto[key] = runBoth(toProto[key], fromProto[key]);
|
|
346
346
|
} else {
|
|
347
347
|
toProto[key] = fromProto[key];
|
package/src/PIXIAnimation.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
82
|
+
const
|
|
83
|
+
cacheKey = getTextureCacheKey(path),
|
|
84
|
+
asset = resolveTextureAsset(path);
|
|
26
85
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
483
|
-
|
|
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(
|
|
628
|
+
match = name.match(imageBasename);
|
|
550
629
|
|
|
551
630
|
if (match) {
|
|
552
631
|
return match[1];
|
|
@@ -139,6 +139,10 @@ const
|
|
|
139
139
|
},
|
|
140
140
|
|
|
141
141
|
addNewPrivateEvent (event) {
|
|
142
|
+
if (this.destroyed || !this.entities || !this._childEvents) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
142
146
|
if (this._childEvents[event]) {
|
|
143
147
|
return false;
|
|
144
148
|
}
|
|
@@ -148,7 +152,17 @@ const
|
|
|
148
152
|
// Listen for message on children
|
|
149
153
|
for (let x = 0; x < this.entities.length; x++) {
|
|
150
154
|
const
|
|
151
|
-
|
|
155
|
+
entity = this.entities[x],
|
|
156
|
+
listeners = entity && entity._listeners;
|
|
157
|
+
|
|
158
|
+
// Child may already be destroyed while still listed (e.g. re-entrant
|
|
159
|
+
// input during container teardown).
|
|
160
|
+
if (!listeners) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const
|
|
165
|
+
listenerList = listeners[event];
|
|
152
166
|
|
|
153
167
|
if (listenerList) {
|
|
154
168
|
const
|
|
@@ -156,7 +170,7 @@ const
|
|
|
156
170
|
|
|
157
171
|
for (let y = 0; y < handlers.length; y++) {
|
|
158
172
|
this.addChildEventListener(
|
|
159
|
-
|
|
173
|
+
entity,
|
|
160
174
|
event,
|
|
161
175
|
handlers[y]
|
|
162
176
|
);
|
|
@@ -174,7 +188,13 @@ const
|
|
|
174
188
|
|
|
175
189
|
addChildEventListeners (entity) {
|
|
176
190
|
const
|
|
177
|
-
{_listeners} = entity
|
|
191
|
+
{_listeners} = entity;
|
|
192
|
+
|
|
193
|
+
if (!_listeners) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const
|
|
178
198
|
keys = Object.keys(_listeners),
|
|
179
199
|
{length} = keys;
|
|
180
200
|
|
|
@@ -268,10 +288,14 @@ const
|
|
|
268
288
|
},
|
|
269
289
|
|
|
270
290
|
destroy: function () {
|
|
291
|
+
// Mark destroyed first so re-entrant input (e.g. Enter:down) cannot
|
|
292
|
+
// walk children mid-teardown after their `_listeners` are nulled.
|
|
293
|
+
this._destroyed = true;
|
|
294
|
+
|
|
271
295
|
const
|
|
272
|
-
entities = greenSlice(this.entities); // Make a copy to handle entities being destroyed while processing list.
|
|
296
|
+
entities = this.entities ? greenSlice(this.entities) : arrayCache.setUp(); // Make a copy to handle entities being destroyed while processing list.
|
|
273
297
|
let i = entities.length;
|
|
274
|
-
|
|
298
|
+
|
|
275
299
|
while (i--) {
|
|
276
300
|
const
|
|
277
301
|
entity = entities[i];
|
|
@@ -279,14 +303,22 @@ const
|
|
|
279
303
|
this.removeChildEventListeners(entity);
|
|
280
304
|
entity.destroy();
|
|
281
305
|
}
|
|
282
|
-
|
|
306
|
+
|
|
283
307
|
arrayCache.recycle(entities);
|
|
284
|
-
|
|
308
|
+
if (this.entities) {
|
|
309
|
+
arrayCache.recycle(this.entities);
|
|
310
|
+
this.entities = null;
|
|
311
|
+
}
|
|
285
312
|
this.owner.entities = null;
|
|
286
|
-
|
|
287
|
-
this.childEvents
|
|
288
|
-
|
|
289
|
-
|
|
313
|
+
this._childEvents = null;
|
|
314
|
+
if (this.childEvents) {
|
|
315
|
+
arrayCache.recycle(this.childEvents);
|
|
316
|
+
this.childEvents = null;
|
|
317
|
+
}
|
|
318
|
+
if (this.newAdds) {
|
|
319
|
+
arrayCache.recycle(this.newAdds);
|
|
320
|
+
this.newAdds = null;
|
|
321
|
+
}
|
|
290
322
|
}
|
|
291
323
|
},
|
|
292
324
|
|
|
@@ -485,7 +517,7 @@ const
|
|
|
485
517
|
* @param {*} debug
|
|
486
518
|
*/
|
|
487
519
|
triggerEventOnChildren: function (event, message, debug) {
|
|
488
|
-
if (this.destroyed) {
|
|
520
|
+
if (this.destroyed || !this.entities || !this._childEvents) {
|
|
489
521
|
return 0;
|
|
490
522
|
}
|
|
491
523
|
|
|
@@ -504,7 +536,7 @@ const
|
|
|
504
536
|
* @param {*} debug
|
|
505
537
|
*/
|
|
506
538
|
triggerOnChildren: function (event) {
|
|
507
|
-
if (this.destroyed) {
|
|
539
|
+
if (this.destroyed || !this.entities || !this._childEvents) {
|
|
508
540
|
return 0;
|
|
509
541
|
}
|
|
510
542
|
|