@rpgjs/common 3.3.1 → 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 +287 -312
- 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,20 +259,20 @@ class AbstractObject {
|
|
|
272
259
|
this.posY = tileY * tileHeight;
|
|
273
260
|
}
|
|
274
261
|
/** @internal */
|
|
275
|
-
triggerCollisionWith(type) {
|
|
262
|
+
async triggerCollisionWith(type) {
|
|
276
263
|
for (let collisionWith of this.collisionWith) {
|
|
277
|
-
if (collisionWith instanceof
|
|
264
|
+
if (collisionWith instanceof RpgShape) {
|
|
278
265
|
const goMap = collisionWith.getProperty('go-map');
|
|
279
266
|
if (goMap && 'changeMap' in this)
|
|
280
|
-
this.changeMap(goMap);
|
|
267
|
+
await this.changeMap(goMap);
|
|
281
268
|
}
|
|
282
269
|
else {
|
|
283
270
|
if (type == AbstractObject.ACTIONS.ACTION) {
|
|
284
271
|
if ('onAction' in collisionWith)
|
|
285
|
-
collisionWith.execMethod('onAction', [this]);
|
|
272
|
+
await collisionWith.execMethod('onAction', [this]);
|
|
286
273
|
}
|
|
287
274
|
else if ('onPlayerTouch' in collisionWith)
|
|
288
|
-
collisionWith.execMethod('onPlayerTouch', [this]);
|
|
275
|
+
await collisionWith.execMethod('onPlayerTouch', [this]);
|
|
289
276
|
}
|
|
290
277
|
}
|
|
291
278
|
}
|
|
@@ -293,7 +280,7 @@ class AbstractObject {
|
|
|
293
280
|
zCollision(other) {
|
|
294
281
|
const z = this.position.z;
|
|
295
282
|
const otherZ = other.position.z;
|
|
296
|
-
return
|
|
283
|
+
return intersection([z, z + this.height], [otherZ, otherZ + other.height]);
|
|
297
284
|
}
|
|
298
285
|
/** @internal */
|
|
299
286
|
moveByDirection(direction, deltaTimeInt) {
|
|
@@ -346,258 +333,248 @@ class AbstractObject {
|
|
|
346
333
|
const map = this.mapInstance;
|
|
347
334
|
return map.getTile(hitbox || this.hitbox, x, y, [z, this.height]);
|
|
348
335
|
}
|
|
349
|
-
collisionObjects(playerSizeBox, hitbox, triggers) {
|
|
350
|
-
|
|
351
|
-
|
|
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
|
-
if (event.
|
|
380
|
-
if (!(event.throughOtherPlayer || this.throughOtherPlayer)) {
|
|
381
|
-
boolFound = true;
|
|
382
|
-
if (!(triggers === null || triggers === void 0 ? void 0 : triggers.allSearch))
|
|
383
|
-
return true;
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
throughOtherPlayer = true;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
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)) {
|
|
390
367
|
boolFound = true;
|
|
391
|
-
if (!
|
|
368
|
+
if (!triggers?.allSearch)
|
|
392
369
|
return true;
|
|
393
370
|
}
|
|
371
|
+
else {
|
|
372
|
+
throughOtherPlayer = true;
|
|
373
|
+
}
|
|
394
374
|
}
|
|
395
|
-
if (
|
|
396
|
-
|
|
397
|
-
|
|
375
|
+
if (!throughOtherPlayer && (!(event.through || this.through))) {
|
|
376
|
+
boolFound = true;
|
|
377
|
+
if (!triggers?.allSearch)
|
|
378
|
+
return true;
|
|
398
379
|
}
|
|
399
380
|
}
|
|
400
|
-
|
|
401
|
-
|
|
381
|
+
if (boolFound) {
|
|
382
|
+
if (triggers?.collision)
|
|
383
|
+
triggers.collision(event);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return boolFound;
|
|
402
387
|
}
|
|
403
388
|
/** @internal */
|
|
404
|
-
collisionWithShape(shape, player, nextPosition) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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;
|
|
423
416
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const playerPositionSaved = player.position.copy();
|
|
427
|
-
// Position can changed after enter or exit shape. So, we need to verify if position changed and update if z is changed
|
|
428
|
-
// If X or Y changed, we need to return true, it means that stop the current movement, and apply the new position
|
|
429
|
-
const verifyIfPositionChanged = () => {
|
|
430
|
-
if (this.position.z != playerPositionSaved.z && nextPosition) {
|
|
431
|
-
nextPosition.z = this.position.z;
|
|
432
|
-
}
|
|
433
|
-
if (this.position.x != playerPositionSaved.x || this.position.y != playerPositionSaved.y) {
|
|
434
|
-
return true;
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
if (collided) {
|
|
438
|
-
this._collisionWithShapes.push(shape);
|
|
439
|
-
// TODO: in shape after map load
|
|
440
|
-
if (!collision)
|
|
441
|
-
yield shape.in(this);
|
|
442
|
-
if (verifyIfPositionChanged() === true)
|
|
443
|
-
return true;
|
|
444
|
-
this.triggerCollisionWith();
|
|
445
|
-
if (collision)
|
|
446
|
-
return true;
|
|
417
|
+
if (this.position.x != playerPositionSaved.x || this.position.y != playerPositionSaved.y) {
|
|
418
|
+
return true;
|
|
447
419
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
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)
|
|
451
458
|
return true;
|
|
452
459
|
}
|
|
453
|
-
|
|
454
|
-
|
|
460
|
+
}
|
|
461
|
+
return boolFound;
|
|
455
462
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if (!(triggers === null || triggers === void 0 ? void 0 : triggers.allSearch))
|
|
476
|
-
return true;
|
|
477
|
-
}
|
|
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));
|
|
478
482
|
}
|
|
479
|
-
return
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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);
|
|
487
500
|
}
|
|
488
|
-
const pull = (target.copy().subtract(nextPosition)).multiply((1 / pullDistance));
|
|
489
|
-
const totalPush = new Vector2d_1.Vector2dZero();
|
|
490
|
-
let contenders = 0;
|
|
491
|
-
const hitbox = Hit_1.Hit.createObjectHitbox(nextPosition.x, nextPosition.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
492
|
-
const createObstacle = function (x, y, radius) {
|
|
493
|
-
const obstacle = new Vector2d_1.Vector2d(x, y);
|
|
494
|
-
let push = nextPosition.copy().subtract(obstacle);
|
|
495
|
-
let distance = (nextPosition.distanceWith(obstacle) - radius) - radius;
|
|
496
|
-
if (distance < radius * 2 * 10) {
|
|
497
|
-
++contenders;
|
|
498
|
-
if (distance < 0.0001)
|
|
499
|
-
distance = 0.0001; // avoid div by 0
|
|
500
|
-
let weight = 1 / distance;
|
|
501
|
-
totalPush.add(push.multiply(weight));
|
|
502
|
-
}
|
|
503
|
-
return obstacle;
|
|
504
|
-
};
|
|
505
|
-
const area = this.mapInstance.tileheight * 2;
|
|
506
|
-
this.mapInstance.gridTiles.getCells({
|
|
507
|
-
minX: nextPosition.x - area,
|
|
508
|
-
maxX: nextPosition.x + area,
|
|
509
|
-
minY: nextPosition.y - area,
|
|
510
|
-
maxY: nextPosition.y + area
|
|
511
|
-
}, (index) => {
|
|
512
|
-
if (index < 0)
|
|
513
|
-
return;
|
|
514
|
-
const pos = this.mapInstance.getTilePosition(index);
|
|
515
|
-
const hitbox = Hit_1.Hit.createObjectHitbox(pos.x, pos.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
516
|
-
const radius = this.mapInstance.tilewidth / 2;
|
|
517
|
-
const tile = this.getTile(pos.x, pos.y, nextPosition.z, hitbox);
|
|
518
|
-
if (tile.hasCollision) {
|
|
519
|
-
createObstacle(pos.x, pos.y, radius);
|
|
520
|
-
}
|
|
521
|
-
});
|
|
522
|
-
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
523
|
-
yield this.collisionObjects(playerSizeBox, hitbox, {
|
|
524
|
-
collision: (event) => {
|
|
525
|
-
const { x, y } = event.position;
|
|
526
|
-
createObstacle(x, y, event.hitbox.w);
|
|
527
|
-
},
|
|
528
|
-
allSearch: true
|
|
529
|
-
});
|
|
530
|
-
yield this.collisionShapes(playerSizeBox, nextPosition, {
|
|
531
|
-
collision: (shape) => {
|
|
532
|
-
const { x, y } = shape.position;
|
|
533
|
-
createObstacle(x, y, shape.hitbox.w);
|
|
534
|
-
},
|
|
535
|
-
allSearch: true
|
|
536
|
-
});
|
|
537
|
-
pull
|
|
538
|
-
.multiply(Math.max(1, 4 * contenders))
|
|
539
|
-
.add(totalPush)
|
|
540
|
-
.normalize();
|
|
541
|
-
return nextPosition.add(pull.multiply(this.speed));
|
|
542
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));
|
|
543
522
|
}
|
|
544
|
-
isCollided(nextPosition, options = {}) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
return true;
|
|
564
|
-
}
|
|
565
|
-
return false;
|
|
566
|
-
};
|
|
567
|
-
if (tileCollision(nextPosition.x, nextPosition.y) ||
|
|
568
|
-
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y) ||
|
|
569
|
-
tileCollision(nextPosition.x, nextPosition.y + this.hitbox.h) ||
|
|
570
|
-
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y + this.hitbox.h)) {
|
|
571
|
-
if (!options.allSearch)
|
|
572
|
-
return true;
|
|
573
|
-
else
|
|
574
|
-
collided = true;
|
|
575
|
-
}
|
|
576
|
-
if (this.autoChangeMap) {
|
|
577
|
-
const changeMap = yield this.autoChangeMap(nextPosition);
|
|
578
|
-
if (changeMap) {
|
|
579
|
-
return true;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
583
|
-
if (yield this.collisionObjects(playerSizeBox, hitbox, options)) {
|
|
584
|
-
if (!options.allSearch)
|
|
585
|
-
return true;
|
|
586
|
-
else
|
|
587
|
-
collided = true;
|
|
588
|
-
}
|
|
589
|
-
if (yield this.collisionShapes(playerSizeBox, nextPosition, options)) {
|
|
590
|
-
if (!options.allSearch)
|
|
591
|
-
return true;
|
|
592
|
-
else
|
|
593
|
-
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;
|
|
594
542
|
}
|
|
595
|
-
|
|
596
|
-
|
|
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) {
|
|
597
557
|
return true;
|
|
598
558
|
}
|
|
599
|
-
|
|
600
|
-
|
|
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;
|
|
601
578
|
}
|
|
602
579
|
/**
|
|
603
580
|
* Attach a shape to the player (and allow interaction with it)
|
|
@@ -623,8 +600,11 @@ class AbstractObject {
|
|
|
623
600
|
* @memberof Player
|
|
624
601
|
*/
|
|
625
602
|
attachShape(obj) {
|
|
626
|
-
obj.name = (obj.name ||
|
|
627
|
-
const shape = new
|
|
603
|
+
obj.name = (obj.name || generateUID());
|
|
604
|
+
const shape = new RpgShape({
|
|
605
|
+
...obj,
|
|
606
|
+
fixEvent: this
|
|
607
|
+
});
|
|
628
608
|
this.shapes.push(shape);
|
|
629
609
|
return shape;
|
|
630
610
|
}
|
|
@@ -647,18 +627,18 @@ class AbstractObject {
|
|
|
647
627
|
const diff = Math.abs(x - nx) > Math.abs(y - ny);
|
|
648
628
|
if (diff) {
|
|
649
629
|
if (nx > x) {
|
|
650
|
-
this.changeDirection(
|
|
630
|
+
this.changeDirection(Direction.Right);
|
|
651
631
|
}
|
|
652
632
|
else {
|
|
653
|
-
this.changeDirection(
|
|
633
|
+
this.changeDirection(Direction.Left);
|
|
654
634
|
}
|
|
655
635
|
}
|
|
656
636
|
else {
|
|
657
637
|
if (ny > y) {
|
|
658
|
-
this.changeDirection(
|
|
638
|
+
this.changeDirection(Direction.Down);
|
|
659
639
|
}
|
|
660
640
|
else {
|
|
661
|
-
this.changeDirection(
|
|
641
|
+
this.changeDirection(Direction.Up);
|
|
662
642
|
}
|
|
663
643
|
}
|
|
664
644
|
}
|
|
@@ -682,12 +662,12 @@ class AbstractObject {
|
|
|
682
662
|
let count = 0;
|
|
683
663
|
const lastPositions = [];
|
|
684
664
|
this.stopMoveTo();
|
|
685
|
-
this.destroyMove$ = new
|
|
665
|
+
this.destroyMove$ = new Subject();
|
|
686
666
|
const { infinite, onStuck, onComplete } = options;
|
|
687
667
|
const getPosition = () => {
|
|
688
668
|
let pos;
|
|
689
669
|
if ('x' in positionTarget) {
|
|
690
|
-
pos = new
|
|
670
|
+
pos = new Vector2d(positionTarget.x, positionTarget.y);
|
|
691
671
|
}
|
|
692
672
|
else {
|
|
693
673
|
pos = positionTarget.position;
|
|
@@ -695,10 +675,10 @@ class AbstractObject {
|
|
|
695
675
|
return pos;
|
|
696
676
|
};
|
|
697
677
|
return tick$
|
|
698
|
-
.pipe(
|
|
678
|
+
.pipe(takeUntil(this.destroyMove$), takeUntil(this._destroy$), mergeMap(() => from(this.computeNextPositionByTarget(this.position.copy(), getPosition()))), map((position) => {
|
|
699
679
|
this.autoChangeDirection(position);
|
|
700
680
|
return this.position.set(position);
|
|
701
|
-
}),
|
|
681
|
+
}), tap((position) => {
|
|
702
682
|
lastPositions[i] = position.copy();
|
|
703
683
|
i++;
|
|
704
684
|
count++;
|
|
@@ -706,10 +686,10 @@ class AbstractObject {
|
|
|
706
686
|
i = 0;
|
|
707
687
|
}
|
|
708
688
|
if (lastPositions[2] && lastPositions[0].isEqual(lastPositions[2])) {
|
|
709
|
-
onStuck
|
|
689
|
+
onStuck?.(count);
|
|
710
690
|
}
|
|
711
691
|
else if (this.position.isEqual(getPosition())) {
|
|
712
|
-
onComplete
|
|
692
|
+
onComplete?.();
|
|
713
693
|
if (!infinite) {
|
|
714
694
|
this.stopMoveTo();
|
|
715
695
|
}
|
|
@@ -720,16 +700,14 @@ class AbstractObject {
|
|
|
720
700
|
}));
|
|
721
701
|
}
|
|
722
702
|
/** @internal */
|
|
723
|
-
move(nextPosition) {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
return true;
|
|
732
|
-
});
|
|
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;
|
|
733
711
|
}
|
|
734
712
|
/**
|
|
735
713
|
* Retrieves all shapes where the player is located
|
|
@@ -793,11 +771,11 @@ class AbstractObject {
|
|
|
793
771
|
get nbPixelInTile() {
|
|
794
772
|
const direction = this.getDirection();
|
|
795
773
|
switch (direction) {
|
|
796
|
-
case
|
|
797
|
-
case
|
|
774
|
+
case Direction.Down:
|
|
775
|
+
case Direction.Up:
|
|
798
776
|
return Math.floor(this.mapInstance.tileHeight / this.speed);
|
|
799
|
-
case
|
|
800
|
-
case
|
|
777
|
+
case Direction.Left:
|
|
778
|
+
case Direction.Right:
|
|
801
779
|
return Math.floor(this.mapInstance.tileWidth / this.speed);
|
|
802
780
|
default:
|
|
803
781
|
return NaN;
|
|
@@ -831,13 +809,10 @@ class AbstractObject {
|
|
|
831
809
|
};
|
|
832
810
|
}
|
|
833
811
|
/** @internal */
|
|
834
|
-
execMethod(methodName, methodData, instance) {
|
|
835
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
836
|
-
}
|
|
812
|
+
async execMethod(methodName, methodData, instance) { }
|
|
837
813
|
/** @internal */
|
|
838
814
|
onAction() { }
|
|
839
815
|
/** @internal */
|
|
840
816
|
onPlayerTouch() { }
|
|
841
817
|
}
|
|
842
|
-
exports.AbstractObject = AbstractObject;
|
|
843
818
|
//# sourceMappingURL=AbstractObject.js.map
|