@makefully/platypus 4.1.5 → 4.1.8
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 +31 -0
- package/README.md +3 -3
- package/lib/platypus.js +1 -1
- package/package.json +7 -6
- package/src/AABB.js +685 -0
- package/src/ActionState.js +121 -0
- package/src/AssetManager.js +206 -0
- package/src/CollisionData.js +96 -0
- package/src/CollisionDataContainer.js +127 -0
- package/src/CollisionShape.js +315 -0
- package/src/Component.js +231 -0
- package/src/Data.js +64 -0
- package/src/DataMap.js +204 -0
- package/src/Entity.js +404 -0
- package/src/EntityLinker.js +113 -0
- package/src/EventHandler.js +115 -0
- package/src/EventHandlerList.js +251 -0
- package/src/Game.js +840 -0
- package/src/Gamepad.js +175 -0
- package/src/ID3CaptionPlayer.js +61 -0
- package/src/Messenger.js +365 -0
- package/src/PIXIAnimation.js +622 -0
- package/src/RandomSet.js +140 -0
- package/src/SFXPlayer.js +120 -0
- package/src/StateMap.js +252 -0
- package/src/Storage.js +152 -0
- package/src/TickerClient.js +48 -0
- package/src/TickerServer.js +23 -0
- package/src/TimeEvent.js +50 -0
- package/src/TimeEventList.js +100 -0
- package/src/VOPlayer.js +684 -0
- package/src/Vector.js +702 -0
- package/src/components/AIChaser.js +161 -0
- package/src/components/AIPacer.js +107 -0
- package/src/components/AudioMusic.js +151 -0
- package/src/components/AudioSFX.js +673 -0
- package/src/components/AudioVO.js +301 -0
- package/src/components/CollisionBasic.js +826 -0
- package/src/components/CollisionFilter.js +74 -0
- package/src/components/CollisionGroup.js +448 -0
- package/src/components/CollisionTiles.js +608 -0
- package/src/components/ComponentSwitcher.js +173 -0
- package/src/components/ControllerInput.js +65 -0
- package/src/components/Counter.js +165 -0
- package/src/components/EntityCamera.js +215 -0
- package/src/components/EntityContainer.js +549 -0
- package/src/components/EntityController.js +541 -0
- package/src/components/HandlerCamera.js +1052 -0
- package/src/components/HandlerCollision.js +1318 -0
- package/src/components/HandlerController.js +291 -0
- package/src/components/HandlerLogic.js +394 -0
- package/src/components/HandlerRender.js +217 -0
- package/src/components/Interactive.js +502 -0
- package/src/components/LevelBuilder.js +524 -0
- package/src/components/LogicAngularMovement.js +154 -0
- package/src/components/LogicAttachment.js +265 -0
- package/src/components/LogicButton.js +466 -0
- package/src/components/LogicCarrier.js +39 -0
- package/src/components/LogicDestroyMe.js +58 -0
- package/src/components/LogicDirectionalMovement.js +325 -0
- package/src/components/LogicDragDrop.js +371 -0
- package/src/components/LogicImpactLaunch.js +144 -0
- package/src/components/LogicPacingPlatform.js +64 -0
- package/src/components/LogicPortable.js +112 -0
- package/src/components/LogicPortal.js +115 -0
- package/src/components/LogicPushable.js +98 -0
- package/src/components/LogicRebounder.js +136 -0
- package/src/components/LogicRegionSpawner.js +139 -0
- package/src/components/LogicRotationalMovement.js +205 -0
- package/src/components/LogicSpawner.js +159 -0
- package/src/components/LogicStateMachine.js +382 -0
- package/src/components/LogicSwitch.js +77 -0
- package/src/components/LogicTeleportee.js +68 -0
- package/src/components/LogicTeleporter.js +93 -0
- package/src/components/LogicTimer.js +178 -0
- package/src/components/LogicWindUpRacer.js +179 -0
- package/src/components/Motion.js +371 -0
- package/src/components/Mover.js +566 -0
- package/src/components/Node.js +289 -0
- package/src/components/NodeMap.js +295 -0
- package/src/components/NodeResident.js +636 -0
- package/src/components/Orientation.js +697 -0
- package/src/components/RandomEvents.js +73 -0
- package/src/components/RelativePosition.js +204 -0
- package/src/components/RelayFamily.js +106 -0
- package/src/components/RelayGame.js +53 -0
- package/src/components/RelayLinker.js +94 -0
- package/src/components/RelayParent.js +57 -0
- package/src/components/RelaySelf.js +55 -0
- package/src/components/Render.js +178 -0
- package/src/components/RenderAnimator.js +275 -0
- package/src/components/RenderContainer.js +646 -0
- package/src/components/RenderDebug.js +319 -0
- package/src/components/RenderDestroyMe.js +59 -0
- package/src/components/RenderLottie.js +149 -0
- package/src/components/RenderProgress.js +120 -0
- package/src/components/RenderSpine.js +840 -0
- package/src/components/RenderSprite.js +527 -0
- package/src/components/RenderText.js +147 -0
- package/src/components/RenderTiles.js +1440 -0
- package/src/components/SceneChanger.js +128 -0
- package/src/components/TiledLoader.js +1459 -0
- package/src/components/Timeline.js +314 -0
- package/src/components/Tutorial.js +267 -0
- package/src/components/Tween.js +296 -0
- package/src/components/VoiceOver.js +373 -0
- package/src/components/XHR.js +129 -0
- package/src/components/index.js +79 -0
- package/src/factory.js +305 -0
- package/src/index.js +159 -0
- package/src/mixins/PIXI.Graphics.js +41 -0
- package/src/platypus.css +68 -0
- package/src/sayHello.js +50 -0
- package/src/shapes/Capsule.js +74 -0
- package/src/shapes/Circle.js +43 -0
- package/src/shapes/Ellipse.js +117 -0
- package/src/shapes/Point.js +191 -0
- package/src/shapes/Polygon.js +112 -0
- package/src/shapes/Polyline.js +97 -0
- package/src/shapes/Rectangle.js +78 -0
- package/src/shapes/RoundedRectangle.js +33 -0
- package/src/shapes/Segment.js +346 -0
- package/src/shapes/adjustedXY.js +19 -0
- package/src/shapes/castFromBox2D.js +92 -0
- package/src/shapes/castFromObject.js +53 -0
- package/src/shapes/castFromPixiGraphics.js +6 -0
- package/src/shapes/castFromPixiShape.js +89 -0
- package/src/shapes/castToBox2D.js +190 -0
- package/src/shapes/castToPixiGraphics.js +100 -0
- package/src/shapes/castToPixiShape.js +61 -0
- package/src/shapes/checkPointsMap.js +313 -0
- package/src/shapes/index.js +35 -0
- package/src/utils/array.js +73 -0
- package/src/utils/string.js +39 -0
- package/lib/243.platypus.mjs +0 -1
- package/lib/platypus.mjs +0 -1
package/src/DataMap.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/* global Map */
|
|
2
|
+
import {arrayCache, greenSplice} from './utils/array.js';
|
|
3
|
+
import recycle from 'recycle';
|
|
4
|
+
|
|
5
|
+
const
|
|
6
|
+
mapSet = function (keys, key, value) {
|
|
7
|
+
if (this.get(key) !== value) {
|
|
8
|
+
if (!this.has(key)) {
|
|
9
|
+
keys.push(key);
|
|
10
|
+
}
|
|
11
|
+
this.set(key, value);
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
},
|
|
15
|
+
mapDelete = function (keys, key) {
|
|
16
|
+
const
|
|
17
|
+
i = keys.indexOf(key),
|
|
18
|
+
value = this.get(key);
|
|
19
|
+
|
|
20
|
+
if (i >= 0) {
|
|
21
|
+
greenSplice(keys, i);
|
|
22
|
+
this.delete(key);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return value;
|
|
26
|
+
},
|
|
27
|
+
mapClear = function (keys) {
|
|
28
|
+
let i = keys.length;
|
|
29
|
+
|
|
30
|
+
while (i--) {
|
|
31
|
+
this.delete(keys[i]);
|
|
32
|
+
}
|
|
33
|
+
keys.length = 0;
|
|
34
|
+
},
|
|
35
|
+
mapToJSON = function (keys) {
|
|
36
|
+
const
|
|
37
|
+
json = {};
|
|
38
|
+
let i = keys.length;
|
|
39
|
+
|
|
40
|
+
while (i--) {
|
|
41
|
+
const
|
|
42
|
+
key = keys[i];
|
|
43
|
+
|
|
44
|
+
json[key] = this.get(key);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return json;
|
|
48
|
+
},
|
|
49
|
+
mapMethods = {
|
|
50
|
+
get: {
|
|
51
|
+
value: null
|
|
52
|
+
},
|
|
53
|
+
has: {
|
|
54
|
+
value: null
|
|
55
|
+
},
|
|
56
|
+
keys: {
|
|
57
|
+
value: null
|
|
58
|
+
},
|
|
59
|
+
set: {
|
|
60
|
+
value: null
|
|
61
|
+
},
|
|
62
|
+
delete: {
|
|
63
|
+
value: null
|
|
64
|
+
},
|
|
65
|
+
clear: {
|
|
66
|
+
value: null
|
|
67
|
+
},
|
|
68
|
+
toJSON: {
|
|
69
|
+
value: null
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* This class defines a generic iterable data object. It behaves similarly to Map but maintains a list of keys as an Array. It includes recycle methods to encourage reuse.
|
|
75
|
+
*
|
|
76
|
+
* @memberof platypus
|
|
77
|
+
* @class DataMap
|
|
78
|
+
* @uses Map
|
|
79
|
+
* @return {platypus.DataMap} Returns the new DataMap object.
|
|
80
|
+
*/
|
|
81
|
+
DataMap = function (first) {
|
|
82
|
+
if (!this.map) {
|
|
83
|
+
const
|
|
84
|
+
mm = mapMethods,
|
|
85
|
+
map = this.map = new Map(),
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Tracks keys on this object to make iteration faster.
|
|
89
|
+
*
|
|
90
|
+
* @property keys
|
|
91
|
+
* @type Array
|
|
92
|
+
* @default []
|
|
93
|
+
*/
|
|
94
|
+
keys = mm.keys.value = arrayCache.setUp();
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Returns the value of the provided key.
|
|
98
|
+
*
|
|
99
|
+
* @method platypus.DataMap#get
|
|
100
|
+
* @param key {String} The key to lookup.
|
|
101
|
+
* @return value {any} The value of the provded key.
|
|
102
|
+
*/
|
|
103
|
+
mm.get.value = map.get.bind(map);
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Determines whether the provided key is available on this DataMap.
|
|
107
|
+
*
|
|
108
|
+
* @method platypus.DataMap#has
|
|
109
|
+
* @param key {String} The key to lookup.
|
|
110
|
+
* @return value {Boolean} Whether the key is listed in this DataMap.
|
|
111
|
+
*/
|
|
112
|
+
mm.has.value = map.has.bind(map);
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sets a value to a key in the DataMap.
|
|
116
|
+
*
|
|
117
|
+
* @method platypus.DataMap#set
|
|
118
|
+
* @param key {String} The key to associate with the provided value.
|
|
119
|
+
* @param value {any} The value to be stored by the DataMap.
|
|
120
|
+
* @return value {any} The value passed in is returned for chaining.
|
|
121
|
+
*/
|
|
122
|
+
mm.set.value = mapSet.bind(map, keys);
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Deletes a key (and value) from the DataMap.
|
|
126
|
+
*
|
|
127
|
+
* @method platypus.DataMap#delete
|
|
128
|
+
* @param key {String} The key to delete from the DataMap.
|
|
129
|
+
* @return value {any} The value of the key is returned.
|
|
130
|
+
*/
|
|
131
|
+
mm.delete.value = mapDelete.bind(map, keys);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Clears out of keys (and values) from the DataMap.
|
|
135
|
+
*
|
|
136
|
+
* @method platypus.DataMap#clear
|
|
137
|
+
*/
|
|
138
|
+
mm.clear.value = mapClear.bind(map, keys);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Returns a JSON object describing the component.
|
|
142
|
+
*
|
|
143
|
+
* @method platypus.DataMap#toJSON
|
|
144
|
+
* @return {Object} Returns a JSON definition that can be used to recreate the component.
|
|
145
|
+
**/
|
|
146
|
+
mm.toJSON.value = mapToJSON.bind(map, keys);
|
|
147
|
+
|
|
148
|
+
Object.defineProperties(this, mm);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (first) {
|
|
152
|
+
if (typeof first === 'string') {
|
|
153
|
+
let i = arguments.length;
|
|
154
|
+
|
|
155
|
+
if (i % 2) {
|
|
156
|
+
i -= 1;
|
|
157
|
+
this.set(arguments[i], null);
|
|
158
|
+
}
|
|
159
|
+
while (i) {
|
|
160
|
+
i -= 2;
|
|
161
|
+
this.set(arguments[i], arguments[i + 1]);
|
|
162
|
+
}
|
|
163
|
+
} else if (first.keys) {
|
|
164
|
+
const
|
|
165
|
+
keys = first.keys;
|
|
166
|
+
let i = keys.length;
|
|
167
|
+
|
|
168
|
+
while (i--) {
|
|
169
|
+
this.set(keys[i], first.get(keys[i]));
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
const
|
|
173
|
+
keys = Object.keys(first);
|
|
174
|
+
let i = keys.length;
|
|
175
|
+
|
|
176
|
+
while (i--) {
|
|
177
|
+
this.set(keys[i], first[keys[i]]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Returns DataMap from cache or creates a new one if none are available.
|
|
185
|
+
*
|
|
186
|
+
* @method platypus.DataMap.setUp
|
|
187
|
+
* @return dataMap {platypus.DataMap} The instantiated DataMap.
|
|
188
|
+
*/
|
|
189
|
+
/**
|
|
190
|
+
* Returns DataMap back to the cache. Prefer the DataMap's recycle method since it recycles property objects as well.
|
|
191
|
+
*
|
|
192
|
+
* @method platypus.DataMap.recycle
|
|
193
|
+
* @param dataMap {platypus.DataMap} The DataMap to be recycled.
|
|
194
|
+
*/
|
|
195
|
+
/**
|
|
196
|
+
* Relinquishes DataMap properties and recycles it.
|
|
197
|
+
*
|
|
198
|
+
* @method platypus.DataMap#recycle
|
|
199
|
+
*/
|
|
200
|
+
recycle.add(DataMap, 'DataMap', DataMap, function () {
|
|
201
|
+
this.clear();
|
|
202
|
+
}, true);
|
|
203
|
+
|
|
204
|
+
export default DataMap;
|
package/src/Entity.js
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/* global platypus */
|
|
2
|
+
import {arrayCache, greenSplice} from './utils/array.js';
|
|
3
|
+
import Messenger from './Messenger.js';
|
|
4
|
+
import StateMap from './StateMap.js';
|
|
5
|
+
import createComponentClass from './factory.js';
|
|
6
|
+
|
|
7
|
+
const
|
|
8
|
+
entityIds = {},
|
|
9
|
+
getComponentClass = function (componentDefinition) {
|
|
10
|
+
const
|
|
11
|
+
{type} = componentDefinition;
|
|
12
|
+
|
|
13
|
+
if (type) {
|
|
14
|
+
if (typeof type === 'function') {
|
|
15
|
+
return type;
|
|
16
|
+
} else if (platypus.components[type]) {
|
|
17
|
+
return platypus.components[type];
|
|
18
|
+
}
|
|
19
|
+
} else if (componentDefinition.id) { // "type" not specified, so we create the component directly.
|
|
20
|
+
return createComponentClass(componentDefinition);
|
|
21
|
+
} else if (typeof componentDefinition === 'function') {
|
|
22
|
+
return componentDefinition;
|
|
23
|
+
} else {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The Entity object acts as a container for components, facilitates communication between components and other game objects, and includes properties set by components to maintain a current state. The entity object serves as the foundation for most of the game objects in the platypus engine.
|
|
30
|
+
*
|
|
31
|
+
* ## JSON Definition Example
|
|
32
|
+
{
|
|
33
|
+
"id": "entity-id",
|
|
34
|
+
// "entity-id" becomes `entity.type` once the entity is created.
|
|
35
|
+
|
|
36
|
+
"components": [
|
|
37
|
+
// This array lists one or more component definition objects
|
|
38
|
+
|
|
39
|
+
{"type": "example-component"}
|
|
40
|
+
// The component objects must include a "type" property corresponding to a component to load, but may also include additional properties to customize the component in a particular way for this entity.
|
|
41
|
+
],
|
|
42
|
+
|
|
43
|
+
"properties": {
|
|
44
|
+
// This object lists properties that will be attached directly to this entity.
|
|
45
|
+
|
|
46
|
+
"x": 240
|
|
47
|
+
// For example, `x` becomes `entity.x` on the new entity.
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
"preload": ['image.png', 'sound.mp3']
|
|
51
|
+
// assets that need to be loaded before this entity loads
|
|
52
|
+
}
|
|
53
|
+
*
|
|
54
|
+
* @memberof platypus
|
|
55
|
+
* @extends platypus.Messenger
|
|
56
|
+
**/
|
|
57
|
+
export default class Entity extends Messenger {
|
|
58
|
+
/**
|
|
59
|
+
* @param {Object} [definition] Base definition for the entity.
|
|
60
|
+
* @param {Object} [definition.components] This lists the components that should be attached to this entity.
|
|
61
|
+
* @param {Object} [definition.id] This declares the type of entity and will be stored on the Entity as `entity.type` after instantiation.
|
|
62
|
+
* @param {Object} [definition.properties] [definition.properties] This is a list of key/value pairs that are added directly to the Entity as `entity.key = value`.
|
|
63
|
+
* @param {Object} [instanceDefinition] Specific instance definition including properties that override the base definition properties.
|
|
64
|
+
* @param {Object} [instanceDefinition.properties] This is a list of key/value pairs that are added directly to the Entity as `entity.key = value`.
|
|
65
|
+
* @param {Function} [callback] A function to run once all of the components on the Entity have been loaded. The first parameter is the entity itself.
|
|
66
|
+
* @param {Entity} [parent] Presets the parent of the entity so that the parent entity is available during component instantiation. Overrides `parent` in properties definitions.
|
|
67
|
+
* @return {Entity} Returns the new entity made up of the provided components.
|
|
68
|
+
* @fires platypus.Entity#load
|
|
69
|
+
*/
|
|
70
|
+
constructor ({
|
|
71
|
+
components: componentDefinitions,
|
|
72
|
+
properties: defaultProperties = {},
|
|
73
|
+
id: type
|
|
74
|
+
}, {
|
|
75
|
+
id,
|
|
76
|
+
properties: instanceProperties = {}
|
|
77
|
+
} = {}, callback, parent) {
|
|
78
|
+
// Set properties of messenger on this entity.
|
|
79
|
+
super();
|
|
80
|
+
|
|
81
|
+
const
|
|
82
|
+
componentInit = (Component, componentDefinition) => new Promise((resolve) => this.addComponent(new Component(this, componentDefinition, resolve))),
|
|
83
|
+
componentInits = arrayCache.setUp(),
|
|
84
|
+
savedEvents = arrayCache.setUp(),
|
|
85
|
+
trigger = this.trigger; // trigger reference for saved events
|
|
86
|
+
|
|
87
|
+
this.components = arrayCache.setUp();
|
|
88
|
+
this.type = type || 'none';
|
|
89
|
+
|
|
90
|
+
this.id = id ?? instanceProperties.id;
|
|
91
|
+
if (this.id) { // check to make sure auto-ids don't overlap.
|
|
92
|
+
if (this.id.search(this.type + '-') === 0) {
|
|
93
|
+
const
|
|
94
|
+
i = parseInt(this.id.substring(this.id.search('-') + 1), 10);
|
|
95
|
+
|
|
96
|
+
if (!isNaN(i) && (!entityIds[this.type] || (entityIds[this.type] <= i))) {
|
|
97
|
+
entityIds[this.type] = i + 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
if (!entityIds[this.type]) {
|
|
102
|
+
entityIds[this.type] = 0;
|
|
103
|
+
}
|
|
104
|
+
this.id = this.type + '-' + entityIds[this.type];
|
|
105
|
+
entityIds[this.type] += 1;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.setProperty(defaultProperties); // This takes the list of properties in the JSON definition and appends them directly to the object.
|
|
109
|
+
this.setProperty(instanceProperties); // This takes the list of options for this particular instance and appends them directly to the object.
|
|
110
|
+
this.on('set-property', (keyValuePairs) => {
|
|
111
|
+
this.setProperty(keyValuePairs);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
this.state = StateMap.setUp(this.state); //starts with no state information. This expands with boolean value properties entered by various logic components.
|
|
115
|
+
this.lastState = StateMap.setUp(); //This is used to determine if the state of the entity has changed.
|
|
116
|
+
|
|
117
|
+
if (parent) {
|
|
118
|
+
this.parent = parent;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.trigger = this.triggerEvent = (...args) => {
|
|
122
|
+
savedEvents.push(trigger.bind(this, ...args));
|
|
123
|
+
|
|
124
|
+
return -1; // Message has not been delivered yet.
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if (componentDefinitions) {
|
|
128
|
+
for (let i = 0; i < componentDefinitions.length; i++) {
|
|
129
|
+
const
|
|
130
|
+
componentDefinition = componentDefinitions[i];
|
|
131
|
+
|
|
132
|
+
if (componentDefinition) {
|
|
133
|
+
if (componentDefinition.type) {
|
|
134
|
+
const
|
|
135
|
+
componentClass = getComponentClass(componentDefinition);
|
|
136
|
+
|
|
137
|
+
if (componentClass) {
|
|
138
|
+
componentInits.push(componentInit(componentClass, componentDefinition));
|
|
139
|
+
} else {
|
|
140
|
+
platypus.debug.warn('Entity "' + this.type + '": Component "' + componentDefinition.type + '" is not defined.', componentDefinition);
|
|
141
|
+
}
|
|
142
|
+
} else if (componentDefinition.id) { // "type" not specified, so we create the component directly.
|
|
143
|
+
componentInits.push(componentInit(createComponentClass(componentDefinition)));
|
|
144
|
+
} else if (typeof componentDefinition === 'function') {
|
|
145
|
+
componentInits.push(componentInit(componentDefinition));
|
|
146
|
+
} else {
|
|
147
|
+
platypus.debug.warn('Entity "' + this.type + '": Component must have an `id` or `type` value.', componentDefinition);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
this.loadingComponents = Promise.all(componentInits).then(() => {
|
|
153
|
+
this.loadingComponents = null;
|
|
154
|
+
|
|
155
|
+
// Trigger saved events that were being fired during component addition.
|
|
156
|
+
delete this.trigger;
|
|
157
|
+
delete this.triggerEvent;
|
|
158
|
+
for (let i = 0; i < savedEvents.length; i++) {
|
|
159
|
+
savedEvents[i]();
|
|
160
|
+
}
|
|
161
|
+
arrayCache.recycle(savedEvents);
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The entity triggers `load` on itself once all the properties and components have been attached, notifying the components that all their peer components are ready for messages.
|
|
165
|
+
*
|
|
166
|
+
* @event platypus.Entity#load
|
|
167
|
+
*/
|
|
168
|
+
this.triggerEvent('load');
|
|
169
|
+
|
|
170
|
+
if (callback) {
|
|
171
|
+
callback(this);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
arrayCache.recycle(componentInits);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Returns a string describing the entity.
|
|
180
|
+
*
|
|
181
|
+
* @return {String} Returns the entity type as a string of the form "[Entity entity-type]".
|
|
182
|
+
**/
|
|
183
|
+
toString () {
|
|
184
|
+
return "[Entity " + this.type + "]";
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Returns a JSON object describing the entity.
|
|
189
|
+
*
|
|
190
|
+
* @param includeComponents {Boolean} Whether the returned JSON should list components. Defaults to `false` to condense output since components are generally defined in `platypus.game.settings.entities`, but may be needed for custom-constructed entities not so defined.
|
|
191
|
+
* @return {Object} Returns a JSON definition that can be used to recreate the entity.
|
|
192
|
+
**/
|
|
193
|
+
toJSON (includeComponents) {
|
|
194
|
+
const
|
|
195
|
+
{components, type} = this,
|
|
196
|
+
properties = {
|
|
197
|
+
id: this.id,
|
|
198
|
+
state: this.state.toJSON()
|
|
199
|
+
},
|
|
200
|
+
definition = {
|
|
201
|
+
properties
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
if (includeComponents) {
|
|
205
|
+
definition.id = type;
|
|
206
|
+
definition.components = [];
|
|
207
|
+
} else {
|
|
208
|
+
definition.type = type;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
for (let i = 0; i < components.length; i++) {
|
|
212
|
+
const
|
|
213
|
+
json = components[i].toJSON(properties);
|
|
214
|
+
|
|
215
|
+
if (includeComponents && json) {
|
|
216
|
+
definition.components.push(json);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return definition;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Attaches the provided component to the entity.
|
|
225
|
+
*
|
|
226
|
+
* @param {platypus.Component} component Must be an object that functions as a Component.
|
|
227
|
+
* @return {platypus.Component} Returns the same object that was submitted.
|
|
228
|
+
* @fires platypus.Entity#component-added
|
|
229
|
+
**/
|
|
230
|
+
addComponent (component) {
|
|
231
|
+
this.components.push(component);
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The entity triggers `component-added` on itself once a component has been attached, notifying other components of their peer component.
|
|
235
|
+
*
|
|
236
|
+
* @event platypus.Entity#component-added
|
|
237
|
+
* @param {platypus.Component} component The added component.
|
|
238
|
+
* @param {String} component.type The type of component.
|
|
239
|
+
**/
|
|
240
|
+
this.triggerEvent('component-added', component);
|
|
241
|
+
return component;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Removes the mentioned component from the entity.
|
|
246
|
+
*
|
|
247
|
+
* @param {Component} component Must be a [[Component]] attached to the entity.
|
|
248
|
+
* @return {Component} Returns the same object that was submitted if removal was successful; otherwise returns false (the component was not found attached to the entity).
|
|
249
|
+
* @fires platypus.Entity#component-removed
|
|
250
|
+
**/
|
|
251
|
+
removeComponent (component) {
|
|
252
|
+
/**
|
|
253
|
+
* The entity triggers `component-removed` on itself once a component has been removed, notifying other components of their peer component's removal.
|
|
254
|
+
*
|
|
255
|
+
* @event platypus.Entity#component-removed
|
|
256
|
+
* @param {Component} component The removed component.
|
|
257
|
+
* @param {String} component.type The type of component.
|
|
258
|
+
**/
|
|
259
|
+
if (typeof component === 'string') {
|
|
260
|
+
for (let i = 0; i < this.components.length; i++) {
|
|
261
|
+
if (this.components[i].type === component) {
|
|
262
|
+
component = this.components[i];
|
|
263
|
+
greenSplice(this.components, i);
|
|
264
|
+
this.triggerEvent('component-removed', component);
|
|
265
|
+
component.destroy();
|
|
266
|
+
return component;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
for (let i = 0; i < this.components.length; i++) {
|
|
271
|
+
if (this.components[i] === component) {
|
|
272
|
+
greenSplice(this.components, i);
|
|
273
|
+
this.triggerEvent('component-removed', component);
|
|
274
|
+
component.destroy();
|
|
275
|
+
return component;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* This method gets a component by its id.
|
|
285
|
+
*
|
|
286
|
+
* @param {String} componentId
|
|
287
|
+
* @returns {Component} A component
|
|
288
|
+
*/
|
|
289
|
+
getComponentById (componentId) {
|
|
290
|
+
return this.components.filter(({id}) => id === componentId)[0] ?? null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* This method gets all components by their type.
|
|
295
|
+
*
|
|
296
|
+
* @param {String} componentType
|
|
297
|
+
* @returns {Array} An array of components
|
|
298
|
+
*/
|
|
299
|
+
getComponentsByType (componentType) {
|
|
300
|
+
return this.components.filter(({type}) => type === componentType);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Allows lookup for components or child entities and their properties.
|
|
305
|
+
*
|
|
306
|
+
* For example, "component-id.sprite" will return an entity component's sprite property value.
|
|
307
|
+
*
|
|
308
|
+
* @param {String} path
|
|
309
|
+
* @returns {*}
|
|
310
|
+
*/
|
|
311
|
+
get (path) {
|
|
312
|
+
const
|
|
313
|
+
tree = path.split('.');
|
|
314
|
+
let obj = this;
|
|
315
|
+
|
|
316
|
+
while (tree.length) {
|
|
317
|
+
let param = tree.shift();
|
|
318
|
+
|
|
319
|
+
obj = obj[param] ?? obj.getComponentById?.(param) ?? obj.getEntityById?.(param);
|
|
320
|
+
|
|
321
|
+
if (!obj) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return obj;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* This method sets one or more properties on the entity.
|
|
331
|
+
*
|
|
332
|
+
* @param {Object} properties A list of key/value pairs to set as properties on the entity.
|
|
333
|
+
**/
|
|
334
|
+
setProperty (properties) {
|
|
335
|
+
const
|
|
336
|
+
keys = Object.keys(properties);
|
|
337
|
+
|
|
338
|
+
// This takes a list of properties and appends them directly to the object.
|
|
339
|
+
for (let i = 0; i < keys.length; i++) {
|
|
340
|
+
const
|
|
341
|
+
key = keys[i];
|
|
342
|
+
|
|
343
|
+
this[key] = properties[key];
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* This method removes all components from the entity.
|
|
349
|
+
*
|
|
350
|
+
**/
|
|
351
|
+
destroy () {
|
|
352
|
+
const
|
|
353
|
+
components = this.components;
|
|
354
|
+
|
|
355
|
+
if (!this._destroyed) {
|
|
356
|
+
while (components.length) {
|
|
357
|
+
components[0].destroy();
|
|
358
|
+
components.shift();
|
|
359
|
+
}
|
|
360
|
+
arrayCache.recycle(components);
|
|
361
|
+
this.components = null;
|
|
362
|
+
|
|
363
|
+
this.state.recycle();
|
|
364
|
+
this.state = null;
|
|
365
|
+
|
|
366
|
+
this.lastState.recycle();
|
|
367
|
+
this.lastState = null;
|
|
368
|
+
|
|
369
|
+
super.destroy();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Returns all of the assets required for this Entity. This method calls the corresponding method on all components to determine the list of assets.
|
|
375
|
+
*
|
|
376
|
+
* @param definition {Object} The definition for the Entity.
|
|
377
|
+
* @param properties {Object} Properties for this instance of the Entity.
|
|
378
|
+
* @param data {Object} Layer data that affects asset list.
|
|
379
|
+
* @return {Array} A list of the necessary assets to load.
|
|
380
|
+
*/
|
|
381
|
+
static getAssetList ({components = [], preload = [], properties = {}, type} = {}, props, data) {
|
|
382
|
+
if (type) {
|
|
383
|
+
const
|
|
384
|
+
definition = platypus.game.settings.entities[type];
|
|
385
|
+
|
|
386
|
+
if (!definition) {
|
|
387
|
+
platypus.debug.warn(`Entity "${type}": This entity is not defined.`);
|
|
388
|
+
return arrayCache.setUp();
|
|
389
|
+
}
|
|
390
|
+
return Entity.getAssetList({
|
|
391
|
+
...definition,
|
|
392
|
+
preload: [
|
|
393
|
+
...preload,
|
|
394
|
+
...definition.preload ?? []
|
|
395
|
+
]
|
|
396
|
+
}, properties, data);
|
|
397
|
+
} else {
|
|
398
|
+
return [...new Set([
|
|
399
|
+
...preload,
|
|
400
|
+
...components.map((component) => getComponentClass(component)?.getAssetList(component, properties, props, data) ?? []).flat()
|
|
401
|
+
])];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|