@makefully/platypus 4.1.11 → 4.1.14

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.11",
3
+ "version": "4.1.14",
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.7",
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/Messenger.js CHANGED
@@ -1,9 +1,8 @@
1
- /* global platypus, window */
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
- if (perfTools) {
76
- perfTools.mark("a");
77
- }
72
+ performance.mark("a");
78
73
 
79
74
  const
80
75
  count = triggerEvent.apply(this, arguments);
81
76
 
82
- if (perfTools) {
83
- perfTools.mark("b");
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
- if (toProto[key]) {
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];
@@ -339,6 +339,9 @@ const
339
339
  */
340
340
  stop () {
341
341
  this.paused = true;
342
+ if (this._animation?.stop) {
343
+ this._animation.stop();
344
+ }
342
345
  };
343
346
 
344
347
  /**
@@ -348,6 +351,9 @@ const
348
351
  */
349
352
  play () {
350
353
  this.paused = false;
354
+ if (this._animation?.play) {
355
+ this._animation.play();
356
+ }
351
357
  };
352
358
 
353
359
  /**
@@ -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
- listenerList = this.entities[x]._listeners[event];
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
- this.entities[x],
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
- arrayCache.recycle(this.entities);
308
+ if (this.entities) {
309
+ arrayCache.recycle(this.entities);
310
+ this.entities = null;
311
+ }
285
312
  this.owner.entities = null;
286
- arrayCache.recycle(this.childEvents);
287
- this.childEvents = null;
288
- arrayCache.recycle(this.newAdds);
289
- this.newAdds = null;
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
 
@@ -379,14 +379,6 @@ export default createComponentClass(/** @lends platypus.components.RenderSpine.p
379
379
  spine = this.spine = new Spine({skeletonData, autoUpdate: false}),
380
380
  map = createAnimationMap(this.animationMap, skeleton.animations);
381
381
 
382
- // Spine 4.3 inherits Pixi container world-transform deltas into skeleton physics by default.
383
- // Platypus pans the camera by moving the world container, which shifts every entity's world
384
- // transform even when owner.x/y are unchanged — causing unwanted physics on stationary characters.
385
- // Use the `apply-spine-physics` event for intentional movement-driven physics instead.
386
- spine.setPhysicsPositionInheritanceFactor(0, 0);
387
- spine.physicsRotationInheritanceFactor = 0;
388
- spine.resetPhysicsTransform();
389
-
390
382
  let animation = '';
391
383
 
392
384
  spine.state.addListener({
@@ -430,15 +430,20 @@ export default createComponentClass(/** @lends platypus.components.RenderSprite.
430
430
  events: {
431
431
  "handle-render": function (renderData) {
432
432
  if (this.sprite) {
433
+ const
434
+ playing = !this.sprite.paused;
435
+
433
436
  /**
434
437
  * This event is triggered each tick to check for animation updates.
435
438
  *
436
439
  * @event platypus.Entity#update-animation
437
440
  * @param playing {Boolean} Whether the animation is in a playing or paused state.
438
441
  */
439
- this.owner.triggerEvent('update-animation', true);
442
+ this.owner.triggerEvent('update-animation', playing);
440
443
 
441
- this.sprite.update(renderData.delta);
444
+ if (playing) {
445
+ this.sprite.update(renderData.delta);
446
+ }
442
447
  }
443
448
  },
444
449
 
package/src/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * @namespace platypus
7
7
  */
8
- /* global global, navigator, window */
8
+ /* global global, navigator */
9
9
 
10
10
  import AssetManager from './AssetManager.js';
11
11
  import {Debugger} from 'springroll';
@@ -46,7 +46,6 @@ const
46
46
  components
47
47
  },
48
48
  uagent = navigator.userAgent.toLowerCase(),
49
- isEdge = (uagent.search('edge') > -1),
50
49
  isIPod = (uagent.search('ipod') > -1),
51
50
  isIPhone = (uagent.search('iphone') > -1),
52
51
  isIPad = (uagent.search('ipad') > -1) || (uagent.search('mac') > -1 && navigator.maxTouchPoints > 2 && !isIPhone),
@@ -109,20 +108,21 @@ const
109
108
 
