@rpgjs/common 3.3.2 → 4.0.0-beta.1
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/LICENSE +19 -0
- package/lib/AbstractObject.d.ts +3 -2
- package/lib/AbstractObject.js +296 -323
- package/lib/AbstractObject.js.map +1 -1
- package/lib/Color.js +1 -5
- package/lib/Color.js.map +1 -1
- package/lib/Event.js +2 -6
- package/lib/Event.js.map +1 -1
- package/lib/EventEmitter.js +3 -7
- package/lib/EventEmitter.js.map +1 -1
- package/lib/Game.js +73 -85
- package/lib/Game.js.map +1 -1
- package/lib/Hit.js +21 -28
- package/lib/Hit.js.map +1 -1
- package/lib/Logger.js +2 -7
- package/lib/Logger.js.map +1 -1
- package/lib/Map.d.ts +1 -0
- package/lib/Map.js +29 -53
- package/lib/Map.js.map +1 -1
- package/lib/Module.d.ts +2 -2
- package/lib/Module.js +84 -97
- package/lib/Module.js.map +1 -1
- package/lib/Player.js +3 -7
- package/lib/Player.js.map +1 -1
- package/lib/Plugin.d.ts +4 -3
- package/lib/Plugin.js +14 -14
- package/lib/Plugin.js.map +1 -1
- package/lib/Scheduler.js +14 -21
- package/lib/Scheduler.js.map +1 -1
- package/lib/Shape.d.ts +1 -1
- package/lib/Shape.js +39 -52
- package/lib/Shape.js.map +1 -1
- package/lib/Utils.d.ts +4 -1
- package/lib/Utils.js +38 -53
- package/lib/Utils.js.map +1 -1
- package/lib/Vector2d.js +3 -8
- package/lib/Vector2d.js.map +1 -1
- package/lib/VirtualGrid.d.ts +1 -1
- package/lib/VirtualGrid.js +5 -12
- package/lib/VirtualGrid.js.map +1 -1
- package/lib/Worker.js +2 -10
- package/lib/Worker.js.map +1 -1
- package/lib/WorldMaps.d.ts +3 -1
- package/lib/WorldMaps.js +29 -15
- package/lib/WorldMaps.js.map +1 -1
- package/lib/gui/PrebuiltGui.js +2 -5
- package/lib/gui/PrebuiltGui.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +23 -69
- package/lib/index.js.map +1 -1
- package/lib/transports/io.js +5 -9
- package/lib/transports/io.js.map +1 -1
- package/lib/workers/move.js +26 -42
- package/lib/workers/move.js.map +1 -1
- package/package.json +7 -7
package/lib/AbstractObject.js
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.AbstractObject = void 0;
|
|
16
|
-
const Utils_1 = require("./Utils");
|
|
17
|
-
const Hit_1 = require("./Hit");
|
|
18
|
-
const Shape_1 = require("./Shape");
|
|
19
|
-
const sat_1 = __importDefault(require("sat"));
|
|
20
|
-
const Map_1 = require("./Map");
|
|
21
|
-
const Plugin_1 = require("./Plugin");
|
|
22
|
-
const Game_1 = require("./Game");
|
|
23
|
-
const Vector2d_1 = require("./Vector2d");
|
|
24
|
-
const types_1 = require("@rpgjs/types");
|
|
25
|
-
const rxjs_1 = require("rxjs");
|
|
1
|
+
import { intersection, generateUID, toRadians, isInstanceOf } from './Utils';
|
|
2
|
+
import { Hit, HitType } from './Hit';
|
|
3
|
+
import { RpgShape } from './Shape';
|
|
4
|
+
import SAT from 'sat';
|
|
5
|
+
import { RpgCommonMap } from './Map';
|
|
6
|
+
import { RpgPlugin, HookServer } from './Plugin';
|
|
7
|
+
import { GameSide } from './Game';
|
|
8
|
+
import { Vector2d, Vector2dZero } from './Vector2d';
|
|
9
|
+
import { Behavior, Direction, MoveClientMode, PlayerType } from '@rpgjs/types';
|
|
10
|
+
import { from, map, mergeMap, Subject, tap, takeUntil } from 'rxjs';
|
|
26
11
|
const ACTIONS = { IDLE: 0, RUN: 1, ACTION: 2 };
|
|
27
|
-
class AbstractObject {
|
|
12
|
+
export class AbstractObject {
|
|
13
|
+
static get ACTIONS() {
|
|
14
|
+
return ACTIONS;
|
|
15
|
+
}
|
|
28
16
|
constructor(gameEngine, playerId) {
|
|
29
17
|
this.gameEngine = gameEngine;
|
|
30
18
|
this.playerId = playerId;
|
|
@@ -36,22 +24,21 @@ class AbstractObject {
|
|
|
36
24
|
Properties for move mode
|
|
37
25
|
*/
|
|
38
26
|
this.checkCollision = true;
|
|
39
|
-
this.clientModeMove =
|
|
40
|
-
this.behavior =
|
|
27
|
+
this.clientModeMove = MoveClientMode.ByDirection;
|
|
28
|
+
this.behavior = Behavior.Direction;
|
|
41
29
|
this.inShapes = {};
|
|
42
30
|
this.disableVirtualGrid = false;
|
|
43
31
|
this.shapes = [];
|
|
44
32
|
this.collisionWith = [];
|
|
45
33
|
this._collisionWithTiles = [];
|
|
46
34
|
this._collisionWithShapes = [];
|
|
47
|
-
this.destroyMove$ = new
|
|
48
|
-
|
|
35
|
+
this.destroyMove$ = new Subject();
|
|
36
|
+
// notifier for destroy
|
|
37
|
+
this._destroy$ = new Subject();
|
|
38
|
+
this._hitboxPos = new SAT.Vector(0, 0);
|
|
49
39
|
this.setHitbox(this.width, this.height);
|
|
50
40
|
this.position = { x: 0, y: 0, z: 0 };
|
|
51
41
|
}
|
|
52
|
-
static get ACTIONS() {
|
|
53
|
-
return ACTIONS;
|
|
54
|
-
}
|
|
55
42
|
get id() {
|
|
56
43
|
return this.playerId;
|
|
57
44
|
}
|
|
@@ -65,10 +52,10 @@ class AbstractObject {
|
|
|
65
52
|
}
|
|
66
53
|
}
|
|
67
54
|
get canMove() {
|
|
68
|
-
return this.clientModeMove ==
|
|
55
|
+
return this.clientModeMove == MoveClientMode.ByDirection;
|
|
69
56
|
}
|
|
70
57
|
set canMove(val) {
|
|
71
|
-
this.clientModeMove = val ?
|
|
58
|
+
this.clientModeMove = val ? MoveClientMode.ByDirection : MoveClientMode.Disabled;
|
|
72
59
|
}
|
|
73
60
|
/**
|
|
74
61
|
* Get/Set position x, y and z of player
|
|
@@ -81,8 +68,8 @@ class AbstractObject {
|
|
|
81
68
|
*/
|
|
82
69
|
set position(val) {
|
|
83
70
|
const { x, y, z } = val;
|
|
84
|
-
if (!
|
|
85
|
-
val = new
|
|
71
|
+
if (!isInstanceOf(val, Vector2d)) {
|
|
72
|
+
val = new Vector2d(x, y, z);
|
|
86
73
|
}
|
|
87
74
|
this._hitboxPos.x = x;
|
|
88
75
|
this._hitboxPos.y = y;
|
|
@@ -125,10 +112,10 @@ class AbstractObject {
|
|
|
125
112
|
}
|
|
126
113
|
/** @internal */
|
|
127
114
|
get mapInstance() {
|
|
128
|
-
if (this.gameEngine.side ==
|
|
129
|
-
return
|
|
115
|
+
if (this.gameEngine.side == GameSide.Client) {
|
|
116
|
+
return RpgCommonMap.bufferClient.get(this.map);
|
|
130
117
|
}
|
|
131
|
-
return
|
|
118
|
+
return RpgCommonMap.buffer.get(this.map);
|
|
132
119
|
}
|
|
133
120
|
/**
|
|
134
121
|
*
|
|
@@ -206,7 +193,7 @@ class AbstractObject {
|
|
|
206
193
|
this.width = obj.width;
|
|
207
194
|
this.height = obj.height;
|
|
208
195
|
if (obj.hitbox) {
|
|
209
|
-
this.hitbox = new
|
|
196
|
+
this.hitbox = new SAT.Box(this._hitboxPos, obj.hitbox.width, obj.hitbox.height);
|
|
210
197
|
}
|
|
211
198
|
}
|
|
212
199
|
/**
|
|
@@ -229,7 +216,7 @@ class AbstractObject {
|
|
|
229
216
|
this.width = map.tileWidth;
|
|
230
217
|
this.height = map.tileHeight;
|
|
231
218
|
}
|
|
232
|
-
this.hitbox = new
|
|
219
|
+
this.hitbox = new SAT.Box(this._hitboxPos, width, height);
|
|
233
220
|
this.wHitbox = width;
|
|
234
221
|
this.hHitbox = height;
|
|
235
222
|
this.updateInVirtualGrid();
|
|
@@ -248,7 +235,7 @@ class AbstractObject {
|
|
|
248
235
|
}
|
|
249
236
|
directionToAngle(direction) {
|
|
250
237
|
const angle = (direction < 2 ? +direction + 2 : direction - 2) * 90;
|
|
251
|
-
return
|
|
238
|
+
return toRadians(angle);
|
|
252
239
|
}
|
|
253
240
|
/** @internal */
|
|
254
241
|
defineNextPosition(direction, deltaTimeInt) {
|
|
@@ -257,7 +244,7 @@ class AbstractObject {
|
|
|
257
244
|
return this.position[prop] + this.speed * deltaTimeInt
|
|
258
245
|
* (Math.round(Math[prop == 'x' ? 'cos' : 'sin'](angle) * 100) / 100);
|
|
259
246
|
};
|
|
260
|
-
return new
|
|
247
|
+
return new Vector2d(~~computePosition('x'), ~~computePosition('y'), ~~this.position.z);
|
|
261
248
|
}
|
|
262
249
|
/** @internal */
|
|
263
250
|
setPosition({ x, y, tileX, tileY }, move = true) {
|
|
@@ -272,30 +259,28 @@ class AbstractObject {
|
|
|
272
259
|
this.posY = tileY * tileHeight;
|
|
273
260
|
}
|
|
274
261
|
/** @internal */
|
|
275
|
-
triggerCollisionWith(type) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (
|
|
285
|
-
|
|
286
|
-
yield collisionWith.execMethod('onAction', [this]);
|
|
287
|
-
}
|
|
288
|
-
else if ('onPlayerTouch' in collisionWith)
|
|
289
|
-
yield collisionWith.execMethod('onPlayerTouch', [this]);
|
|
262
|
+
async triggerCollisionWith(type) {
|
|
263
|
+
for (let collisionWith of this.collisionWith) {
|
|
264
|
+
if (collisionWith instanceof RpgShape) {
|
|
265
|
+
const goMap = collisionWith.getProperty('go-map');
|
|
266
|
+
if (goMap && 'changeMap' in this)
|
|
267
|
+
await this.changeMap(goMap);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
if (type == AbstractObject.ACTIONS.ACTION) {
|
|
271
|
+
if ('onAction' in collisionWith)
|
|
272
|
+
await collisionWith.execMethod('onAction', [this]);
|
|
290
273
|
}
|
|
274
|
+
else if ('onPlayerTouch' in collisionWith)
|
|
275
|
+
await collisionWith.execMethod('onPlayerTouch', [this]);
|
|
291
276
|
}
|
|
292
|
-
}
|
|
277
|
+
}
|
|
293
278
|
}
|
|
294
279
|
/** @internal */
|
|
295
280
|
zCollision(other) {
|
|
296
281
|
const z = this.position.z;
|
|
297
282
|
const otherZ = other.position.z;
|
|
298
|
-
return
|
|
283
|
+
return intersection([z, z + this.height], [otherZ, otherZ + other.height]);
|
|
299
284
|
}
|
|
300
285
|
/** @internal */
|
|
301
286
|
moveByDirection(direction, deltaTimeInt) {
|
|
@@ -348,258 +333,248 @@ class AbstractObject {
|
|
|
348
333
|
const map = this.mapInstance;
|
|
349
334
|
return map.getTile(hitbox || this.hitbox, x, y, [z, this.height]);
|
|
350
335
|
}
|
|
351
|
-
collisionObjects(playerSizeBox, hitbox, triggers) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (event.
|
|
382
|
-
if (!(event.throughOtherPlayer || this.throughOtherPlayer)) {
|
|
383
|
-
boolFound = true;
|
|
384
|
-
if (!(triggers === null || triggers === void 0 ? void 0 : triggers.allSearch))
|
|
385
|
-
return true;
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
throughOtherPlayer = true;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
if (!throughOtherPlayer && (!(event.through || this.through))) {
|
|
336
|
+
async collisionObjects(playerSizeBox, hitbox, triggers) {
|
|
337
|
+
const map = this.mapInstance;
|
|
338
|
+
if (!map)
|
|
339
|
+
return true;
|
|
340
|
+
const events = this.gameEngine.world.getObjectsOfGroup(this.map, this);
|
|
341
|
+
const objects = map.grid.getObjectsByBox(playerSizeBox);
|
|
342
|
+
let boolFound = false;
|
|
343
|
+
for (let objectId of objects) {
|
|
344
|
+
// client side: read "object" propertie
|
|
345
|
+
if (!events[objectId])
|
|
346
|
+
continue;
|
|
347
|
+
const event = events[objectId]['object'] || events[objectId];
|
|
348
|
+
if (event.id == this.id)
|
|
349
|
+
continue;
|
|
350
|
+
if (!this.zCollision(event))
|
|
351
|
+
continue;
|
|
352
|
+
const collided = Hit.testPolyCollision(HitType.Box, hitbox, event.hitbox);
|
|
353
|
+
for (let shape of this.shapes) {
|
|
354
|
+
await this.collisionWithShape(shape, event);
|
|
355
|
+
}
|
|
356
|
+
for (let shape of event.shapes) {
|
|
357
|
+
await event.collisionWithShape(shape, this);
|
|
358
|
+
}
|
|
359
|
+
if (triggers?.near)
|
|
360
|
+
triggers.near(event);
|
|
361
|
+
if (collided) {
|
|
362
|
+
this.collisionWith.push(event);
|
|
363
|
+
this.triggerCollisionWith();
|
|
364
|
+
let throughOtherPlayer = false;
|
|
365
|
+
if (event.type == PlayerType.Player && this.type == PlayerType.Player) {
|
|
366
|
+
if (!(event.throughOtherPlayer || this.throughOtherPlayer)) {
|
|
392
367
|
boolFound = true;
|
|
393
|
-
if (!
|
|
368
|
+
if (!triggers?.allSearch)
|
|
394
369
|
return true;
|
|
395
370
|
}
|
|
371
|
+
else {
|
|
372
|
+
throughOtherPlayer = true;
|
|
373
|
+
}
|
|
396
374
|
}
|
|
397
|
-
if (
|
|
398
|
-
|
|
399
|
-
|
|
375
|
+
if (!throughOtherPlayer && (!(event.through || this.through))) {
|
|
376
|
+
boolFound = true;
|
|
377
|
+
if (!triggers?.allSearch)
|
|
378
|
+
return true;
|
|
400
379
|
}
|
|
401
380
|
}
|
|
402
|
-
|
|
403
|
-
|
|
381
|
+
if (boolFound) {
|
|
382
|
+
if (triggers?.collision)
|
|
383
|
+
triggers.collision(event);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return boolFound;
|
|
404
387
|
}
|
|
405
388
|
/** @internal */
|
|
406
|
-
collisionWithShape(shape, player, nextPosition) {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
389
|
+
async collisionWithShape(shape, player, nextPosition) {
|
|
390
|
+
const collision = shape.hasCollision;
|
|
391
|
+
const z = shape.z;
|
|
392
|
+
if (shape.isShapePosition())
|
|
393
|
+
return false;
|
|
394
|
+
if (z !== undefined && !this.zCollision({
|
|
395
|
+
position: { z },
|
|
396
|
+
height: this.mapInstance.zTileHeight
|
|
397
|
+
})) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
let position;
|
|
401
|
+
let { hitbox } = player;
|
|
402
|
+
if (nextPosition) {
|
|
403
|
+
position = nextPosition.copy();
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
position = player.position.copy();
|
|
407
|
+
}
|
|
408
|
+
const hitboxObj = Hit.createObjectHitbox(position.x, position.y, position.z, hitbox.w, hitbox.h);
|
|
409
|
+
let collided = Hit.testPolyCollision(shape.type, hitboxObj, shape.hitbox);
|
|
410
|
+
const playerPositionSaved = player.position.copy();
|
|
411
|
+
// Position can changed after enter or exit shape. So, we need to verify if position changed and update if z is changed
|
|
412
|
+
// If X or Y changed, we need to return true, it means that stop the current movement, and apply the new position
|
|
413
|
+
const verifyIfPositionChanged = () => {
|
|
414
|
+
if (this.position.z != playerPositionSaved.z && nextPosition) {
|
|
415
|
+
nextPosition.z = this.position.z;
|
|
425
416
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const playerPositionSaved = player.position.copy();
|
|
429
|
-
// Position can changed after enter or exit shape. So, we need to verify if position changed and update if z is changed
|
|
430
|
-
// If X or Y changed, we need to return true, it means that stop the current movement, and apply the new position
|
|
431
|
-
const verifyIfPositionChanged = () => {
|
|
432
|
-
if (this.position.z != playerPositionSaved.z && nextPosition) {
|
|
433
|
-
nextPosition.z = this.position.z;
|
|
434
|
-
}
|
|
435
|
-
if (this.position.x != playerPositionSaved.x || this.position.y != playerPositionSaved.y) {
|
|
436
|
-
return true;
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
if (collided) {
|
|
440
|
-
this._collisionWithShapes.push(shape);
|
|
441
|
-
// TODO: in shape after map load
|
|
442
|
-
if (!collision)
|
|
443
|
-
yield shape.in(this);
|
|
444
|
-
if (verifyIfPositionChanged() === true)
|
|
445
|
-
return true;
|
|
446
|
-
this.triggerCollisionWith();
|
|
447
|
-
if (collision)
|
|
448
|
-
return true;
|
|
417
|
+
if (this.position.x != playerPositionSaved.x || this.position.y != playerPositionSaved.y) {
|
|
418
|
+
return true;
|
|
449
419
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
420
|
+
};
|
|
421
|
+
if (collided) {
|
|
422
|
+
this._collisionWithShapes.push(shape);
|
|
423
|
+
// TODO: in shape after map load
|
|
424
|
+
if (!collision)
|
|
425
|
+
await shape.in(this);
|
|
426
|
+
if (verifyIfPositionChanged() === true)
|
|
427
|
+
return true;
|
|
428
|
+
this.triggerCollisionWith();
|
|
429
|
+
if (collision)
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
await shape.out(this);
|
|
434
|
+
if (verifyIfPositionChanged() === true)
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
async collisionShapes(playerSizeBox, nextPosition, triggers) {
|
|
440
|
+
const map = this.mapInstance;
|
|
441
|
+
if (!map)
|
|
442
|
+
return false;
|
|
443
|
+
const shapes = this.gameEngine.world.getShapesOfGroup(this.map);
|
|
444
|
+
const shapesInGrid = this.gameEngine.side == GameSide.Client
|
|
445
|
+
? new Set(Object.keys(shapes))
|
|
446
|
+
: map.gridShapes.getObjectsByBox(playerSizeBox);
|
|
447
|
+
let boolFound = false;
|
|
448
|
+
for (let shapeId of shapesInGrid) {
|
|
449
|
+
const shape = shapes[shapeId]['object'] || shapes[shapeId];
|
|
450
|
+
if (triggers?.near)
|
|
451
|
+
triggers.near(shape);
|
|
452
|
+
const bool = await this.collisionWithShape(shape, this, nextPosition);
|
|
453
|
+
if (bool) {
|
|
454
|
+
if (triggers?.collision)
|
|
455
|
+
triggers.collision(shape);
|
|
456
|
+
boolFound = true;
|
|
457
|
+
if (!triggers?.allSearch)
|
|
453
458
|
return true;
|
|
454
459
|
}
|
|
455
|
-
|
|
456
|
-
|
|
460
|
+
}
|
|
461
|
+
return boolFound;
|
|
457
462
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
if (!(triggers === null || triggers === void 0 ? void 0 : triggers.allSearch))
|
|
478
|
-
return true;
|
|
479
|
-
}
|
|
463
|
+
async computeNextPositionByTarget(nextPosition, target) {
|
|
464
|
+
const pullDistance = target.distanceWith(nextPosition);
|
|
465
|
+
if (pullDistance <= this.speed) {
|
|
466
|
+
return nextPosition.set(target);
|
|
467
|
+
}
|
|
468
|
+
const pull = (target.copy().subtract(nextPosition)).multiply((1 / pullDistance));
|
|
469
|
+
const totalPush = new Vector2dZero();
|
|
470
|
+
let contenders = 0;
|
|
471
|
+
const hitbox = Hit.createObjectHitbox(nextPosition.x, nextPosition.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
472
|
+
const createObstacle = function (x, y, radius) {
|
|
473
|
+
const obstacle = new Vector2d(x, y);
|
|
474
|
+
let push = nextPosition.copy().subtract(obstacle);
|
|
475
|
+
let distance = (nextPosition.distanceWith(obstacle) - radius) - radius;
|
|
476
|
+
if (distance < radius * 2 * 10) {
|
|
477
|
+
++contenders;
|
|
478
|
+
if (distance < 0.0001)
|
|
479
|
+
distance = 0.0001; // avoid div by 0
|
|
480
|
+
let weight = 1 / distance;
|
|
481
|
+
totalPush.add(push.multiply(weight));
|
|
480
482
|
}
|
|
481
|
-
return
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
483
|
+
return obstacle;
|
|
484
|
+
};
|
|
485
|
+
const area = this.mapInstance.tileheight * 2;
|
|
486
|
+
this.mapInstance.gridTiles.getCells({
|
|
487
|
+
minX: nextPosition.x - area,
|
|
488
|
+
maxX: nextPosition.x + area,
|
|
489
|
+
minY: nextPosition.y - area,
|
|
490
|
+
maxY: nextPosition.y + area
|
|
491
|
+
}, (index) => {
|
|
492
|
+
if (index < 0)
|
|
493
|
+
return;
|
|
494
|
+
const pos = this.mapInstance.getTilePosition(index);
|
|
495
|
+
const hitbox = Hit.createObjectHitbox(pos.x, pos.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
496
|
+
const radius = this.mapInstance.tilewidth / 2;
|
|
497
|
+
const tile = this.getTile(pos.x, pos.y, nextPosition.z, hitbox);
|
|
498
|
+
if (tile.hasCollision) {
|
|
499
|
+
createObstacle(pos.x, pos.y, radius);
|
|
489
500
|
}
|
|
490
|
-
const pull = (target.copy().subtract(nextPosition)).multiply((1 / pullDistance));
|
|
491
|
-
const totalPush = new Vector2d_1.Vector2dZero();
|
|
492
|
-
let contenders = 0;
|
|
493
|
-
const hitbox = Hit_1.Hit.createObjectHitbox(nextPosition.x, nextPosition.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
494
|
-
const createObstacle = function (x, y, radius) {
|
|
495
|
-
const obstacle = new Vector2d_1.Vector2d(x, y);
|
|
496
|
-
let push = nextPosition.copy().subtract(obstacle);
|
|
497
|
-
let distance = (nextPosition.distanceWith(obstacle) - radius) - radius;
|
|
498
|
-
if (distance < radius * 2 * 10) {
|
|
499
|
-
++contenders;
|
|
500
|
-
if (distance < 0.0001)
|
|
501
|
-
distance = 0.0001; // avoid div by 0
|
|
502
|
-
let weight = 1 / distance;
|
|
503
|
-
totalPush.add(push.multiply(weight));
|
|
504
|
-
}
|
|
505
|
-
return obstacle;
|
|
506
|
-
};
|
|
507
|
-
const area = this.mapInstance.tileheight * 2;
|
|
508
|
-
this.mapInstance.gridTiles.getCells({
|
|
509
|
-
minX: nextPosition.x - area,
|
|
510
|
-
maxX: nextPosition.x + area,
|
|
511
|
-
minY: nextPosition.y - area,
|
|
512
|
-
maxY: nextPosition.y + area
|
|
513
|
-
}, (index) => {
|
|
514
|
-
if (index < 0)
|
|
515
|
-
return;
|
|
516
|
-
const pos = this.mapInstance.getTilePosition(index);
|
|
517
|
-
const hitbox = Hit_1.Hit.createObjectHitbox(pos.x, pos.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
518
|
-
const radius = this.mapInstance.tilewidth / 2;
|
|
519
|
-
const tile = this.getTile(pos.x, pos.y, nextPosition.z, hitbox);
|
|
520
|
-
if (tile.hasCollision) {
|
|
521
|
-
createObstacle(pos.x, pos.y, radius);
|
|
522
|
-
}
|
|
523
|
-
});
|
|
524
|
-
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
525
|
-
yield this.collisionObjects(playerSizeBox, hitbox, {
|
|
526
|
-
collision: (event) => {
|
|
527
|
-
const { x, y } = event.position;
|
|
528
|
-
createObstacle(x, y, event.hitbox.w);
|
|
529
|
-
},
|
|
530
|
-
allSearch: true
|
|
531
|
-
});
|
|
532
|
-
yield this.collisionShapes(playerSizeBox, nextPosition, {
|
|
533
|
-
collision: (shape) => {
|
|
534
|
-
const { x, y } = shape.position;
|
|
535
|
-
createObstacle(x, y, shape.hitbox.w);
|
|
536
|
-
},
|
|
537
|
-
allSearch: true
|
|
538
|
-
});
|
|
539
|
-
pull
|
|
540
|
-
.multiply(Math.max(1, 4 * contenders))
|
|
541
|
-
.add(totalPush)
|
|
542
|
-
.normalize();
|
|
543
|
-
return nextPosition.add(pull.multiply(this.speed));
|
|
544
501
|
});
|
|
502
|
+
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
503
|
+
await this.collisionObjects(playerSizeBox, hitbox, {
|
|
504
|
+
collision: (event) => {
|
|
505
|
+
const { x, y } = event.position;
|
|
506
|
+
createObstacle(x, y, event.hitbox.w);
|
|
507
|
+
},
|
|
508
|
+
allSearch: true
|
|
509
|
+
});
|
|
510
|
+
await this.collisionShapes(playerSizeBox, nextPosition, {
|
|
511
|
+
collision: (shape) => {
|
|
512
|
+
const { x, y } = shape.position;
|
|
513
|
+
createObstacle(x, y, shape.hitbox.w);
|
|
514
|
+
},
|
|
515
|
+
allSearch: true
|
|
516
|
+
});
|
|
517
|
+
pull
|
|
518
|
+
.multiply(Math.max(1, 4 * contenders))
|
|
519
|
+
.add(totalPush)
|
|
520
|
+
.normalize();
|
|
521
|
+
return nextPosition.add(pull.multiply(this.speed));
|
|
545
522
|
}
|
|
546
|
-
isCollided(nextPosition, options = {}) {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return true;
|
|
566
|
-
}
|
|
567
|
-
return false;
|
|
568
|
-
};
|
|
569
|
-
if (tileCollision(nextPosition.x, nextPosition.y) ||
|
|
570
|
-
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y) ||
|
|
571
|
-
tileCollision(nextPosition.x, nextPosition.y + this.hitbox.h) ||
|
|
572
|
-
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y + this.hitbox.h)) {
|
|
573
|
-
if (!options.allSearch)
|
|
574
|
-
return true;
|
|
575
|
-
else
|
|
576
|
-
collided = true;
|
|
577
|
-
}
|
|
578
|
-
if (this.autoChangeMap) {
|
|
579
|
-
const changeMap = yield this.autoChangeMap(nextPosition);
|
|
580
|
-
if (changeMap) {
|
|
581
|
-
return true;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
585
|
-
if (yield this.collisionObjects(playerSizeBox, hitbox, options)) {
|
|
586
|
-
if (!options.allSearch)
|
|
587
|
-
return true;
|
|
588
|
-
else
|
|
589
|
-
collided = true;
|
|
590
|
-
}
|
|
591
|
-
if (yield this.collisionShapes(playerSizeBox, nextPosition, options)) {
|
|
592
|
-
if (!options.allSearch)
|
|
593
|
-
return true;
|
|
594
|
-
else
|
|
595
|
-
collided = true;
|
|
523
|
+
async isCollided(nextPosition, options = {}) {
|
|
524
|
+
this.collisionWith = [];
|
|
525
|
+
this._collisionWithTiles = [];
|
|
526
|
+
const prevMapId = this.map;
|
|
527
|
+
const hitbox = Hit.createObjectHitbox(nextPosition.x, nextPosition.y, 0, this.hitbox.w, this.hitbox.h);
|
|
528
|
+
const boundingMap = this.mapInstance.boundingMap(nextPosition, this.hitbox);
|
|
529
|
+
let collided = false;
|
|
530
|
+
if (boundingMap?.bounding) {
|
|
531
|
+
this.position.set(nextPosition);
|
|
532
|
+
if (!options.allSearch)
|
|
533
|
+
return true;
|
|
534
|
+
else
|
|
535
|
+
collided = true;
|
|
536
|
+
}
|
|
537
|
+
const tileCollision = (x, y) => {
|
|
538
|
+
const tile = this.getTile(x, y, nextPosition.z, hitbox);
|
|
539
|
+
if (tile.hasCollision) {
|
|
540
|
+
this._collisionWithTiles.push(tile);
|
|
541
|
+
return true;
|
|
596
542
|
}
|
|
597
|
-
|
|
598
|
-
|
|
543
|
+
return false;
|
|
544
|
+
};
|
|
545
|
+
if (tileCollision(nextPosition.x, nextPosition.y) ||
|
|
546
|
+
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y) ||
|
|
547
|
+
tileCollision(nextPosition.x, nextPosition.y + this.hitbox.h) ||
|
|
548
|
+
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y + this.hitbox.h)) {
|
|
549
|
+
if (!options.allSearch)
|
|
550
|
+
return true;
|
|
551
|
+
else
|
|
552
|
+
collided = true;
|
|
553
|
+
}
|
|
554
|
+
if (this.autoChangeMap) {
|
|
555
|
+
const changeMap = await this.autoChangeMap(nextPosition);
|
|
556
|
+
if (changeMap) {
|
|
599
557
|
return true;
|
|
600
558
|
}
|
|
601
|
-
|
|
602
|
-
|
|
559
|
+
}
|
|
560
|
+
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
561
|
+
if (await this.collisionObjects(playerSizeBox, hitbox, options)) {
|
|
562
|
+
if (!options.allSearch)
|
|
563
|
+
return true;
|
|
564
|
+
else
|
|
565
|
+
collided = true;
|
|
566
|
+
}
|
|
567
|
+
if (await this.collisionShapes(playerSizeBox, nextPosition, options)) {
|
|
568
|
+
if (!options.allSearch)
|
|
569
|
+
return true;
|
|
570
|
+
else
|
|
571
|
+
collided = true;
|
|
572
|
+
}
|
|
573
|
+
// if there is a change of map after a move, the moves are not changed
|
|
574
|
+
if (prevMapId != this.map) {
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
return collided;
|
|
603
578
|
}
|
|
604
579
|
/**
|
|
605
580
|
* Attach a shape to the player (and allow interaction with it)
|
|
@@ -625,8 +600,11 @@ class AbstractObject {
|
|
|
625
600
|
* @memberof Player
|
|
626
601
|
*/
|
|
627
602
|
attachShape(obj) {
|
|
628
|
-
obj.name = (obj.name ||
|
|
629
|
-
const shape = new
|
|
603
|
+
obj.name = (obj.name || generateUID());
|
|
604
|
+
const shape = new RpgShape({
|
|
605
|
+
...obj,
|
|
606
|
+
fixEvent: this
|
|
607
|
+
});
|
|
630
608
|
this.shapes.push(shape);
|
|
631
609
|
return shape;
|
|
632
610
|
}
|
|
@@ -649,18 +627,18 @@ class AbstractObject {
|
|
|
649
627
|
const diff = Math.abs(x - nx) > Math.abs(y - ny);
|
|
650
628
|
if (diff) {
|
|
651
629
|
if (nx > x) {
|
|
652
|
-
this.changeDirection(
|
|
630
|
+
this.changeDirection(Direction.Right);
|
|
653
631
|
}
|
|
654
632
|
else {
|
|
655
|
-
this.changeDirection(
|
|
633
|
+
this.changeDirection(Direction.Left);
|
|
656
634
|
}
|
|
657
635
|
}
|
|
658
636
|
else {
|
|
659
637
|
if (ny > y) {
|
|
660
|
-
this.changeDirection(
|
|
638
|
+
this.changeDirection(Direction.Down);
|
|
661
639
|
}
|
|
662
640
|
else {
|
|
663
|
-
this.changeDirection(
|
|
641
|
+
this.changeDirection(Direction.Up);
|
|
664
642
|
}
|
|
665
643
|
}
|
|
666
644
|
}
|
|
@@ -684,12 +662,12 @@ class AbstractObject {
|
|
|
684
662
|
let count = 0;
|
|
685
663
|
const lastPositions = [];
|
|
686
664
|
this.stopMoveTo();
|
|
687
|
-
this.destroyMove$ = new
|
|
665
|
+
this.destroyMove$ = new Subject();
|
|
688
666
|
const { infinite, onStuck, onComplete } = options;
|
|
689
667
|
const getPosition = () => {
|
|
690
668
|
let pos;
|
|
691
669
|
if ('x' in positionTarget) {
|
|
692
|
-
pos = new
|
|
670
|
+
pos = new Vector2d(positionTarget.x, positionTarget.y);
|
|
693
671
|
}
|
|
694
672
|
else {
|
|
695
673
|
pos = positionTarget.position;
|
|
@@ -697,10 +675,10 @@ class AbstractObject {
|
|
|
697
675
|
return pos;
|
|
698
676
|
};
|
|
699
677
|
return tick$
|
|
700
|
-
.pipe(
|
|
678
|
+
.pipe(takeUntil(this.destroyMove$), takeUntil(this._destroy$), mergeMap(() => from(this.computeNextPositionByTarget(this.position.copy(), getPosition()))), map((position) => {
|
|
701
679
|
this.autoChangeDirection(position);
|
|
702
680
|
return this.position.set(position);
|
|
703
|
-
}),
|
|
681
|
+
}), tap((position) => {
|
|
704
682
|
lastPositions[i] = position.copy();
|
|
705
683
|
i++;
|
|
706
684
|
count++;
|
|
@@ -708,10 +686,10 @@ class AbstractObject {
|
|
|
708
686
|
i = 0;
|
|
709
687
|
}
|
|
710
688
|
if (lastPositions[2] && lastPositions[0].isEqual(lastPositions[2])) {
|
|
711
|
-
onStuck
|
|
689
|
+
onStuck?.(count);
|
|
712
690
|
}
|
|
713
691
|
else if (this.position.isEqual(getPosition())) {
|
|
714
|
-
onComplete
|
|
692
|
+
onComplete?.();
|
|
715
693
|
if (!infinite) {
|
|
716
694
|
this.stopMoveTo();
|
|
717
695
|
}
|
|
@@ -722,16 +700,14 @@ class AbstractObject {
|
|
|
722
700
|
}));
|
|
723
701
|
}
|
|
724
702
|
/** @internal */
|
|
725
|
-
move(nextPosition) {
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
return true;
|
|
734
|
-
});
|
|
703
|
+
async move(nextPosition) {
|
|
704
|
+
this.autoChangeDirection(nextPosition);
|
|
705
|
+
const notCollided = !(await this.isCollided(nextPosition));
|
|
706
|
+
if (notCollided || !this.checkCollision) {
|
|
707
|
+
this.position = nextPosition.copy();
|
|
708
|
+
await RpgPlugin.emit(HookServer.PlayerMove, this);
|
|
709
|
+
}
|
|
710
|
+
return true;
|
|
735
711
|
}
|
|
736
712
|
/**
|
|
737
713
|
* Retrieves all shapes where the player is located
|
|
@@ -795,11 +771,11 @@ class AbstractObject {
|
|
|
795
771
|
get nbPixelInTile() {
|
|
796
772
|
const direction = this.getDirection();
|
|
797
773
|
switch (direction) {
|
|
798
|
-
case
|
|
799
|
-
case
|
|
774
|
+
case Direction.Down:
|
|
775
|
+
case Direction.Up:
|
|
800
776
|
return Math.floor(this.mapInstance.tileHeight / this.speed);
|
|
801
|
-
case
|
|
802
|
-
case
|
|
777
|
+
case Direction.Left:
|
|
778
|
+
case Direction.Right:
|
|
803
779
|
return Math.floor(this.mapInstance.tileWidth / this.speed);
|
|
804
780
|
default:
|
|
805
781
|
return NaN;
|
|
@@ -833,13 +809,10 @@ class AbstractObject {
|
|
|
833
809
|
};
|
|
834
810
|
}
|
|
835
811
|
/** @internal */
|
|
836
|
-
execMethod(methodName, methodData, instance) {
|
|
837
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
838
|
-
}
|
|
812
|
+
async execMethod(methodName, methodData, instance) { }
|
|
839
813
|
/** @internal */
|
|
840
814
|
onAction() { }
|
|
841
815
|
/** @internal */
|
|
842
816
|
onPlayerTouch() { }
|
|
843
817
|
}
|
|
844
|
-
exports.AbstractObject = AbstractObject;
|
|
845
818
|
//# sourceMappingURL=AbstractObject.js.map
|