@rpgjs/common 3.0.1 → 3.2.0
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 +318 -0
- package/lib/AbstractObject.js +828 -0
- package/lib/AbstractObject.js.map +1 -0
- package/lib/Game.d.ts +6 -2
- package/lib/Game.js +42 -13
- package/lib/Game.js.map +1 -1
- package/lib/Hit.d.ts +4 -28
- package/lib/Hit.js +12 -15
- package/lib/Hit.js.map +1 -1
- package/lib/Hitbox.d.ts +6 -0
- package/lib/Hitbox.js +10 -0
- package/lib/Hitbox.js.map +1 -0
- package/lib/HitboxEffect.d.ts +6 -0
- package/lib/HitboxEffect.js +10 -0
- package/lib/HitboxEffect.js.map +1 -0
- package/lib/Map.d.ts +12 -0
- package/lib/Map.js +77 -4
- package/lib/Map.js.map +1 -1
- package/lib/Player.d.ts +9 -296
- package/lib/Player.js +7 -639
- package/lib/Player.js.map +1 -1
- package/lib/Scheduler.d.ts +16 -38
- package/lib/Scheduler.js +69 -76
- package/lib/Scheduler.js.map +1 -1
- package/lib/Shape.d.ts +8 -7
- package/lib/Shape.js +11 -15
- package/lib/Shape.js.map +1 -1
- package/lib/SocketEvents.d.ts +8 -0
- package/lib/SocketEvents.js +14 -0
- package/lib/SocketEvents.js.map +1 -0
- package/lib/Utils.d.ts +12 -11
- package/lib/Utils.js.map +1 -1
- package/lib/Vector2d.d.ts +19 -0
- package/lib/Vector2d.js +63 -0
- package/lib/Vector2d.js.map +1 -0
- package/lib/VirtualGrid.d.ts +2 -3
- package/lib/VirtualGrid.js.map +1 -1
- package/lib/WorldMaps.d.ts +1 -1
- package/lib/WorldMaps.js +5 -5
- package/lib/WorldMaps.js.map +1 -1
- package/lib/index.d.ts +21 -19
- package/lib/index.js +27 -30
- package/lib/index.js.map +1 -1
- package/lib/types/Hitbox.d.ts +24 -0
- package/lib/types/Hitbox.js +3 -0
- package/lib/types/Hitbox.js.map +1 -0
- package/lib/types/Player.d.ts +8 -0
- package/lib/types/Player.js +3 -0
- package/lib/types/Player.js.map +1 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.js +3 -0
- package/lib/types/index.js.map +1 -0
- package/lib/workers/move.js +1 -1
- package/lib/workers/move.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,828 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
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");
|
|
26
|
+
const ACTIONS = { IDLE: 0, RUN: 1, ACTION: 2 };
|
|
27
|
+
class AbstractObject {
|
|
28
|
+
constructor(gameEngine, playerId) {
|
|
29
|
+
this.gameEngine = gameEngine;
|
|
30
|
+
this.playerId = playerId;
|
|
31
|
+
this.map = '';
|
|
32
|
+
this.height = 0;
|
|
33
|
+
this.width = 0;
|
|
34
|
+
this.direction = 3;
|
|
35
|
+
/*
|
|
36
|
+
Properties for move mode
|
|
37
|
+
*/
|
|
38
|
+
this.checkCollision = true;
|
|
39
|
+
this.clientModeMove = types_1.MoveClientMode.ByDirection;
|
|
40
|
+
this.behavior = types_1.Behavior.Direction;
|
|
41
|
+
this.inShapes = {};
|
|
42
|
+
this.disableVirtualGrid = false;
|
|
43
|
+
this.shapes = [];
|
|
44
|
+
this.collisionWith = [];
|
|
45
|
+
this._collisionWithTiles = [];
|
|
46
|
+
this._collisionWithShapes = [];
|
|
47
|
+
this.destroyMove$ = new rxjs_1.Subject();
|
|
48
|
+
this._hitboxPos = new sat_1.default.Vector(0, 0);
|
|
49
|
+
this.setHitbox(this.width, this.height);
|
|
50
|
+
this.position = { x: 0, y: 0, z: 0 };
|
|
51
|
+
}
|
|
52
|
+
static get ACTIONS() {
|
|
53
|
+
return ACTIONS;
|
|
54
|
+
}
|
|
55
|
+
get id() {
|
|
56
|
+
return this.playerId;
|
|
57
|
+
}
|
|
58
|
+
set id(str) {
|
|
59
|
+
this.playerId = str;
|
|
60
|
+
}
|
|
61
|
+
updateInVirtualGrid() {
|
|
62
|
+
const map = this.mapInstance;
|
|
63
|
+
if (map && !this.disableVirtualGrid /*&& this.gameEngine.isWorker TODO */) {
|
|
64
|
+
map.grid.insertInCells(this.id, this.getSizeMaxShape());
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
get canMove() {
|
|
68
|
+
return this.clientModeMove == types_1.MoveClientMode.ByDirection;
|
|
69
|
+
}
|
|
70
|
+
set canMove(val) {
|
|
71
|
+
this.clientModeMove = val ? types_1.MoveClientMode.ByDirection : types_1.MoveClientMode.Disabled;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get/Set position x, y and z of player
|
|
75
|
+
*
|
|
76
|
+
* z is the depth layer. By default, its value is 0. Collisions and overlays will be performed with other objects on the same z-position.
|
|
77
|
+
*
|
|
78
|
+
* @title Get/Set position
|
|
79
|
+
* @prop { { x: number, y: number, z: number } } position
|
|
80
|
+
* @memberof Player
|
|
81
|
+
*/
|
|
82
|
+
set position(val) {
|
|
83
|
+
const { x, y, z } = val;
|
|
84
|
+
if (!Utils_1.isInstanceOf(val, Vector2d_1.Vector2d)) {
|
|
85
|
+
val = new Vector2d_1.Vector2d(x, y, z);
|
|
86
|
+
}
|
|
87
|
+
this._hitboxPos.x = x;
|
|
88
|
+
this._hitboxPos.y = y;
|
|
89
|
+
this._hitboxPos.z = z;
|
|
90
|
+
this.updateInVirtualGrid();
|
|
91
|
+
this._position = new Proxy(val, {
|
|
92
|
+
get: (target, prop) => target[prop],
|
|
93
|
+
set: (target, prop, value) => {
|
|
94
|
+
this._hitboxPos[prop] = value;
|
|
95
|
+
target[prop] = value;
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
get position() {
|
|
101
|
+
return this._position;
|
|
102
|
+
}
|
|
103
|
+
get worldPositionX() {
|
|
104
|
+
let x = this.position.x;
|
|
105
|
+
if (this.mapInstance) {
|
|
106
|
+
x += this.mapInstance.worldX;
|
|
107
|
+
}
|
|
108
|
+
return x;
|
|
109
|
+
}
|
|
110
|
+
get worldPositionY() {
|
|
111
|
+
let y = this.position.y;
|
|
112
|
+
if (this.mapInstance) {
|
|
113
|
+
y += this.mapInstance.worldY;
|
|
114
|
+
}
|
|
115
|
+
return y;
|
|
116
|
+
}
|
|
117
|
+
set posX(val) {
|
|
118
|
+
this.position.x = val;
|
|
119
|
+
}
|
|
120
|
+
set posY(val) {
|
|
121
|
+
this.position.y = val;
|
|
122
|
+
}
|
|
123
|
+
set posZ(val) {
|
|
124
|
+
this.position.z = val;
|
|
125
|
+
}
|
|
126
|
+
/** @internal */
|
|
127
|
+
get mapInstance() {
|
|
128
|
+
if (this.gameEngine.side == Game_1.GameSide.Client) {
|
|
129
|
+
return Map_1.RpgCommonMap.bufferClient.get(this.map);
|
|
130
|
+
}
|
|
131
|
+
return Map_1.RpgCommonMap.buffer.get(this.map);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* Recovers all the colliding shapes of the current player
|
|
136
|
+
*
|
|
137
|
+
* @title Get Collision of shapes
|
|
138
|
+
* @since 3.2.0
|
|
139
|
+
* @readonly
|
|
140
|
+
* @prop { RpgShape[] } shapes
|
|
141
|
+
* @memberof Player
|
|
142
|
+
* @memberof RpgSpriteLogic
|
|
143
|
+
*/
|
|
144
|
+
get shapesCollision() {
|
|
145
|
+
return this._collisionWithShapes;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
*
|
|
149
|
+
* Recovers all the colliding tiles of the current player
|
|
150
|
+
*
|
|
151
|
+
* @title Get Collision of tiles
|
|
152
|
+
* @since 3.0.0-beta.4
|
|
153
|
+
* @readonly
|
|
154
|
+
* @prop { TileInfo[] } tiles
|
|
155
|
+
* @memberof Player
|
|
156
|
+
* @memberof RpgSpriteLogic
|
|
157
|
+
*/
|
|
158
|
+
get tilesCollision() {
|
|
159
|
+
return this._collisionWithTiles;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
*
|
|
163
|
+
* Recovers all other players and events colliding with the current player's hitbox
|
|
164
|
+
*
|
|
165
|
+
* @title Get Collision of other players/events
|
|
166
|
+
* @since 3.0.0-beta.4
|
|
167
|
+
* @readonly
|
|
168
|
+
* @prop { (RpgPlayer | RpgEvent)[] } otherPlayersCollision
|
|
169
|
+
* @memberof Player
|
|
170
|
+
* @memberof RpgSpriteLogic
|
|
171
|
+
*/
|
|
172
|
+
get otherPlayersCollision() {
|
|
173
|
+
return this.collisionWith;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Define the size of the player. You can set the hitbox for collisions
|
|
177
|
+
*
|
|
178
|
+
* ```ts
|
|
179
|
+
* player.setSizes({
|
|
180
|
+
* width: 32,
|
|
181
|
+
* height: 32
|
|
182
|
+
* })
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* and with hitbox:
|
|
186
|
+
*
|
|
187
|
+
* ```ts
|
|
188
|
+
* player.setSizes({
|
|
189
|
+
* width: 32,
|
|
190
|
+
* height: 32,
|
|
191
|
+
* hitbox: {
|
|
192
|
+
* width: 20,
|
|
193
|
+
* height: 20
|
|
194
|
+
* }
|
|
195
|
+
* })
|
|
196
|
+
* ```
|
|
197
|
+
*
|
|
198
|
+
* @title Set Sizes
|
|
199
|
+
* @method player.setSizes(key,value)
|
|
200
|
+
* @param { { width: number, height: number, hitbox?: { width: number, height: number } } } obj
|
|
201
|
+
* @deprecated
|
|
202
|
+
* @returns {void}
|
|
203
|
+
* @memberof Player
|
|
204
|
+
*/
|
|
205
|
+
setSizes(obj) {
|
|
206
|
+
this.width = obj.width;
|
|
207
|
+
this.height = obj.height;
|
|
208
|
+
if (obj.hitbox) {
|
|
209
|
+
this.hitbox = new sat_1.default.Box(this._hitboxPos, obj.hitbox.width, obj.hitbox.height);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Define the hitbox of the player.
|
|
214
|
+
*
|
|
215
|
+
* ```ts
|
|
216
|
+
* player.setHitbox(20, 20)
|
|
217
|
+
* ```
|
|
218
|
+
*
|
|
219
|
+
* @title Set Hitbox
|
|
220
|
+
* @method player.setHitbox(width,height)
|
|
221
|
+
* @param {number} width
|
|
222
|
+
* @param {number} height
|
|
223
|
+
* @returns {void}
|
|
224
|
+
* @memberof Player
|
|
225
|
+
*/
|
|
226
|
+
setHitbox(width, height) {
|
|
227
|
+
const map = this.mapInstance;
|
|
228
|
+
if (map) {
|
|
229
|
+
this.width = map.tileWidth;
|
|
230
|
+
this.height = map.tileHeight;
|
|
231
|
+
}
|
|
232
|
+
this.hitbox = new sat_1.default.Box(this._hitboxPos, width, height);
|
|
233
|
+
this.wHitbox = width;
|
|
234
|
+
this.hHitbox = height;
|
|
235
|
+
this.updateInVirtualGrid();
|
|
236
|
+
}
|
|
237
|
+
set wHitbox(val) {
|
|
238
|
+
this.hitbox.w = val;
|
|
239
|
+
}
|
|
240
|
+
set hHitbox(val) {
|
|
241
|
+
this.hitbox.h = val;
|
|
242
|
+
}
|
|
243
|
+
get wHitbox() {
|
|
244
|
+
return this.hitbox.w;
|
|
245
|
+
}
|
|
246
|
+
get hHitbox() {
|
|
247
|
+
return this.hitbox.h;
|
|
248
|
+
}
|
|
249
|
+
directionToAngle(direction) {
|
|
250
|
+
const angle = (direction < 2 ? +direction + 2 : direction - 2) * 90;
|
|
251
|
+
return Utils_1.toRadians(angle);
|
|
252
|
+
}
|
|
253
|
+
/** @internal */
|
|
254
|
+
defineNextPosition(direction, deltaTimeInt) {
|
|
255
|
+
const angle = this.directionToAngle(direction);
|
|
256
|
+
const computePosition = (prop) => {
|
|
257
|
+
return this.position[prop] + this.speed * deltaTimeInt
|
|
258
|
+
* (Math.round(Math[prop == 'x' ? 'cos' : 'sin'](angle) * 100) / 100);
|
|
259
|
+
};
|
|
260
|
+
return new Vector2d_1.Vector2d(~~computePosition('x'), ~~computePosition('y'), ~~this.position.z);
|
|
261
|
+
}
|
|
262
|
+
/** @internal */
|
|
263
|
+
setPosition({ x, y, tileX, tileY }, move = true) {
|
|
264
|
+
const { tileWidth, tileHeight } = this.mapInstance;
|
|
265
|
+
if (x !== undefined)
|
|
266
|
+
this.posX = x;
|
|
267
|
+
if (y !== undefined)
|
|
268
|
+
this.posY = y;
|
|
269
|
+
if (tileX !== undefined)
|
|
270
|
+
this.posX = tileX * tileWidth;
|
|
271
|
+
if (tileY !== undefined)
|
|
272
|
+
this.posY = tileY * tileHeight;
|
|
273
|
+
}
|
|
274
|
+
/** @internal */
|
|
275
|
+
triggerCollisionWith(type) {
|
|
276
|
+
for (let collisionWith of this.collisionWith) {
|
|
277
|
+
if (collisionWith instanceof Shape_1.RpgShape) {
|
|
278
|
+
const goMap = collisionWith.getProperty('go-map');
|
|
279
|
+
if (goMap && 'changeMap' in this)
|
|
280
|
+
this.changeMap(goMap);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
if (type == AbstractObject.ACTIONS.ACTION) {
|
|
284
|
+
if ('onAction' in collisionWith)
|
|
285
|
+
collisionWith.execMethod('onAction', [this]);
|
|
286
|
+
}
|
|
287
|
+
else if ('onPlayerTouch' in collisionWith)
|
|
288
|
+
collisionWith.execMethod('onPlayerTouch', [this]);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/** @internal */
|
|
293
|
+
zCollision(other) {
|
|
294
|
+
const z = this.position.z;
|
|
295
|
+
const otherZ = other.position.z;
|
|
296
|
+
return Utils_1.intersection([z, z + this.height], [otherZ, otherZ + other.height]);
|
|
297
|
+
}
|
|
298
|
+
/** @internal */
|
|
299
|
+
moveByDirection(direction, deltaTimeInt) {
|
|
300
|
+
const nextPosition = this.defineNextPosition(direction, deltaTimeInt);
|
|
301
|
+
return this.move(nextPosition);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Retrieves a tile and checks if the player has a collision
|
|
305
|
+
*
|
|
306
|
+
* ```ts
|
|
307
|
+
* const tileInfo = player.getTile(20, 30)
|
|
308
|
+
* console.log(tileInfo)
|
|
309
|
+
* ```
|
|
310
|
+
*
|
|
311
|
+
* Example of returns:
|
|
312
|
+
*
|
|
313
|
+
```ts
|
|
314
|
+
{
|
|
315
|
+
tiles: [
|
|
316
|
+
{
|
|
317
|
+
id: 0,
|
|
318
|
+
terrain: [],
|
|
319
|
+
probability: null,
|
|
320
|
+
properties: [Object],
|
|
321
|
+
animations: [],
|
|
322
|
+
objectGroups: [],
|
|
323
|
+
image: null,
|
|
324
|
+
gid: 1
|
|
325
|
+
}
|
|
326
|
+
],
|
|
327
|
+
hasCollision: false,
|
|
328
|
+
isOverlay: undefined,
|
|
329
|
+
objectGroups: [],
|
|
330
|
+
isClimbable: undefined,
|
|
331
|
+
tileIndex: 93
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
*
|
|
335
|
+
* @title Get Tile
|
|
336
|
+
* @since 3.0.0-beta.4
|
|
337
|
+
* @method player.getTile(x,y,z?)
|
|
338
|
+
* @param {number} x
|
|
339
|
+
* @param {number} y
|
|
340
|
+
* @param {number} [z]
|
|
341
|
+
* @returns {object}
|
|
342
|
+
* @memberof Player
|
|
343
|
+
* @memberof RpgSpriteLogic
|
|
344
|
+
*/
|
|
345
|
+
getTile(x, y, z = 0, hitbox) {
|
|
346
|
+
const map = this.mapInstance;
|
|
347
|
+
return map.getTile(hitbox || this.hitbox, x, y, [z, this.height]);
|
|
348
|
+
}
|
|
349
|
+
collisionObjects(playerSizeBox, hitbox, triggers) {
|
|
350
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
351
|
+
const map = this.mapInstance;
|
|
352
|
+
if (!map)
|
|
353
|
+
return true;
|
|
354
|
+
const events = this.gameEngine.world.getObjectsOfGroup(this.map, this);
|
|
355
|
+
const objects = map.grid.getObjectsByBox(playerSizeBox);
|
|
356
|
+
let boolFound = false;
|
|
357
|
+
for (let objectId of objects) {
|
|
358
|
+
// client side: read "object" propertie
|
|
359
|
+
if (!events[objectId])
|
|
360
|
+
continue;
|
|
361
|
+
const event = events[objectId]['object'] || events[objectId];
|
|
362
|
+
if (event.id == this.id)
|
|
363
|
+
continue;
|
|
364
|
+
if (!this.zCollision(event))
|
|
365
|
+
continue;
|
|
366
|
+
const collided = Hit_1.Hit.testPolyCollision(Hit_1.HitType.Box, hitbox, event.hitbox);
|
|
367
|
+
for (let shape of this.shapes) {
|
|
368
|
+
yield this.collisionWithShape(shape, event);
|
|
369
|
+
}
|
|
370
|
+
for (let shape of event.shapes) {
|
|
371
|
+
yield event.collisionWithShape(shape, this);
|
|
372
|
+
}
|
|
373
|
+
if (triggers === null || triggers === void 0 ? void 0 : triggers.near)
|
|
374
|
+
triggers.near(event);
|
|
375
|
+
if (collided) {
|
|
376
|
+
this.collisionWith.push(event);
|
|
377
|
+
this.triggerCollisionWith();
|
|
378
|
+
let throughOtherPlayer = false;
|
|
379
|
+
if (event.type == types_1.PlayerType.Player && this.type == types_1.PlayerType.Player) {
|
|
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))) {
|
|
390
|
+
boolFound = true;
|
|
391
|
+
if (!(triggers === null || triggers === void 0 ? void 0 : triggers.allSearch))
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (boolFound) {
|
|
396
|
+
if (triggers === null || triggers === void 0 ? void 0 : triggers.collision)
|
|
397
|
+
triggers.collision(event);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return boolFound;
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
/** @internal */
|
|
404
|
+
collisionWithShape(shape, player, nextPosition) {
|
|
405
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
406
|
+
const collision = shape.hasCollision;
|
|
407
|
+
const z = shape.z;
|
|
408
|
+
if (shape.isShapePosition())
|
|
409
|
+
return false;
|
|
410
|
+
if (z !== undefined && !this.zCollision({
|
|
411
|
+
position: { z },
|
|
412
|
+
height: this.mapInstance.zTileHeight
|
|
413
|
+
})) {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
let position;
|
|
417
|
+
let { hitbox } = player;
|
|
418
|
+
if (nextPosition) {
|
|
419
|
+
position = nextPosition.copy();
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
position = player.position.copy();
|
|
423
|
+
}
|
|
424
|
+
const hitboxObj = Hit_1.Hit.createObjectHitbox(position.x, position.y, position.z, hitbox.w, hitbox.h);
|
|
425
|
+
let collided = Hit_1.Hit.testPolyCollision(shape.type, hitboxObj, shape.hitbox);
|
|
426
|
+
if (collided) {
|
|
427
|
+
this._collisionWithShapes.push(shape);
|
|
428
|
+
// TODO: in shape after map load
|
|
429
|
+
if (!collision)
|
|
430
|
+
yield shape.in(this);
|
|
431
|
+
this.triggerCollisionWith();
|
|
432
|
+
if (collision)
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
yield shape.out(this);
|
|
437
|
+
}
|
|
438
|
+
return false;
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
collisionShapes(playerSizeBox, nextPosition, triggers) {
|
|
442
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
443
|
+
const map = this.mapInstance;
|
|
444
|
+
if (!map)
|
|
445
|
+
return false;
|
|
446
|
+
const shapes = this.gameEngine.world.getShapesOfGroup(this.map);
|
|
447
|
+
const shapesInGrid = this.gameEngine.side == Game_1.GameSide.Client
|
|
448
|
+
? new Set(Object.keys(shapes))
|
|
449
|
+
: map.gridShapes.getObjectsByBox(playerSizeBox);
|
|
450
|
+
let boolFound = false;
|
|
451
|
+
for (let shapeId of shapesInGrid) {
|
|
452
|
+
const shape = shapes[shapeId]['object'] || shapes[shapeId];
|
|
453
|
+
if (triggers === null || triggers === void 0 ? void 0 : triggers.near)
|
|
454
|
+
triggers.near(shape);
|
|
455
|
+
const bool = yield this.collisionWithShape(shape, this, nextPosition);
|
|
456
|
+
if (bool) {
|
|
457
|
+
if (triggers === null || triggers === void 0 ? void 0 : triggers.collision)
|
|
458
|
+
triggers.collision(shape);
|
|
459
|
+
boolFound = true;
|
|
460
|
+
if (!(triggers === null || triggers === void 0 ? void 0 : triggers.allSearch))
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return boolFound;
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
computeNextPositionByTarget(nextPosition, target) {
|
|
468
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
469
|
+
const pullDistance = target.distanceWith(nextPosition);
|
|
470
|
+
if (pullDistance <= this.speed) {
|
|
471
|
+
return nextPosition.set(target);
|
|
472
|
+
}
|
|
473
|
+
const pull = (target.copy().subtract(nextPosition)).multiply((1 / pullDistance));
|
|
474
|
+
const totalPush = new Vector2d_1.Vector2dZero();
|
|
475
|
+
let contenders = 0;
|
|
476
|
+
const hitbox = Hit_1.Hit.createObjectHitbox(nextPosition.x, nextPosition.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
477
|
+
const createObstacle = function (x, y, radius) {
|
|
478
|
+
const obstacle = new Vector2d_1.Vector2d(x, y);
|
|
479
|
+
let push = nextPosition.copy().subtract(obstacle);
|
|
480
|
+
let distance = (nextPosition.distanceWith(obstacle) - radius) - radius;
|
|
481
|
+
if (distance < radius * 2 * 10) {
|
|
482
|
+
++contenders;
|
|
483
|
+
if (distance < 0.0001)
|
|
484
|
+
distance = 0.0001; // avoid div by 0
|
|
485
|
+
let weight = 1 / distance;
|
|
486
|
+
totalPush.add(push.multiply(weight));
|
|
487
|
+
}
|
|
488
|
+
return obstacle;
|
|
489
|
+
};
|
|
490
|
+
const area = this.mapInstance.tileheight * 2;
|
|
491
|
+
this.mapInstance.gridTiles.getCells({
|
|
492
|
+
minX: nextPosition.x - area,
|
|
493
|
+
maxX: nextPosition.x + area,
|
|
494
|
+
minY: nextPosition.y - area,
|
|
495
|
+
maxY: nextPosition.y + area
|
|
496
|
+
}, (index) => {
|
|
497
|
+
if (index < 0)
|
|
498
|
+
return;
|
|
499
|
+
const pos = this.mapInstance.getTilePosition(index);
|
|
500
|
+
const hitbox = Hit_1.Hit.createObjectHitbox(pos.x, pos.y, nextPosition.z, this.hitbox.w, this.hitbox.h);
|
|
501
|
+
const radius = this.mapInstance.tilewidth / 2;
|
|
502
|
+
const tile = this.getTile(pos.x, pos.y, nextPosition.z, hitbox);
|
|
503
|
+
if (tile.hasCollision) {
|
|
504
|
+
createObstacle(pos.x, pos.y, radius);
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
508
|
+
yield this.collisionObjects(playerSizeBox, hitbox, {
|
|
509
|
+
collision: (event) => {
|
|
510
|
+
const { x, y } = event.position;
|
|
511
|
+
createObstacle(x, y, event.hitbox.w);
|
|
512
|
+
},
|
|
513
|
+
allSearch: true
|
|
514
|
+
});
|
|
515
|
+
yield this.collisionShapes(playerSizeBox, nextPosition, {
|
|
516
|
+
collision: (shape) => {
|
|
517
|
+
const { x, y } = shape.position;
|
|
518
|
+
createObstacle(x, y, shape.hitbox.w);
|
|
519
|
+
},
|
|
520
|
+
allSearch: true
|
|
521
|
+
});
|
|
522
|
+
pull
|
|
523
|
+
.multiply(Math.max(1, 4 * contenders))
|
|
524
|
+
.add(totalPush)
|
|
525
|
+
.normalize();
|
|
526
|
+
return nextPosition.add(pull.multiply(this.speed));
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
isCollided(nextPosition, options = {}) {
|
|
530
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
531
|
+
this.collisionWith = [];
|
|
532
|
+
this._collisionWithTiles = [];
|
|
533
|
+
const prevMapId = this.map;
|
|
534
|
+
const hitbox = Hit_1.Hit.createObjectHitbox(nextPosition.x, nextPosition.y, 0, this.hitbox.w, this.hitbox.h);
|
|
535
|
+
const boundingMap = this.mapInstance.boundingMap(nextPosition, this.hitbox);
|
|
536
|
+
let collided = false;
|
|
537
|
+
if (boundingMap === null || boundingMap === void 0 ? void 0 : boundingMap.bounding) {
|
|
538
|
+
this.position.set(nextPosition);
|
|
539
|
+
if (!options.allSearch)
|
|
540
|
+
return true;
|
|
541
|
+
else
|
|
542
|
+
collided = true;
|
|
543
|
+
}
|
|
544
|
+
const tileCollision = (x, y) => {
|
|
545
|
+
const tile = this.getTile(x, y, nextPosition.z, hitbox);
|
|
546
|
+
if (tile.hasCollision) {
|
|
547
|
+
this._collisionWithTiles.push(tile);
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
return false;
|
|
551
|
+
};
|
|
552
|
+
if (tileCollision(nextPosition.x, nextPosition.y) ||
|
|
553
|
+
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y) ||
|
|
554
|
+
tileCollision(nextPosition.x, nextPosition.y + this.hitbox.h) ||
|
|
555
|
+
tileCollision(nextPosition.x + this.hitbox.w, nextPosition.y + this.hitbox.h)) {
|
|
556
|
+
if (!options.allSearch)
|
|
557
|
+
return true;
|
|
558
|
+
else
|
|
559
|
+
collided = true;
|
|
560
|
+
}
|
|
561
|
+
if (this.autoChangeMap) {
|
|
562
|
+
const changeMap = yield this.autoChangeMap(nextPosition);
|
|
563
|
+
if (changeMap) {
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
const playerSizeBox = this.getSizeMaxShape(nextPosition.x, nextPosition.y);
|
|
568
|
+
if (yield this.collisionObjects(playerSizeBox, hitbox, options)) {
|
|
569
|
+
if (!options.allSearch)
|
|
570
|
+
return true;
|
|
571
|
+
else
|
|
572
|
+
collided = true;
|
|
573
|
+
}
|
|
574
|
+
if (yield this.collisionShapes(playerSizeBox, nextPosition, options)) {
|
|
575
|
+
if (!options.allSearch)
|
|
576
|
+
return true;
|
|
577
|
+
else
|
|
578
|
+
collided = true;
|
|
579
|
+
}
|
|
580
|
+
// if there is a change of map after a move, the moves are not changed
|
|
581
|
+
if (prevMapId != this.map) {
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
return collided;
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Attach a shape to the player (and allow interaction with it)
|
|
589
|
+
*
|
|
590
|
+
* ```ts
|
|
591
|
+
* import { ShapePositioning } from '@rpgjs/server'
|
|
592
|
+
*
|
|
593
|
+
* player.attachShape({
|
|
594
|
+
* width: 100,
|
|
595
|
+
* height: 100,
|
|
596
|
+
* positioning: ShapePositioning.Center
|
|
597
|
+
* })
|
|
598
|
+
* ```
|
|
599
|
+
*
|
|
600
|
+
* @title Attach Shape
|
|
601
|
+
* @method player.attachShape(parameters)
|
|
602
|
+
* @param { { width: number, height: number, positioning?, name?, properties?: object } } obj
|
|
603
|
+
* - positioning: Indicate where the shape is placed.
|
|
604
|
+
* - properties: An object in order to retrieve information when interacting with the shape
|
|
605
|
+
* - name: The name of the shape
|
|
606
|
+
* @since 3.0.0-beta.3
|
|
607
|
+
* @returns {RpgShape}
|
|
608
|
+
* @memberof Player
|
|
609
|
+
*/
|
|
610
|
+
attachShape(obj) {
|
|
611
|
+
obj.name = (obj.name || Utils_1.generateUID());
|
|
612
|
+
const shape = new Shape_1.RpgShape(Object.assign(Object.assign({}, obj), { fixEvent: this }));
|
|
613
|
+
this.shapes.push(shape);
|
|
614
|
+
return shape;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Returns all shapes assigned to this player
|
|
618
|
+
*
|
|
619
|
+
* @title Get Shapes
|
|
620
|
+
* @method player.getShapes()
|
|
621
|
+
* @returns {RpgShape[]}
|
|
622
|
+
* @since 3.0.0-beta.3
|
|
623
|
+
* @memberof Player
|
|
624
|
+
* @memberof RpgSpriteLogic
|
|
625
|
+
*/
|
|
626
|
+
getShapes() {
|
|
627
|
+
return this.shapes;
|
|
628
|
+
}
|
|
629
|
+
autoChangeDirection(nextPosition) {
|
|
630
|
+
const { x, y } = this.position;
|
|
631
|
+
const { x: nx, y: ny } = nextPosition;
|
|
632
|
+
const diff = Math.abs(x - nx) > Math.abs(y - ny);
|
|
633
|
+
if (diff) {
|
|
634
|
+
if (nx > x) {
|
|
635
|
+
this.changeDirection(types_1.Direction.Right);
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
this.changeDirection(types_1.Direction.Left);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
if (ny > y) {
|
|
643
|
+
this.changeDirection(types_1.Direction.Down);
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
this.changeDirection(types_1.Direction.Up);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Stops the movement of the player who moves towards his target
|
|
652
|
+
*
|
|
653
|
+
* @title Stop Move To
|
|
654
|
+
* @method player.stopMoveTo()
|
|
655
|
+
* @returns {void}
|
|
656
|
+
* @since 3.2.0
|
|
657
|
+
* @memberof MoveManager
|
|
658
|
+
*/
|
|
659
|
+
stopMoveTo() {
|
|
660
|
+
if (this.destroyMove$.closed)
|
|
661
|
+
return;
|
|
662
|
+
this.destroyMove$.next(true);
|
|
663
|
+
this.destroyMove$.unsubscribe();
|
|
664
|
+
}
|
|
665
|
+
_moveTo(tick$, positionTarget, options = {}) {
|
|
666
|
+
let i = 0;
|
|
667
|
+
let count = 0;
|
|
668
|
+
const lastPositions = [];
|
|
669
|
+
this.stopMoveTo();
|
|
670
|
+
this.destroyMove$ = new rxjs_1.Subject();
|
|
671
|
+
const { infinite, onStuck, onComplete } = options;
|
|
672
|
+
const getPosition = () => {
|
|
673
|
+
let pos;
|
|
674
|
+
if ('x' in positionTarget) {
|
|
675
|
+
pos = new Vector2d_1.Vector2d(positionTarget.x, positionTarget.y);
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
pos = positionTarget.position;
|
|
679
|
+
}
|
|
680
|
+
return pos;
|
|
681
|
+
};
|
|
682
|
+
return tick$
|
|
683
|
+
.pipe(rxjs_1.takeUntil(this.destroyMove$), rxjs_1.mergeMap(() => rxjs_1.from(this.computeNextPositionByTarget(this.position.copy(), getPosition()))), rxjs_1.map((position) => {
|
|
684
|
+
this.autoChangeDirection(position);
|
|
685
|
+
return this.position.set(position);
|
|
686
|
+
}), rxjs_1.tap((position) => {
|
|
687
|
+
lastPositions[i] = position.copy();
|
|
688
|
+
i++;
|
|
689
|
+
count++;
|
|
690
|
+
if (i >= 3) {
|
|
691
|
+
i = 0;
|
|
692
|
+
}
|
|
693
|
+
if (lastPositions[2] && lastPositions[0].isEqual(lastPositions[2])) {
|
|
694
|
+
onStuck === null || onStuck === void 0 ? void 0 : onStuck(count);
|
|
695
|
+
}
|
|
696
|
+
else if (this.position.isEqual(getPosition())) {
|
|
697
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
698
|
+
if (!infinite) {
|
|
699
|
+
this.stopMoveTo();
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
count = 0;
|
|
704
|
+
}
|
|
705
|
+
}));
|
|
706
|
+
}
|
|
707
|
+
/** @internal */
|
|
708
|
+
move(nextPosition) {
|
|
709
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
710
|
+
this.autoChangeDirection(nextPosition);
|
|
711
|
+
const notCollided = !(yield this.isCollided(nextPosition));
|
|
712
|
+
if (notCollided || !this.checkCollision) {
|
|
713
|
+
this.position = nextPosition.copy();
|
|
714
|
+
yield Plugin_1.RpgPlugin.emit(Plugin_1.HookServer.PlayerMove, this);
|
|
715
|
+
}
|
|
716
|
+
return true;
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Retrieves all shapes where the player is located
|
|
721
|
+
*
|
|
722
|
+
* @title Get In-Shapes
|
|
723
|
+
* @method player.getInShapes()
|
|
724
|
+
* @returns {RpgShape[]}
|
|
725
|
+
* @since 3.0.0-beta.3
|
|
726
|
+
* @memberof Player
|
|
727
|
+
*/
|
|
728
|
+
getInShapes() {
|
|
729
|
+
return Object.values(this.inShapes);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Get the current direction.
|
|
733
|
+
*
|
|
734
|
+
* ```ts
|
|
735
|
+
* player.getDirection()
|
|
736
|
+
* ```
|
|
737
|
+
*
|
|
738
|
+
* @title Get Direction
|
|
739
|
+
* @method player.getDirection()
|
|
740
|
+
* @returns {Direction | number} direction
|
|
741
|
+
* @memberof Player
|
|
742
|
+
*/
|
|
743
|
+
getDirection(direction) {
|
|
744
|
+
return direction || this.direction;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Changes the player's direction
|
|
748
|
+
*
|
|
749
|
+
* ```ts
|
|
750
|
+
* import { Direction } from '@rpgjs/server'
|
|
751
|
+
*
|
|
752
|
+
* player.changeDirection(Direction.Left)
|
|
753
|
+
* ```
|
|
754
|
+
*
|
|
755
|
+
* @title Change direction
|
|
756
|
+
* @method player.changeDirection(direction)
|
|
757
|
+
* @param {Direction} direction
|
|
758
|
+
* @enum {string}
|
|
759
|
+
*
|
|
760
|
+
* Direction.Left | left
|
|
761
|
+
* Direction.Right | right
|
|
762
|
+
* Direction.Up | up
|
|
763
|
+
* Direction.Down | down
|
|
764
|
+
* @returns {boolean} the direction has changed
|
|
765
|
+
* @memberof Player
|
|
766
|
+
*/
|
|
767
|
+
changeDirection(direction) {
|
|
768
|
+
const dir = +this.getDirection(direction);
|
|
769
|
+
if (dir === undefined)
|
|
770
|
+
return false;
|
|
771
|
+
this.direction = dir;
|
|
772
|
+
return true;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Gets the necessary number of pixels to allow the player to cross a tile.
|
|
776
|
+
* This is the ratio between the height or width of the tile and the speed of the player.
|
|
777
|
+
*/
|
|
778
|
+
get nbPixelInTile() {
|
|
779
|
+
const direction = this.getDirection();
|
|
780
|
+
switch (direction) {
|
|
781
|
+
case types_1.Direction.Down:
|
|
782
|
+
case types_1.Direction.Up:
|
|
783
|
+
return Math.floor(this.mapInstance.tileHeight / this.speed);
|
|
784
|
+
case types_1.Direction.Left:
|
|
785
|
+
case types_1.Direction.Right:
|
|
786
|
+
return Math.floor(this.mapInstance.tileWidth / this.speed);
|
|
787
|
+
default:
|
|
788
|
+
return NaN;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
getSizeMaxShape(x, y) {
|
|
792
|
+
const _x = x || this.position.x;
|
|
793
|
+
const _y = y || this.position.y;
|
|
794
|
+
let minX = _x;
|
|
795
|
+
let minY = _y;
|
|
796
|
+
let maxX = _x + this.wHitbox;
|
|
797
|
+
let maxY = _y + this.hHitbox;
|
|
798
|
+
const shapes = this.getShapes();
|
|
799
|
+
for (let shape of shapes) {
|
|
800
|
+
if (shape.x < minX)
|
|
801
|
+
minX = shape.x;
|
|
802
|
+
if (shape.y < minY)
|
|
803
|
+
minY = shape.y;
|
|
804
|
+
const shapeMaxX = shape.x + shape.width;
|
|
805
|
+
const shapeMaxY = shape.y + shape.height;
|
|
806
|
+
if (shapeMaxX > maxX)
|
|
807
|
+
maxX = shapeMaxX;
|
|
808
|
+
if (shapeMaxY > maxY)
|
|
809
|
+
maxY = shapeMaxY;
|
|
810
|
+
}
|
|
811
|
+
return {
|
|
812
|
+
minX,
|
|
813
|
+
minY,
|
|
814
|
+
maxX,
|
|
815
|
+
maxY
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
/** @internal */
|
|
819
|
+
execMethod(methodName, methodData, instance) {
|
|
820
|
+
return __awaiter(this, void 0, void 0, function* () { });
|
|
821
|
+
}
|
|
822
|
+
/** @internal */
|
|
823
|
+
onAction() { }
|
|
824
|
+
/** @internal */
|
|
825
|
+
onPlayerTouch() { }
|
|
826
|
+
}
|
|
827
|
+
exports.AbstractObject = AbstractObject;
|
|
828
|
+
//# sourceMappingURL=AbstractObject.js.map
|