@makefully/platypus 4.1.4 → 4.1.6
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 +20 -0
- package/README.md +4 -2
- package/lib/platypus.js +1 -1
- package/package.json +7 -2
- 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 +833 -0
- package/src/components/RenderSprite.js +527 -0
- package/src/components/RenderText.js +147 -0
- package/src/components/RenderTiles.js +1391 -0
- package/src/components/SceneChanger.js +128 -0
- package/src/components/TiledLoader.js +1451 -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
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
import {arrayCache, greenSplice, union} from '../utils/array.js';
|
|
2
|
+
import AABB from '../AABB.js';
|
|
3
|
+
import CollisionData from '../CollisionData.js';
|
|
4
|
+
import CollisionDataContainer from '../CollisionDataContainer.js';
|
|
5
|
+
import Data from '../Data.js';
|
|
6
|
+
import DataMap from '../DataMap.js';
|
|
7
|
+
import Vector from '../Vector.js';
|
|
8
|
+
import createComponentClass from '../factory.js';
|
|
9
|
+
|
|
10
|
+
const
|
|
11
|
+
BIT_16 = 0xffff,
|
|
12
|
+
combine = function (x, y) {
|
|
13
|
+
return (x << 16) | (y & BIT_16);
|
|
14
|
+
},
|
|
15
|
+
getBucketId = function (x, y, bits) {
|
|
16
|
+
return combine(x >> bits, y >> bits);
|
|
17
|
+
},
|
|
18
|
+
triggerMessage = {
|
|
19
|
+
entity: null,
|
|
20
|
+
target: null,
|
|
21
|
+
type: null,
|
|
22
|
+
x: 0,
|
|
23
|
+
y: 0,
|
|
24
|
+
hitType: null,
|
|
25
|
+
myType: null
|
|
26
|
+
},
|
|
27
|
+
groupSortBySize = function (a, b) {
|
|
28
|
+
return a.collisionGroup.getAllEntities() - b.collisionGroup.getAllEntities();
|
|
29
|
+
},
|
|
30
|
+
epsilon = 0.000001;
|
|
31
|
+
|
|
32
|
+
export default createComponentClass(/** @lends platypus.components.HandlerCollision.prototype */{
|
|
33
|
+
id: 'HandlerCollision',
|
|
34
|
+
|
|
35
|
+
properties: {
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
gridBits: 8
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* This component checks for collisions between entities which typically have either a [CollisionTiles](platypus.components.CollisionTiles.html) component for tile maps or a [CollisionBasic](platypus.components.CollisionBasic.html) component for other entities. It uses `EntityContainer` component messages if triggered to add to its collision list and also listens for explicit add/remove messages (useful in the absence of an `EntityContainer` component).
|
|
44
|
+
*
|
|
45
|
+
* @memberof platypus.components
|
|
46
|
+
* @uses platypus.Component
|
|
47
|
+
* @constructs
|
|
48
|
+
* @listens platypus.Entity#add-collision-entity
|
|
49
|
+
* @listens platypus.Entity#check-collision-group
|
|
50
|
+
* @listens platypus.Entity#child-entity-added
|
|
51
|
+
* @listens platypus.Entity#child-entity-removed
|
|
52
|
+
* @listens platypus.Entity#child-entity-updated
|
|
53
|
+
* @listens platypus.Entity#remove-collision-entity
|
|
54
|
+
* @fires platypus.Entity#hit-by-*
|
|
55
|
+
* @fires platypus.Entity#relocate-entity
|
|
56
|
+
*/
|
|
57
|
+
initialize: function () {
|
|
58
|
+
this.againstGrid = Data.setUp();
|
|
59
|
+
|
|
60
|
+
this.solidEntitiesLive = arrayCache.setUp();
|
|
61
|
+
this.softEntitiesLive = arrayCache.setUp();
|
|
62
|
+
this.allEntitiesLive = arrayCache.setUp();
|
|
63
|
+
this.groupsLive = arrayCache.setUp();
|
|
64
|
+
this.nonColliders = arrayCache.setUp();
|
|
65
|
+
|
|
66
|
+
this.terrains = [];
|
|
67
|
+
this.owner.previousX = this.owner.previousX || this.owner.x;
|
|
68
|
+
this.owner.previousY = this.owner.previousY || this.owner.y;
|
|
69
|
+
|
|
70
|
+
this.relocationMessage = Data.setUp(
|
|
71
|
+
"position", Vector.setUp(),
|
|
72
|
+
"relative", false
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
events: {
|
|
77
|
+
"child-entity-added": function (entity) {
|
|
78
|
+
if (!entity.collideOff) {
|
|
79
|
+
this.addCollisionEntity(entity);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
"add-collision-entity": function (entity) {
|
|
84
|
+
this.addCollisionEntity(entity);
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
"child-entity-removed": function (entity) {
|
|
88
|
+
this.removeCollisionEntity(entity);
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
"remove-collision-entity": function (entity) {
|
|
92
|
+
this.removeCollisionEntity(entity);
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
"child-entity-updated": function (entity) {
|
|
96
|
+
this.removeCollisionEntity(entity);
|
|
97
|
+
this.addCollisionEntity(entity);
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
"check-collision-group": function (resp) {
|
|
101
|
+
this.checkCamera(resp.camera, resp.entities);
|
|
102
|
+
this.checkGroupCollisions();
|
|
103
|
+
this.checkSolidCollisions();
|
|
104
|
+
this.resolveNonCollisions();
|
|
105
|
+
this.checkSoftCollisions(resp);
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
methods: {
|
|
110
|
+
mapDown (aabb2) {
|
|
111
|
+
const
|
|
112
|
+
aabb1 = AABB.setUp(),
|
|
113
|
+
gb = this.gridBits;
|
|
114
|
+
|
|
115
|
+
return aabb1.setBounds(aabb2.left >> gb, aabb2.top >> gb, aabb2.right >> gb, aabb2.bottom >> gb);
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
getAgainstGrid (entity, sweep, types) {
|
|
119
|
+
const
|
|
120
|
+
aabb = this.mapDown(sweep),
|
|
121
|
+
data = Data.setUp(),
|
|
122
|
+
thisAgainstGrid = this.againstGrid;
|
|
123
|
+
|
|
124
|
+
if (entity && sweep.equals(entity.againstAABB)) {
|
|
125
|
+
return this.getEntityAgainstGrid(entity, types);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (let x = aabb.left; x <= aabb.right; x++) {
|
|
129
|
+
for (let y = aabb.top; y <= aabb.bottom; y++) {
|
|
130
|
+
const
|
|
131
|
+
list = thisAgainstGrid[combine(x, y)];
|
|
132
|
+
|
|
133
|
+
if (list) {
|
|
134
|
+
this.mergeAGCell(list, data, types);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
aabb.recycle();
|
|
140
|
+
return data;
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
getEntityAgainstGrid: function (entity, types) {
|
|
144
|
+
const
|
|
145
|
+
ag = entity.againstGrid,
|
|
146
|
+
data = Data.setUp();
|
|
147
|
+
let i = ag.length;
|
|
148
|
+
|
|
149
|
+
while (i--) {
|
|
150
|
+
this.mergeAGCell(ag[i], data, types);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return data;
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
mergeAGCell: function (list, data, types) {
|
|
157
|
+
let i = types.length;
|
|
158
|
+
|
|
159
|
+
while (i--) {
|
|
160
|
+
const
|
|
161
|
+
type = types[i],
|
|
162
|
+
arr = list.get(type);
|
|
163
|
+
|
|
164
|
+
if (arr?.length) {
|
|
165
|
+
const tList = data[type];
|
|
166
|
+
if (!tList) {
|
|
167
|
+
data[type] = union(arrayCache.setUp(), arr);
|
|
168
|
+
} else {
|
|
169
|
+
union(tList, arr);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
removeAgainst (entity) {
|
|
176
|
+
const
|
|
177
|
+
{collisionTypes, againstGrid} = entity,
|
|
178
|
+
len = collisionTypes.length;
|
|
179
|
+
let i = againstGrid.length;
|
|
180
|
+
|
|
181
|
+
while (i--) {
|
|
182
|
+
const
|
|
183
|
+
list = againstGrid[i];
|
|
184
|
+
let j = len;
|
|
185
|
+
|
|
186
|
+
while (j--) {
|
|
187
|
+
const
|
|
188
|
+
arr = list.get(collisionTypes[j]);
|
|
189
|
+
|
|
190
|
+
if (arr) {
|
|
191
|
+
const
|
|
192
|
+
id = arr.indexOf(entity);
|
|
193
|
+
|
|
194
|
+
if (id >= 0) {
|
|
195
|
+
greenSplice(arr, id);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
againstGrid.length = 0;
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
updateAgainst (entity) {
|
|
204
|
+
const
|
|
205
|
+
{againstAABB, againstGrid: entityAgainstGrid, collisionTypes} = entity,
|
|
206
|
+
aabb = this.mapDown(entity.getAABB()),
|
|
207
|
+
{againstGrid} = this;
|
|
208
|
+
|
|
209
|
+
if (!aabb.equals(againstAABB)) {
|
|
210
|
+
againstAABB.set(aabb);
|
|
211
|
+
this.removeAgainst(entity);
|
|
212
|
+
|
|
213
|
+
for (let x = aabb.left; x <= aabb.right; x++) {
|
|
214
|
+
for (let y = aabb.top; y <= aabb.bottom; y++) {
|
|
215
|
+
const
|
|
216
|
+
id = combine(x, y);
|
|
217
|
+
let list = againstGrid[id],
|
|
218
|
+
i = collisionTypes.length;
|
|
219
|
+
|
|
220
|
+
if (!list) {
|
|
221
|
+
list = againstGrid[id] = DataMap.setUp();
|
|
222
|
+
}
|
|
223
|
+
while (i--) {
|
|
224
|
+
const
|
|
225
|
+
type = collisionTypes[i],
|
|
226
|
+
arr = list.get(type) ?? list.set(type, arrayCache.setUp());
|
|
227
|
+
|
|
228
|
+
arr.push(entity);
|
|
229
|
+
}
|
|
230
|
+
entityAgainstGrid.push(list);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
aabb.recycle();
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
addCollisionEntity: function (entity) {
|
|
239
|
+
if (entity.getTileShapes) { // Has a CollisionTiles component
|
|
240
|
+
this.terrains.push(entity);
|
|
241
|
+
} else if (entity.collisionTypes && !entity.againstGrid) {
|
|
242
|
+
entity.againstGrid = arrayCache.setUp();
|
|
243
|
+
entity.againstAABB = AABB.setUp();
|
|
244
|
+
this.updateAgainst(entity);
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
removeCollisionEntity: function (entity) {
|
|
249
|
+
if (entity.getTileShapes) { // Has a CollisionTiles component
|
|
250
|
+
const index = this.terrains.indexOf(entity);
|
|
251
|
+
if (index !== -1) {
|
|
252
|
+
this.terrains.splice(index, 1);
|
|
253
|
+
}
|
|
254
|
+
} if (entity.againstGrid) {
|
|
255
|
+
this.removeAgainst(entity);
|
|
256
|
+
arrayCache.recycle(entity.againstGrid);
|
|
257
|
+
entity.againstGrid = null;
|
|
258
|
+
entity.againstAABB.recycle();
|
|
259
|
+
entity.againstAABB = null;
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
checkCamera: function (camera, all) {
|
|
264
|
+
const
|
|
265
|
+
{allEntitiesLive, solidEntitiesLive, softEntitiesLive, nonColliders, groupsLive} = this;
|
|
266
|
+
let i = all.length;
|
|
267
|
+
|
|
268
|
+
allEntitiesLive.length = 0;
|
|
269
|
+
solidEntitiesLive.length = 0;
|
|
270
|
+
softEntitiesLive.length = 0;
|
|
271
|
+
nonColliders.length = 0;
|
|
272
|
+
groupsLive.length = 0;
|
|
273
|
+
|
|
274
|
+
while (i--) {
|
|
275
|
+
const
|
|
276
|
+
entity = all[i],
|
|
277
|
+
{collisionTypes, immobile} = entity;
|
|
278
|
+
|
|
279
|
+
if (!immobile && collisionTypes?.length) {
|
|
280
|
+
let collides = false,
|
|
281
|
+
j = collisionTypes.length;
|
|
282
|
+
|
|
283
|
+
allEntitiesLive.push(entity);
|
|
284
|
+
|
|
285
|
+
if (entity !== this.owner) {
|
|
286
|
+
let k = collisionTypes.length;
|
|
287
|
+
|
|
288
|
+
while (k--) {
|
|
289
|
+
if (entity.solidCollisionMap.get(collisionTypes[k]).length) {
|
|
290
|
+
solidEntitiesLive.push(entity);
|
|
291
|
+
collides = true;
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
while (j--) {
|
|
298
|
+
if (entity.softCollisionMap.get(collisionTypes[j]).length) {
|
|
299
|
+
softEntitiesLive.push(entity);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (!collides) {
|
|
305
|
+
nonColliders.push(entity);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (entity.collisionGroup) {
|
|
309
|
+
groupsLive.push(entity);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
groupsLive.sort(groupSortBySize);
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
resolveNonCollisions: function () {
|
|
318
|
+
const
|
|
319
|
+
msg = this.relocationMessage,
|
|
320
|
+
nons = this.nonColliders;
|
|
321
|
+
let i = nons.length;
|
|
322
|
+
|
|
323
|
+
msg.relative = false;
|
|
324
|
+
while (i--) {
|
|
325
|
+
const
|
|
326
|
+
entity = nons[i];
|
|
327
|
+
|
|
328
|
+
if ((entity.position.x !== entity.previousPosition.x) || (entity.position.y !== entity.previousPosition.y)) {
|
|
329
|
+
msg.position.setVector(entity.position);
|
|
330
|
+
entity.triggerEvent('relocate-entity', msg);
|
|
331
|
+
this.updateAgainst(entity);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
checkGroupCollisions: (function () {
|
|
337
|
+
/**
|
|
338
|
+
* When an entity collides with an entity of a listed collision-type, this message is triggered on the entity. * is the other entity's collision-type.
|
|
339
|
+
*
|
|
340
|
+
* @event platypus.Entity#hit-by-*
|
|
341
|
+
* @param collision {Object}
|
|
342
|
+
* @param collision.entity {Entity} The entity with which the collision occurred.
|
|
343
|
+
* @param collision.target {Entity} The entity that's receiving the collision event.
|
|
344
|
+
* @param collision.type {String} The collision type of the other entity.
|
|
345
|
+
* @param collision.shape {CollisionShape} This is the shape of the other entity that caused the collision.
|
|
346
|
+
* @param collision.x {number} Returns -1, 0, or 1 indicating on which side of this entity the collision occurred: left, neither, or right respectively.
|
|
347
|
+
* @param collision.y {number} Returns -1, 0, or 1 indicating on which side of this entity the collision occurred: top, neither, or bottom respectively.
|
|
348
|
+
*/
|
|
349
|
+
const
|
|
350
|
+
triggerCollisionMessages = function (entity, otherEntity, thisType, thatType, x, y, hitType, vector) {
|
|
351
|
+
const
|
|
352
|
+
msg = triggerMessage;
|
|
353
|
+
|
|
354
|
+
msg.entity = otherEntity;
|
|
355
|
+
msg.target = entity;
|
|
356
|
+
msg.myType = thisType;
|
|
357
|
+
msg.type = thatType;
|
|
358
|
+
msg.x = x;
|
|
359
|
+
msg.y = y;
|
|
360
|
+
msg.direction = vector;
|
|
361
|
+
msg.hitType = hitType;
|
|
362
|
+
entity.triggerEvent('hit-by-' + thatType, msg);
|
|
363
|
+
|
|
364
|
+
if (otherEntity) {
|
|
365
|
+
msg.entity = entity;
|
|
366
|
+
msg.target = otherEntity;
|
|
367
|
+
msg.type = thisType;
|
|
368
|
+
msg.myType = thatType;
|
|
369
|
+
msg.x = -x;
|
|
370
|
+
msg.y = -y;
|
|
371
|
+
msg.direction = vector.getInverse();
|
|
372
|
+
msg.hitType = hitType;
|
|
373
|
+
otherEntity.triggerEvent('hit-by-' + thisType, msg);
|
|
374
|
+
|
|
375
|
+
msg.direction.recycle();
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
return function () {
|
|
380
|
+
const
|
|
381
|
+
entities = this.groupsLive;
|
|
382
|
+
let i = entities.length;
|
|
383
|
+
|
|
384
|
+
while (i--) {
|
|
385
|
+
const
|
|
386
|
+
entity = entities[i];
|
|
387
|
+
|
|
388
|
+
if (entity.collisionGroup.getSize() > 1) {
|
|
389
|
+
const
|
|
390
|
+
entityCDC = this.checkSolidEntityCollision(entity, entity.collisionGroup),
|
|
391
|
+
{xData, yData} = entityCDC;
|
|
392
|
+
let x = xData.length,
|
|
393
|
+
y = yData.length
|
|
394
|
+
|
|
395
|
+
while (x--) {
|
|
396
|
+
const
|
|
397
|
+
messageData = xData[x];
|
|
398
|
+
triggerCollisionMessages(messageData.thisShape.owner, messageData.thatShape.owner, messageData.thisShape.collisionType, messageData.thatShape.collisionType, messageData.direction, 0, 'solid', messageData.vector);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
while (y--) {
|
|
402
|
+
const
|
|
403
|
+
messageData = yData[y];
|
|
404
|
+
|
|
405
|
+
triggerCollisionMessages(messageData.thisShape.owner, messageData.thatShape.owner, messageData.thisShape.collisionType, messageData.thatShape.collisionType, 0, messageData.direction, 'solid', messageData.vector);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
entityCDC.recycle();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
}()),
|
|
413
|
+
|
|
414
|
+
checkSolidCollisions: (function () {
|
|
415
|
+
const
|
|
416
|
+
triggerCollisionMessages = function (entity, otherEntity, thisType, thatType, x, y, hitType, vector) {
|
|
417
|
+
const
|
|
418
|
+
msg = triggerMessage;
|
|
419
|
+
|
|
420
|
+
msg.entity = otherEntity;
|
|
421
|
+
msg.target = entity;
|
|
422
|
+
msg.myType = thisType;
|
|
423
|
+
msg.type = thatType;
|
|
424
|
+
msg.x = x;
|
|
425
|
+
msg.y = y;
|
|
426
|
+
msg.direction = vector;
|
|
427
|
+
msg.hitType = hitType;
|
|
428
|
+
entity.triggerEvent('hit-by-' + thatType, msg);
|
|
429
|
+
|
|
430
|
+
if (otherEntity) {
|
|
431
|
+
msg.entity = entity;
|
|
432
|
+
msg.target = otherEntity;
|
|
433
|
+
msg.type = thisType;
|
|
434
|
+
msg.myType = thatType;
|
|
435
|
+
msg.x = -x;
|
|
436
|
+
msg.y = -y;
|
|
437
|
+
msg.direction = vector.getInverse();
|
|
438
|
+
msg.hitType = hitType;
|
|
439
|
+
otherEntity.triggerEvent('hit-by-' + thisType, msg);
|
|
440
|
+
|
|
441
|
+
msg.direction.recycle();
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
return function () {
|
|
446
|
+
const
|
|
447
|
+
entities = this.solidEntitiesLive;
|
|
448
|
+
let i = entities.length;
|
|
449
|
+
|
|
450
|
+
while (i--) {
|
|
451
|
+
const
|
|
452
|
+
entity = entities[i],
|
|
453
|
+
entityCDC = this.checkSolidEntityCollision(entity, entity),
|
|
454
|
+
{xData, yData} = entityCDC;
|
|
455
|
+
let x = xData.length,
|
|
456
|
+
y = yData.length
|
|
457
|
+
|
|
458
|
+
while (x--) {
|
|
459
|
+
const
|
|
460
|
+
messageData = xData[x];
|
|
461
|
+
|
|
462
|
+
triggerCollisionMessages(messageData.thisShape.owner, messageData.thatShape.owner, messageData.thisShape.collisionType, messageData.thatShape.collisionType, messageData.direction, 0, 'solid', messageData.vector);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
while (y--) {
|
|
466
|
+
const
|
|
467
|
+
messageData = yData[y];
|
|
468
|
+
|
|
469
|
+
triggerCollisionMessages(messageData.thisShape.owner, messageData.thatShape.owner, messageData.thisShape.collisionType, messageData.thatShape.collisionType, 0, messageData.direction, 'solid', messageData.vector);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
entityCDC.recycle();
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
}()),
|
|
476
|
+
|
|
477
|
+
checkSolidEntityCollision: function (ent, entityOrGroup) {
|
|
478
|
+
const
|
|
479
|
+
{bullet, collisionDirty, previousX, previousY, x, y} = ent,
|
|
480
|
+
collisionDataCollection = CollisionDataContainer.setUp(),
|
|
481
|
+
dX = x - previousX,
|
|
482
|
+
dY = y - previousY,
|
|
483
|
+
collisionTypes = entityOrGroup.getCollisionTypes(),
|
|
484
|
+
ignoredEntities = entityOrGroup.getSolidEntities?.() ?? false;
|
|
485
|
+
let finalMovementInfo = Vector.setUp(ent.position);
|
|
486
|
+
|
|
487
|
+
if (dX || dY || collisionDirty) {
|
|
488
|
+
|
|
489
|
+
if (bullet) {
|
|
490
|
+
let sW = Infinity,
|
|
491
|
+
sH = Infinity,
|
|
492
|
+
i = collisionTypes.length;
|
|
493
|
+
|
|
494
|
+
while (i--) {
|
|
495
|
+
const
|
|
496
|
+
aabb = entityOrGroup.getAABB(collisionTypes[i]);
|
|
497
|
+
|
|
498
|
+
sW = Math.min(sW, aabb.width);
|
|
499
|
+
sH = Math.min(sH, aabb.height);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
{
|
|
503
|
+
const
|
|
504
|
+
//Stepping to catch really fast entities - this is not perfect, but should prevent the majority of fallthrough cases.
|
|
505
|
+
steps = Math.min(Math.ceil(Math.max(Math.abs(dX) / sW, Math.abs(dY) / sH)), 100), //Prevent memory overflow if things move exponentially far.
|
|
506
|
+
stepDX = dX / steps,
|
|
507
|
+
stepDY = dY / steps;
|
|
508
|
+
let step = steps;
|
|
509
|
+
|
|
510
|
+
while (step--) {
|
|
511
|
+
entityOrGroup.prepareCollision(ent.previousX + stepDX, ent.previousY + stepDY);
|
|
512
|
+
|
|
513
|
+
finalMovementInfo = this.processCollisionStep(ent, entityOrGroup, ignoredEntities, collisionDataCollection, finalMovementInfo.setVector(ent.position), stepDX, stepDY, collisionTypes);
|
|
514
|
+
|
|
515
|
+
if ((finalMovementInfo.x === ent.previousX) && (finalMovementInfo.y === ent.previousY)) {
|
|
516
|
+
entityOrGroup.relocateEntity(finalMovementInfo, collisionDataCollection);
|
|
517
|
+
//No more movement so we bail!
|
|
518
|
+
break;
|
|
519
|
+
} else {
|
|
520
|
+
entityOrGroup.relocateEntity(finalMovementInfo, collisionDataCollection);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
} else {
|
|
525
|
+
entityOrGroup.prepareCollision(previousX + dX, previousY + dY);
|
|
526
|
+
finalMovementInfo = this.processCollisionStep(ent, entityOrGroup, ignoredEntities, collisionDataCollection, finalMovementInfo, dX, dY, collisionTypes);
|
|
527
|
+
entityOrGroup.relocateEntity(finalMovementInfo, collisionDataCollection);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if ((finalMovementInfo.x !== previousX) || (finalMovementInfo.y !== previousY)) {
|
|
531
|
+
this.updateAgainst(ent);
|
|
532
|
+
|
|
533
|
+
// Update children affected by this movement.
|
|
534
|
+
if (ent !== entityOrGroup) {
|
|
535
|
+
const
|
|
536
|
+
children = entityOrGroup.getSolidEntities();
|
|
537
|
+
|
|
538
|
+
for (let i = 0; i < children.length; i++) {
|
|
539
|
+
this.updateAgainst(children[i]);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
finalMovementInfo.recycle();
|
|
546
|
+
|
|
547
|
+
return collisionDataCollection;
|
|
548
|
+
},
|
|
549
|
+
|
|
550
|
+
processCollisionStep: (function () {
|
|
551
|
+
const
|
|
552
|
+
sweeper = AABB.setUp(),
|
|
553
|
+
getJumpThroughNormal = function (shape) {
|
|
554
|
+
const
|
|
555
|
+
jt = shape.jumpThrough;
|
|
556
|
+
|
|
557
|
+
if (!jt) {
|
|
558
|
+
return null;
|
|
559
|
+
} else {
|
|
560
|
+
const
|
|
561
|
+
owner = shape.owner,
|
|
562
|
+
v = Vector.setUp(jt.x * (owner.scaleX || 1), jt.y * (owner.scaleY || 1));
|
|
563
|
+
|
|
564
|
+
if (owner.rotation) {
|
|
565
|
+
v.rotate(owner.rotation * Math.PI / 180);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return v;
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
shouldSkipJumpThroughCollision = function (platformEntity, movingAABB, platformAABB) {
|
|
572
|
+
//TODO: currently does not handle individual shape jumpThrough. That will need to happen a layer deeper.
|
|
573
|
+
const collisionTypes = platformEntity.collisionTypes;
|
|
574
|
+
|
|
575
|
+
if (!collisionTypes) {
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
let i = collisionTypes.length;
|
|
580
|
+
|
|
581
|
+
while (i--) {
|
|
582
|
+
const shapes = platformEntity.getShapes(collisionTypes[i]);
|
|
583
|
+
|
|
584
|
+
if (!shapes) {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
let j = shapes.length;
|
|
589
|
+
|
|
590
|
+
while (j--) {
|
|
591
|
+
const
|
|
592
|
+
shape = shapes[j],
|
|
593
|
+
normal = getJumpThroughNormal(shape);
|
|
594
|
+
|
|
595
|
+
if (!normal) {
|
|
596
|
+
continue;
|
|
597
|
+
} else {
|
|
598
|
+
const
|
|
599
|
+
absx = Math.abs(normal.x),
|
|
600
|
+
absy = Math.abs(normal.y),
|
|
601
|
+
ignore = absy >= absx
|
|
602
|
+
? ( // Primarily vertical normal
|
|
603
|
+
(normal.y < -epsilon && movingAABB.bottom > platformAABB.top) ||
|
|
604
|
+
(normal.y > epsilon && movingAABB.top < platformAABB.bottom)
|
|
605
|
+
)
|
|
606
|
+
: ( // Primarily horizontal normal
|
|
607
|
+
(normal.x < -epsilon && movingAABB.right > platformAABB.left) ||
|
|
608
|
+
(normal.x > epsilon && movingAABB.left < platformAABB.right)
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
normal.recycle();
|
|
612
|
+
|
|
613
|
+
if (ignore) {
|
|
614
|
+
return ignore;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
return false;
|
|
621
|
+
},
|
|
622
|
+
includeEntity = function (thisEntity, aabb, otherEntity, otherAABB, ignoredEntities, sweepAABB) {
|
|
623
|
+
//Chop out all the special case entities we don't want to check against.
|
|
624
|
+
if (otherEntity === thisEntity) {
|
|
625
|
+
return false;
|
|
626
|
+
} else if (shouldSkipJumpThroughCollision(otherEntity, aabb, otherAABB)) {
|
|
627
|
+
return false;
|
|
628
|
+
} else if (shouldSkipJumpThroughCollision(thisEntity, otherAABB, aabb)) { // This will allow platforms to hit something solid sideways if it runs into them from the side even though originally they were above the top. - DDD
|
|
629
|
+
return false;
|
|
630
|
+
} else if (ignoredEntities) {
|
|
631
|
+
let i = ignoredEntities.length;
|
|
632
|
+
|
|
633
|
+
while (i--) {
|
|
634
|
+
if (otherEntity === ignoredEntities[i]) {
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return sweepAABB.collides(otherAABB);
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
return function (ent, entityOrGroup, ignoredEntities, collisionDataCollection, finalMovementInfo, entityDeltaX, entityDeltaY, collisionTypes) {
|
|
644
|
+
const
|
|
645
|
+
potentialCollidingShapes = arrayCache.setUp(),
|
|
646
|
+
terrains = this.terrains,
|
|
647
|
+
solidCollisionMap = entityOrGroup.getSolidCollisions(),
|
|
648
|
+
sweepAABB = sweeper;
|
|
649
|
+
let i = collisionTypes.length,
|
|
650
|
+
potentialCollision = false;
|
|
651
|
+
|
|
652
|
+
while (i--) {
|
|
653
|
+
//Sweep the full movement of each collision type
|
|
654
|
+
const
|
|
655
|
+
pcsGroup = potentialCollidingShapes[i] = arrayCache.setUp(),
|
|
656
|
+
collisionType = collisionTypes[i],
|
|
657
|
+
previousAABB = entityOrGroup.getPreviousAABB(collisionType),
|
|
658
|
+
currentAABB = entityOrGroup.getAABB(collisionType),
|
|
659
|
+
collisionSubTypes = solidCollisionMap.get(collisionType);
|
|
660
|
+
let againstGrid = null,
|
|
661
|
+
j = collisionSubTypes.length;;
|
|
662
|
+
|
|
663
|
+
sweepAABB.set(currentAABB);
|
|
664
|
+
sweepAABB.include(previousAABB);
|
|
665
|
+
|
|
666
|
+
againstGrid = this.getAgainstGrid(ent, sweepAABB, collisionSubTypes);
|
|
667
|
+
|
|
668
|
+
while (j--) {
|
|
669
|
+
const
|
|
670
|
+
otherCollisionType = collisionSubTypes[j],
|
|
671
|
+
otherEntities = againstGrid[otherCollisionType];
|
|
672
|
+
|
|
673
|
+
if (otherEntities) {
|
|
674
|
+
let k = otherEntities.length;
|
|
675
|
+
|
|
676
|
+
while (k--) {
|
|
677
|
+
const
|
|
678
|
+
otherEntity = otherEntities[k],
|
|
679
|
+
otherAABB = otherEntity.getAABB(otherCollisionType);
|
|
680
|
+
|
|
681
|
+
//Do our sweep check against the AABB of the other object and add potentially colliding shapes to our list.
|
|
682
|
+
if (includeEntity(ent, previousAABB, otherEntity, otherAABB, ignoredEntities, sweepAABB)) {
|
|
683
|
+
const
|
|
684
|
+
otherShapes = otherEntity.getShapes(otherCollisionType);
|
|
685
|
+
let l = otherShapes.length;
|
|
686
|
+
|
|
687
|
+
while (l--) {
|
|
688
|
+
//Push the shapes on the end!
|
|
689
|
+
pcsGroup.push(otherShapes[l]);
|
|
690
|
+
}
|
|
691
|
+
potentialCollision = true;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
arrayCache.recycle(otherEntities);
|
|
695
|
+
} else if (terrains.length) {
|
|
696
|
+
//Do our sweep check against the tiles and add potentially colliding shapes to our list.
|
|
697
|
+
let l = 0;
|
|
698
|
+
|
|
699
|
+
for (l = 0; l < terrains.length; l++) {
|
|
700
|
+
const otherShapes = terrains[l].getTileShapes(sweepAABB, previousAABB, otherCollisionType);
|
|
701
|
+
let k = otherShapes.length;
|
|
702
|
+
|
|
703
|
+
while (k--) {
|
|
704
|
+
//Push the shapes on the end!
|
|
705
|
+
pcsGroup.push(otherShapes[k]);
|
|
706
|
+
potentialCollision = true;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
againstGrid.recycle();
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (potentialCollision) {
|
|
715
|
+
finalMovementInfo = this.resolveCollisionPosition(ent, entityOrGroup, finalMovementInfo, potentialCollidingShapes, collisionDataCollection, collisionTypes, entityDeltaX, entityDeltaY);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Array recycling
|
|
719
|
+
arrayCache.recycle(potentialCollidingShapes, 2);
|
|
720
|
+
|
|
721
|
+
return finalMovementInfo;
|
|
722
|
+
};
|
|
723
|
+
}()),
|
|
724
|
+
|
|
725
|
+
resolveCollisionPosition: function (ent, entityOrGroup, finalMovementInfo, potentialCollidingShapes, collisionDataCollection, collisionTypes, entityDeltaX, entityDeltaY) {
|
|
726
|
+
if (entityDeltaX !== 0) {
|
|
727
|
+
let j = collisionTypes.length;
|
|
728
|
+
|
|
729
|
+
while (j--) {
|
|
730
|
+
//Move each collision type in X to find the min X movement
|
|
731
|
+
const
|
|
732
|
+
cd = this.findMinAxisMovement(ent, entityOrGroup, collisionTypes[j], 'x', potentialCollidingShapes[j]);
|
|
733
|
+
|
|
734
|
+
if (!cd.occurred || !collisionDataCollection.tryToAddX(cd)) {
|
|
735
|
+
cd.recycle();
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
{
|
|
741
|
+
const
|
|
742
|
+
cd = collisionDataCollection.xData[0];
|
|
743
|
+
if (cd) {
|
|
744
|
+
finalMovementInfo.x = ent.previousX + cd.deltaMovement * cd.direction;
|
|
745
|
+
} else {
|
|
746
|
+
finalMovementInfo.x = ent.x;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// This moves the previous position of everything so that the check in Y can begin.
|
|
751
|
+
entityOrGroup.movePreviousX(finalMovementInfo.x);
|
|
752
|
+
|
|
753
|
+
if (entityDeltaY !== 0) {
|
|
754
|
+
let j = collisionTypes.length;
|
|
755
|
+
|
|
756
|
+
while (j--) {
|
|
757
|
+
//Move each collision type in Y to find the min Y movement
|
|
758
|
+
const
|
|
759
|
+
cd = this.findMinAxisMovement(ent, entityOrGroup, collisionTypes[j], 'y', potentialCollidingShapes[j]);
|
|
760
|
+
|
|
761
|
+
if (!cd.occurred || !collisionDataCollection.tryToAddY(cd)) {
|
|
762
|
+
cd.recycle();
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
{
|
|
768
|
+
const
|
|
769
|
+
cd = collisionDataCollection.yData[0];
|
|
770
|
+
if (cd) {
|
|
771
|
+
finalMovementInfo.y = ent.previousY + cd.deltaMovement * cd.direction;
|
|
772
|
+
} else {
|
|
773
|
+
finalMovementInfo.y = ent.y;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
return finalMovementInfo;
|
|
778
|
+
},
|
|
779
|
+
|
|
780
|
+
findMinAxisMovement: function (ent, entityOrGroup, collisionType, axis, potentialCollidingShapes) {
|
|
781
|
+
//Loop through my shapes of this type vs the colliding shapes and do precise collision returning the shortest movement in axis direction
|
|
782
|
+
const
|
|
783
|
+
shapes = entityOrGroup.getShapes(collisionType),
|
|
784
|
+
prevShapes = entityOrGroup.getPrevShapes(collisionType);
|
|
785
|
+
let bestCD = CollisionData.setUp(),
|
|
786
|
+
i = shapes.length;
|
|
787
|
+
|
|
788
|
+
while (i--) {
|
|
789
|
+
const
|
|
790
|
+
cd = this.findMinShapeMovementCollision(prevShapes[i], shapes[i], axis, potentialCollidingShapes);
|
|
791
|
+
|
|
792
|
+
if (cd.occurred && (!bestCD.occurred //if a collision occurred and we haven't already had a collision.
|
|
793
|
+
|| (cd.deltaMovement < bestCD.deltaMovement))) { //if a collision occurred and the diff is smaller than our best diff.
|
|
794
|
+
bestCD.recycle();
|
|
795
|
+
bestCD = cd;
|
|
796
|
+
} else {
|
|
797
|
+
cd.recycle();
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
return bestCD;
|
|
802
|
+
},
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Find the earliest point at which this shape collides with one of the potential colliding shapes along this axis.
|
|
806
|
+
* For example, cycles through shapes a, b, and c to find the earliest position:
|
|
807
|
+
*
|
|
808
|
+
* O----> [b] [a] [c]
|
|
809
|
+
*
|
|
810
|
+
* Returns collision location for:
|
|
811
|
+
*
|
|
812
|
+
* O[b]
|
|
813
|
+
*
|
|
814
|
+
*/
|
|
815
|
+
findMinShapeMovementCollision: (function () {
|
|
816
|
+
const
|
|
817
|
+
returnInfo = {
|
|
818
|
+
position: 0,
|
|
819
|
+
contactVector: Vector.setUp()
|
|
820
|
+
},
|
|
821
|
+
getMovementDistance = (currentDistance, minimumDistance) => Math.sqrt((minimumDistance ** 2) - (currentDistance ** 2)),
|
|
822
|
+
getCorner = function (circlePos, rectanglePos, half) {
|
|
823
|
+
const
|
|
824
|
+
diff = circlePos - rectanglePos;
|
|
825
|
+
|
|
826
|
+
return diff - (diff / Math.abs(diff)) * half;
|
|
827
|
+
},
|
|
828
|
+
getOffsetForCircleVsAABBX = function (circle, rect, moving, direction, v) {
|
|
829
|
+
const
|
|
830
|
+
aabb = rect.aABB,
|
|
831
|
+
hw = aabb.halfWidth,
|
|
832
|
+
{x, y} = circle;
|
|
833
|
+
|
|
834
|
+
if (y >= aabb.top && y <= aabb.bottom) {
|
|
835
|
+
return hw + circle.radius;
|
|
836
|
+
} else {
|
|
837
|
+
const
|
|
838
|
+
cornerY = getCorner(y, rect.y, aabb.halfHeight),
|
|
839
|
+
newAxisPosition = hw + getMovementDistance(cornerY, circle.radius);
|
|
840
|
+
|
|
841
|
+
if (moving === circle) {
|
|
842
|
+
v.x = -getCorner(x - direction * newAxisPosition, rect.x, hw) / 2;
|
|
843
|
+
v.y = -cornerY;
|
|
844
|
+
} else {
|
|
845
|
+
v.x = getCorner(x, rect.x - direction * newAxisPosition, hw) / 2;
|
|
846
|
+
v.y = cornerY;
|
|
847
|
+
}
|
|
848
|
+
v.normalize();
|
|
849
|
+
return newAxisPosition;
|
|
850
|
+
}
|
|
851
|
+
},
|
|
852
|
+
getOffsetForCircleVsAABBY = function (circle, rect, moving, direction, v) {
|
|
853
|
+
const
|
|
854
|
+
aabb = rect.aABB,
|
|
855
|
+
hh = aabb.halfHeight,
|
|
856
|
+
{x, y} = circle;
|
|
857
|
+
|
|
858
|
+
if (x >= aabb.left && x <= aabb.right) {
|
|
859
|
+
return hh + circle.radius;
|
|
860
|
+
} else {
|
|
861
|
+
const
|
|
862
|
+
cornerX = getCorner(x, rect.x, aabb.halfWidth),
|
|
863
|
+
newAxisPosition = hh + getMovementDistance(cornerX, circle.radius);
|
|
864
|
+
|
|
865
|
+
if (moving === circle) {
|
|
866
|
+
v.x = -cornerX;
|
|
867
|
+
v.y = -getCorner(y - direction * newAxisPosition, rect.y, hh) / 2;
|
|
868
|
+
} else {
|
|
869
|
+
v.x = cornerX;
|
|
870
|
+
v.y = getCorner(y, rect.y - direction * newAxisPosition, hh) / 2;
|
|
871
|
+
}
|
|
872
|
+
v.normalize();
|
|
873
|
+
return newAxisPosition;
|
|
874
|
+
}
|
|
875
|
+
},
|
|
876
|
+
findAxisCollisionPosition = { // Decision tree for quicker access, optimized for mobile devices.
|
|
877
|
+
x: {
|
|
878
|
+
rectangle: {
|
|
879
|
+
rectangle: function (direction, thisShape, thatShape) {
|
|
880
|
+
const
|
|
881
|
+
ri = returnInfo;
|
|
882
|
+
|
|
883
|
+
ri.position = thatShape.x - direction * (thatShape.aABB.halfWidth + thisShape.aABB.halfWidth);
|
|
884
|
+
ri.contactVector.setXYZ(direction, 0);
|
|
885
|
+
|
|
886
|
+
return ri;
|
|
887
|
+
},
|
|
888
|
+
circle: function (direction, thisShape, thatShape) {
|
|
889
|
+
const
|
|
890
|
+
ri = returnInfo;
|
|
891
|
+
|
|
892
|
+
ri.position = thatShape.x - direction * getOffsetForCircleVsAABBX(thatShape, thisShape, thisShape, direction, ri.contactVector.setXYZ(direction, 0));
|
|
893
|
+
|
|
894
|
+
return ri;
|
|
895
|
+
}
|
|
896
|
+
},
|
|
897
|
+
circle: {
|
|
898
|
+
rectangle: function (direction, thisShape, thatShape) {
|
|
899
|
+
const
|
|
900
|
+
ri = returnInfo;
|
|
901
|
+
|
|
902
|
+
ri.position = thatShape.x - direction * getOffsetForCircleVsAABBX(thisShape, thatShape, thisShape, direction, ri.contactVector.setXYZ(direction, 0));
|
|
903
|
+
|
|
904
|
+
return ri;
|
|
905
|
+
},
|
|
906
|
+
circle: function (direction, thisShape, thatShape) {
|
|
907
|
+
const
|
|
908
|
+
y = thatShape.y - thisShape.y,
|
|
909
|
+
position = thatShape.x - direction * getMovementDistance(y, thisShape.radius + thatShape.radius),
|
|
910
|
+
ri = returnInfo;
|
|
911
|
+
|
|
912
|
+
ri.contactVector.setXYZ(thatShape.x - position, y).normalize();
|
|
913
|
+
ri.position = position;
|
|
914
|
+
|
|
915
|
+
return ri;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
y: {
|
|
920
|
+
rectangle: {
|
|
921
|
+
rectangle: function (direction, thisShape, thatShape) {
|
|
922
|
+
const
|
|
923
|
+
ri = returnInfo;
|
|
924
|
+
|
|
925
|
+
ri.position = thatShape.y - direction * (thatShape.aABB.halfHeight + thisShape.aABB.halfHeight);
|
|
926
|
+
ri.contactVector.setXYZ(0, direction);
|
|
927
|
+
|
|
928
|
+
return ri;
|
|
929
|
+
},
|
|
930
|
+
circle: function (direction, thisShape, thatShape) {
|
|
931
|
+
const
|
|
932
|
+
ri = returnInfo;
|
|
933
|
+
|
|
934
|
+
ri.position = thatShape.y - direction * getOffsetForCircleVsAABBY(thatShape, thisShape, thisShape, direction, ri.contactVector.setXYZ(0, direction));
|
|
935
|
+
|
|
936
|
+
return ri;
|
|
937
|
+
}
|
|
938
|
+
},
|
|
939
|
+
circle: {
|
|
940
|
+
rectangle: function (direction, thisShape, thatShape) {
|
|
941
|
+
const
|
|
942
|
+
ri = returnInfo;
|
|
943
|
+
|
|
944
|
+
ri.position = thatShape.y - direction * getOffsetForCircleVsAABBY(thisShape, thatShape, thisShape, direction, ri.contactVector.setXYZ(0, direction));
|
|
945
|
+
|
|
946
|
+
return ri;
|
|
947
|
+
},
|
|
948
|
+
circle: function (direction, thisShape, thatShape) {
|
|
949
|
+
const
|
|
950
|
+
x = thatShape.x - thisShape.x,
|
|
951
|
+
position = thatShape.y - direction * getMovementDistance(x, thisShape.radius + thatShape.radius),
|
|
952
|
+
ri = returnInfo;
|
|
953
|
+
|
|
954
|
+
ri.contactVector.setXYZ(x, thatShape.y - position).normalize();
|
|
955
|
+
ri.position = position;
|
|
956
|
+
|
|
957
|
+
return ri;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
return function (translatedShape, currentShape, axis, potentialCollidingShapes) {
|
|
964
|
+
const
|
|
965
|
+
initialPoint = translatedShape[axis],
|
|
966
|
+
goalPoint = currentShape[axis],
|
|
967
|
+
direction = ((initialPoint < goalPoint) ? 1 : -1),
|
|
968
|
+
cd = CollisionData.setUp();
|
|
969
|
+
let finalPosition = goalPoint;
|
|
970
|
+
|
|
971
|
+
if (initialPoint !== goalPoint) {
|
|
972
|
+
const
|
|
973
|
+
findACP = findAxisCollisionPosition[axis][translatedShape.type];
|
|
974
|
+
let i = potentialCollidingShapes.length
|
|
975
|
+
|
|
976
|
+
if (axis === 'x') {
|
|
977
|
+
translatedShape.moveX(goalPoint);
|
|
978
|
+
} else if (axis === 'y') {
|
|
979
|
+
translatedShape.moveY(goalPoint);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
while (i--) {
|
|
983
|
+
const
|
|
984
|
+
pcShape = potentialCollidingShapes[i];
|
|
985
|
+
|
|
986
|
+
if (translatedShape.collides(pcShape)) {
|
|
987
|
+
const
|
|
988
|
+
collisionInfo = findACP[pcShape.type](direction, translatedShape, pcShape),
|
|
989
|
+
position = collisionInfo.position;
|
|
990
|
+
|
|
991
|
+
if (direction > 0) {
|
|
992
|
+
if (position < finalPosition) {
|
|
993
|
+
finalPosition = position < initialPoint ? initialPoint : position; // Reality check: I think this is necessary due to floating point inaccuracies. - DDD
|
|
994
|
+
cd.set(true, direction, finalPosition, Math.abs(finalPosition - initialPoint), pcShape.aABB, currentShape, pcShape, collisionInfo.contactVector, 0);
|
|
995
|
+
}
|
|
996
|
+
} else if (position > finalPosition) {
|
|
997
|
+
finalPosition = position > initialPoint ? initialPoint : position; // Reality check: I think this is necessary due to floating point inaccuracies. - DDD
|
|
998
|
+
cd.set(true, direction, finalPosition, Math.abs(finalPosition - initialPoint), pcShape.aABB, currentShape, pcShape, collisionInfo.contactVector, 0);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
return cd;
|
|
1005
|
+
};
|
|
1006
|
+
}()),
|
|
1007
|
+
|
|
1008
|
+
checkSoftCollisions () {
|
|
1009
|
+
const
|
|
1010
|
+
softs = this.softEntitiesLive;
|
|
1011
|
+
let i = softs.length;
|
|
1012
|
+
|
|
1013
|
+
while (i--) {
|
|
1014
|
+
const
|
|
1015
|
+
entity = softs[i];
|
|
1016
|
+
|
|
1017
|
+
this.checkEntityForSoftCollisions(entity, (collision) => {
|
|
1018
|
+
entity.triggerEvent('hit-by-' + collision.type, collision);
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
|
|
1023
|
+
checkEntityForSoftCollisions: function (ent, callback) {
|
|
1024
|
+
const
|
|
1025
|
+
message = triggerMessage,
|
|
1026
|
+
terrains = this.terrains;
|
|
1027
|
+
let i = ent.collisionTypes.length;
|
|
1028
|
+
|
|
1029
|
+
message.x = 0;
|
|
1030
|
+
message.y = 0;
|
|
1031
|
+
|
|
1032
|
+
while (i--) {
|
|
1033
|
+
const
|
|
1034
|
+
collisionType = ent.collisionTypes[i],
|
|
1035
|
+
softCollisionMap = ent.softCollisionMap.get(collisionType),
|
|
1036
|
+
againstGrid = this.getEntityAgainstGrid(ent, softCollisionMap);
|
|
1037
|
+
let j = softCollisionMap.length;
|
|
1038
|
+
|
|
1039
|
+
while (j--) {
|
|
1040
|
+
const
|
|
1041
|
+
otherCollisionType = softCollisionMap[j],
|
|
1042
|
+
otherEntities = againstGrid[otherCollisionType];
|
|
1043
|
+
|
|
1044
|
+
if (otherEntities) {
|
|
1045
|
+
let k = otherEntities.length;
|
|
1046
|
+
|
|
1047
|
+
while (k--) {
|
|
1048
|
+
const
|
|
1049
|
+
otherEntity = otherEntities[k];
|
|
1050
|
+
|
|
1051
|
+
if ((otherEntity !== ent) && (ent.getAABB(collisionType).collides(otherEntity.getAABB(otherCollisionType)))) {
|
|
1052
|
+
const
|
|
1053
|
+
shapes = ent.getShapes(collisionType),
|
|
1054
|
+
otherShapes = otherEntity.getShapes(otherCollisionType);
|
|
1055
|
+
let collisionFound = false,
|
|
1056
|
+
l = shapes.length;
|
|
1057
|
+
|
|
1058
|
+
while (l--) {
|
|
1059
|
+
let m = otherShapes.length;
|
|
1060
|
+
|
|
1061
|
+
while (m--) {
|
|
1062
|
+
if (shapes[l].collides(otherShapes[m])) {
|
|
1063
|
+
//TML - We're only reporting the first shape we hit even though there may be multiple that we could be hitting.
|
|
1064
|
+
message.entity = otherEntity;
|
|
1065
|
+
message.target = ent;
|
|
1066
|
+
message.type = otherCollisionType;
|
|
1067
|
+
message.myType = collisionType;
|
|
1068
|
+
message.shape = otherShapes[m];
|
|
1069
|
+
message.hitType = 'soft';
|
|
1070
|
+
|
|
1071
|
+
callback(message);
|
|
1072
|
+
|
|
1073
|
+
collisionFound = true;
|
|
1074
|
+
break;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
if (collisionFound) {
|
|
1078
|
+
break;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
arrayCache.recycle(otherEntities);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (terrains.length) {
|
|
1087
|
+
//Do our sweep check against the tiles and add potentially colliding shapes to our list.
|
|
1088
|
+
let l = 0;
|
|
1089
|
+
|
|
1090
|
+
for (l = 0; l < terrains.length; l++) {
|
|
1091
|
+
//Sending the same AABB twice because we don't do sweep or jumpThrough checks with soft collision.
|
|
1092
|
+
const entAABB = ent.getAABB(collisionType),
|
|
1093
|
+
otherShapes = terrains[l].getTileShapes(entAABB, entAABB, otherCollisionType);
|
|
1094
|
+
let k = otherShapes.length;
|
|
1095
|
+
|
|
1096
|
+
while (k--) {
|
|
1097
|
+
message.entity = terrains[l];
|
|
1098
|
+
message.target = ent;
|
|
1099
|
+
message.type = otherCollisionType;
|
|
1100
|
+
message.myType = collisionType;
|
|
1101
|
+
message.shape = otherShapes[k];
|
|
1102
|
+
message.hitType = 'soft';
|
|
1103
|
+
|
|
1104
|
+
callback(message);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
againstGrid.recycle();
|
|
1111
|
+
}
|
|
1112
|
+
},
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
checkShapeForCollisions: function (shape, softCollisionMap, callback) {
|
|
1116
|
+
const
|
|
1117
|
+
againstGrid = this.getAgainstGrid(null, shape.getAABB(), softCollisionMap),
|
|
1118
|
+
message = triggerMessage;
|
|
1119
|
+
let j = softCollisionMap.length;
|
|
1120
|
+
|
|
1121
|
+
message.x = 0;
|
|
1122
|
+
message.y = 0;
|
|
1123
|
+
|
|
1124
|
+
while (j--) {
|
|
1125
|
+
const
|
|
1126
|
+
otherCollisionType = softCollisionMap[j],
|
|
1127
|
+
otherEntities = againstGrid[otherCollisionType];
|
|
1128
|
+
|
|
1129
|
+
if (otherEntities) {
|
|
1130
|
+
let k = otherEntities.length;
|
|
1131
|
+
|
|
1132
|
+
while (k--) {
|
|
1133
|
+
const
|
|
1134
|
+
otherEntity = otherEntities[k];
|
|
1135
|
+
|
|
1136
|
+
if ((shape.getAABB().collides(otherEntity.getAABB(otherCollisionType)))) {
|
|
1137
|
+
const
|
|
1138
|
+
otherShapes = otherEntity.getShapes(otherCollisionType);
|
|
1139
|
+
let m = otherShapes.length;
|
|
1140
|
+
|
|
1141
|
+
while (m--) {
|
|
1142
|
+
if (shape.collides(otherShapes[m])) {
|
|
1143
|
+
//TML - We're only reporting the first shape we hit even though there may be multiple that we could be hitting.
|
|
1144
|
+
message.entity = otherEntity;
|
|
1145
|
+
message.target = null;
|
|
1146
|
+
message.type = otherCollisionType;
|
|
1147
|
+
message.myType = '';
|
|
1148
|
+
message.shape = otherShapes[m];
|
|
1149
|
+
message.hitType = 'soft';
|
|
1150
|
+
|
|
1151
|
+
callback(message);
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
arrayCache.recycle(otherEntities);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
againstGrid.recycle();
|
|
1161
|
+
},
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
checkPointForCollisions: function (x, y, collisions, callback) {
|
|
1165
|
+
const
|
|
1166
|
+
gb = this.gridBits,
|
|
1167
|
+
againstGrid = this.againstGrid[getBucketId(x, y, gb)],
|
|
1168
|
+
message = triggerMessage;
|
|
1169
|
+
let j = collisions.length;
|
|
1170
|
+
|
|
1171
|
+
message.x = 0;
|
|
1172
|
+
message.y = 0;
|
|
1173
|
+
|
|
1174
|
+
if (!againstGrid) {
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
while (j--) {
|
|
1179
|
+
const
|
|
1180
|
+
otherCollisionType = collisions[j],
|
|
1181
|
+
otherEntities = againstGrid.get(otherCollisionType);
|
|
1182
|
+
|
|
1183
|
+
if (otherEntities) {
|
|
1184
|
+
let k = otherEntities.length;
|
|
1185
|
+
|
|
1186
|
+
while (k--) {
|
|
1187
|
+
const
|
|
1188
|
+
otherEntity = otherEntities[k];
|
|
1189
|
+
|
|
1190
|
+
if (otherEntity.getAABB(otherCollisionType).containsPoint(x, y)) {
|
|
1191
|
+
const
|
|
1192
|
+
otherShapes = otherEntity.getShapes(otherCollisionType);
|
|
1193
|
+
let m = otherShapes.length;
|
|
1194
|
+
|
|
1195
|
+
while (m--) {
|
|
1196
|
+
if (otherShapes[m].containsPoint(x, y)) {
|
|
1197
|
+
//TML - We're only reporting the first shape we hit even though there may be multiple that we could be hitting.
|
|
1198
|
+
message.entity = otherEntity;
|
|
1199
|
+
message.target = null;
|
|
1200
|
+
message.type = otherCollisionType;
|
|
1201
|
+
message.myType = '';
|
|
1202
|
+
message.shape = otherShapes[m];
|
|
1203
|
+
message.hitType = 'soft';
|
|
1204
|
+
|
|
1205
|
+
callback(message);
|
|
1206
|
+
|
|
1207
|
+
break;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
},
|
|
1215
|
+
|
|
1216
|
+
destroy: function () {
|
|
1217
|
+
const
|
|
1218
|
+
ag = this.againstGrid,
|
|
1219
|
+
keys = Object.keys(ag),
|
|
1220
|
+
{length} = keys;
|
|
1221
|
+
|
|
1222
|
+
arrayCache.recycle(this.groupsLive);
|
|
1223
|
+
arrayCache.recycle(this.nonColliders);
|
|
1224
|
+
arrayCache.recycle(this.allEntitiesLive);
|
|
1225
|
+
arrayCache.recycle(this.softEntitiesLive);
|
|
1226
|
+
arrayCache.recycle(this.solidEntitiesLive);
|
|
1227
|
+
this.relocationMessage.position.recycle();
|
|
1228
|
+
this.relocationMessage.recycle();
|
|
1229
|
+
|
|
1230
|
+
for (let i = 0; i < length; i++) {
|
|
1231
|
+
const
|
|
1232
|
+
data = ag[keys[i]],
|
|
1233
|
+
dataKeys = data.keys;
|
|
1234
|
+
let j = dataKeys.length;
|
|
1235
|
+
|
|
1236
|
+
while (j--) {
|
|
1237
|
+
arrayCache.recycle(data.get(dataKeys[j]));
|
|
1238
|
+
}
|
|
1239
|
+
data.recycle();
|
|
1240
|
+
}
|
|
1241
|
+
ag.recycle();
|
|
1242
|
+
this.againstGrid = null;
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1245
|
+
|
|
1246
|
+
publicMethods: {
|
|
1247
|
+
/**
|
|
1248
|
+
* This method returns an object containing world entities.
|
|
1249
|
+
*
|
|
1250
|
+
* @method platypus.components.HandlerCollision#getWorldEntities
|
|
1251
|
+
* @return {Array} A list of all world collision entities.
|
|
1252
|
+
*/
|
|
1253
|
+
getWorldEntities: function () {
|
|
1254
|
+
return this.allEntitiesLive;
|
|
1255
|
+
},
|
|
1256
|
+
|
|
1257
|
+
/**
|
|
1258
|
+
* This method returns an array of entities representing the collision maps of the world.
|
|
1259
|
+
*
|
|
1260
|
+
* @method platypus.components.HandlerCollision#getWorldTerrain
|
|
1261
|
+
* @return {Array.<platypus.Entity>} An array of entities describing the collision maps of the world. This entity typically includes a `CollisionTiles` component.
|
|
1262
|
+
*/
|
|
1263
|
+
getWorldTerrain: function () {
|
|
1264
|
+
return this.terrains;
|
|
1265
|
+
},
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* This method returns a list of collision objects describing soft collisions between an entity and a list of other entities.
|
|
1269
|
+
*
|
|
1270
|
+
* @method platypus.components.HandlerCollision#getEntityCollisions
|
|
1271
|
+
* @param entity {Entity} The entity to test against the world.
|
|
1272
|
+
* @return collisions {Array} This is a list of collision objects describing the soft collisions.
|
|
1273
|
+
*/
|
|
1274
|
+
getEntityCollisions: function (entity) {
|
|
1275
|
+
const
|
|
1276
|
+
collisions = arrayCache.setUp();
|
|
1277
|
+
|
|
1278
|
+
this.checkEntityForSoftCollisions(entity, (collision) => collisions.push(Data.setUp(collision)));
|
|
1279
|
+
|
|
1280
|
+
return collisions;
|
|
1281
|
+
},
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* This method returns a list of collision objects describing collisions between a shape and a list of other entities.
|
|
1285
|
+
*
|
|
1286
|
+
* @method platypus.components.HandlerCollision#getShapeCollisions
|
|
1287
|
+
* @param shape {CollisionShape} The shape to check for collisions.
|
|
1288
|
+
* @param collisionTypes {String[]} The collision types to check against.
|
|
1289
|
+
* @return collisions {Array} This is a list of collision objects describing the soft collisions.
|
|
1290
|
+
*/
|
|
1291
|
+
getShapeCollisions: function (shape, collisionTypes) {
|
|
1292
|
+
const
|
|
1293
|
+
collisions = arrayCache.setUp();
|
|
1294
|
+
|
|
1295
|
+
this.checkShapeForCollisions(shape, collisionTypes, (collision) => collisions.push(Data.setUp(collision)));
|
|
1296
|
+
|
|
1297
|
+
return collisions;
|
|
1298
|
+
},
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* This method returns a list of collision objects describing collisions between a point and a list of other entities.
|
|
1302
|
+
*
|
|
1303
|
+
* @method platypus.components.HandlerCollision#getPointCollisions
|
|
1304
|
+
* @param x {number} The x-axis value.
|
|
1305
|
+
* @param y {number} The y-axis value.
|
|
1306
|
+
* @param collisionTypes {String[]} The collision types to check against.
|
|
1307
|
+
* @return collisions {Array} This is a list of collision objects describing the soft collisions.
|
|
1308
|
+
*/
|
|
1309
|
+
getPointCollisions: function (x, y, collisionTypes) {
|
|
1310
|
+
const
|
|
1311
|
+
collisions = arrayCache.setUp();
|
|
1312
|
+
|
|
1313
|
+
this.checkPointForCollisions(x, y, collisionTypes, (collision) => collisions.push(Data.setUp(collision)));
|
|
1314
|
+
|
|
1315
|
+
return collisions;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
});
|