110
109
  /**
111
110
  * This is an object of boolean key/value pairs describing the current browser's properties.
111
+ * Obsolete capability flags (`touch`, `edge`, `ie`) are fixed to match modern browser support.
112
112
  * @property supports
113
113
  * @type Object
114
114
  **/
115
115
  platypus.supports = {
116
- touch: (window.ontouchstart !== 'undefined'),
117
- edge: isEdge,
116
+ touch: true, // Touch Events are universally available in modern browsers
117
+ edge: false, // Legacy EdgeHTML is no longer supported
118
118
  iPod: isIPod,
119
119
  iPhone: isIPhone,
120
120
  iPad: isIPad,
121
- safari: (uagent.search('safari') > -1) && !isEdge,
122
- ie: (uagent.search('msie') > -1) || (uagent.search('trident') > -1),
121
+ safari: (uagent.search('safari') > -1),
122
+ ie: false, // Internet Explorer is no longer supported
123
123
  firefox: (uagent.search('firefox') > -1),
124
124
  android: isAndroid,
125
- chrome: (uagent.search('chrome') > -1) && !isEdge,
125
+ chrome: (uagent.search('chrome') > -1),
126
126
  silk: isSilk,
127
127
  iOS: isIOS,
128
128
  mobile: isMobile,
package/src/platypus.css CHANGED
@@ -1,8 +1,6 @@
1
1
  div#captions {
2
- user-select: none;
3
- -moz-user-select: none;
4
2
  -webkit-user-select: none;
5
- -ms-user-select: none;
3
+ user-select: none;
6
4
  -webkit-touch-callout: none;
7
5
  }
8
6
 
@@ -11,11 +9,10 @@ canvas.platypus-canvas {
11
9
  position: relative;
12
10
  width: 100%;
13
11
 
14
- user-select: none;
15
- -moz-user-select: none;
16
12
  -webkit-user-select: none;
17
- -ms-user-select: none;
13
+ user-select: none;
18
14
  -webkit-touch-callout: none;
15
+ touch-action: none;
19
16
  }
20
17
 
21
18
  .platypus-debugging {
@@ -28,6 +25,7 @@ canvas.platypus-canvas {
28
25
  z-index: 2;
29
26
  font-family: "Lucida Console", Monaco, monospace;
30
27
  -webkit-touch-callout: none;
28
+ -webkit-user-select: none;
31
29
  user-select: none;
32
30
  cursor: default;
33
31
  margin: 0;
package/src/sayHello.js CHANGED
@@ -30,7 +30,7 @@ export default function (app) {
30
30
  author = docAuth ? `by ${docAuth}` : '',
31
31
  title = `${options.name ?? app.name ?? document.title ?? ''}${version ? ` ${version}` : ''}`,
32
32
  using = arrayCache.setUp(),
33
- {springroll, supports} = platypus;
33
+ {springroll} = platypus;
34
34
 
35
35
  if (springroll) {
36
36
  using.push('SpringRoll ' + springroll.version);
@@ -38,13 +38,10 @@ export default function (app) {
38
38
 
39
39
  using.push('Pixi.js ' + pixiVersion);
40
40
 
41
- if (supports.firefox || supports.chrome) {
42
- console.log(`%c ${title} %c ${author}`, getStyle(title, title.substr(title.lastIndexOf(' ') - title.length + 1)), 'line-height: 1.5em;');
43
- using.push(`Platypus ${platypus.version}`);
44
- console.log(`Using %c ${using.join(' %c %c ')} %c `, ...getVersions(using));
45
- } else {
46
- console.log(`--- "${title}" ${author} - Using ${using.join(', ')}, and Platypus ${platypus.version} ---`);
47
- }
41
+ // Styled console (%c) is supported in all modern browsers.
42
+ console.log(`%c ${title} %c ${author}`, getStyle(title, title.substr(title.lastIndexOf(' ') - title.length + 1)), 'line-height: 1.5em;');
43
+ using.push(`Platypus ${platypus.version}`);
44
+ console.log(`Using %c ${using.join(' %c %c ')} %c `, ...getVersions(using));
48
45
 
49
46
  arrayCache.recycle(using);
50
47
  };