@rpgjs/client 5.0.0-alpha.10 → 5.0.0-alpha.2
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/dist/Game/EffectManager.d.ts +5 -0
- package/dist/RpgClient.d.ts +68 -99
- package/dist/RpgClientEngine.d.ts +4 -86
- package/dist/components/effects/index.d.ts +4 -0
- package/dist/components/index.d.ts +1 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/index10.js +1 -1
- package/dist/index11.js +4 -4
- package/dist/index11.js.map +1 -1
- package/dist/index12.js +2 -6
- package/dist/index12.js.map +1 -1
- package/dist/index13.js +2 -2
- package/dist/index13.js.map +1 -1
- package/dist/index14.js +35 -95
- package/dist/index14.js.map +1 -1
- package/dist/index15.js +186 -45
- package/dist/index15.js.map +1 -1
- package/dist/index16.js +5 -187
- package/dist/index16.js.map +1 -1
- package/dist/index17.js +383 -5
- package/dist/index17.js.map +1 -1
- package/dist/index18.js +28 -384
- package/dist/index18.js.map +1 -1
- package/dist/index19.js +17 -24
- package/dist/index19.js.map +1 -1
- package/dist/index2.js +25 -147
- package/dist/index2.js.map +1 -1
- package/dist/index20.js +2413 -16
- package/dist/index20.js.map +1 -1
- package/dist/index21.js +88 -2395
- package/dist/index21.js.map +1 -1
- package/dist/index22.js +103 -108
- package/dist/index22.js.map +1 -1
- package/dist/index23.js +57 -95
- package/dist/index23.js.map +1 -1
- package/dist/index24.js +12 -62
- package/dist/index24.js.map +1 -1
- package/dist/index25.js +37 -18
- package/dist/index25.js.map +1 -1
- package/dist/index26.js +3 -25
- package/dist/index26.js.map +1 -1
- package/dist/index27.js +314 -87
- package/dist/index27.js.map +1 -1
- package/dist/index28.js +21 -37
- package/dist/index28.js.map +1 -1
- package/dist/index29.js +9 -3
- package/dist/index29.js.map +1 -1
- package/dist/index3.js +2 -2
- package/dist/index30.js +6 -317
- package/dist/index30.js.map +1 -1
- package/dist/index31.js +171 -24
- package/dist/index31.js.map +1 -1
- package/dist/index32.js +497 -7
- package/dist/index32.js.map +1 -1
- package/dist/index33.js +9 -8
- package/dist/index33.js.map +1 -1
- package/dist/index34.js +4400 -9
- package/dist/index34.js.map +1 -1
- package/dist/index35.js +307 -4394
- package/dist/index35.js.map +1 -1
- package/dist/index36.js +85 -310
- package/dist/index36.js.map +1 -1
- package/dist/index37.js +56 -169
- package/dist/index37.js.map +1 -1
- package/dist/index38.js +16 -497
- package/dist/index38.js.map +1 -1
- package/dist/index39.js +10 -51
- package/dist/index39.js.map +1 -1
- package/dist/index4.js +5 -18
- package/dist/index4.js.map +1 -1
- package/dist/index5.js +1 -2
- package/dist/index5.js.map +1 -1
- package/dist/index6.js +1 -1
- package/dist/index7.js +2 -10
- package/dist/index7.js.map +1 -1
- package/dist/index8.js +6 -24
- package/dist/index8.js.map +1 -1
- package/dist/index9.js +2 -2
- package/dist/presets/index.d.ts +0 -102
- package/dist/services/loadMap.d.ts +2 -123
- package/dist/services/mmorpg.d.ts +3 -7
- package/package.json +12 -14
- package/src/Game/{AnimationManager.ts → EffectManager.ts} +2 -2
- package/src/Game/Object.ts +0 -69
- package/src/RpgClient.ts +67 -101
- package/src/RpgClientEngine.ts +24 -159
- package/src/components/character.ce +33 -74
- package/src/components/{animations → effects}/animation.ce +5 -3
- package/src/components/{animations → effects}/index.ts +1 -1
- package/src/components/index.ts +1 -2
- package/src/components/scenes/draw-map.ce +23 -6
- package/src/components/scenes/element-map.ce +23 -0
- package/src/components/scenes/event-layer.ce +3 -3
- package/src/core/setup.ts +0 -2
- package/src/index.ts +1 -1
- package/src/module.ts +5 -23
- package/src/presets/index.ts +1 -5
- package/src/services/loadMap.ts +2 -131
- package/src/services/mmorpg.ts +4 -20
- package/tsconfig.json +1 -1
- package/vite.config.ts +1 -1
- package/dist/Game/AnimationManager.d.ts +0 -8
- package/dist/components/animations/index.d.ts +0 -4
- package/dist/index40.js +0 -20
- package/dist/index40.js.map +0 -1
- package/dist/index41.js +0 -82
- package/dist/index41.js.map +0 -1
- package/dist/presets/animation.d.ts +0 -31
- package/dist/presets/lpc.d.ts +0 -89
- package/src/presets/animation.ts +0 -46
- package/src/presets/lpc.ts +0 -108
- /package/src/components/{animations → effects}/hit.ce +0 -0
package/src/RpgClient.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { ComponentFunction } from 'canvasengine'
|
|
2
1
|
import { RpgClientEngine } from './RpgClientEngine'
|
|
3
|
-
import { Loader
|
|
2
|
+
import { Loader } from 'pixi.js'
|
|
4
3
|
|
|
5
4
|
type RpgClass<T = any> = new (...args: any[]) => T
|
|
6
|
-
type RpgComponent =
|
|
7
|
-
type SceneMap =
|
|
5
|
+
type RpgComponent = any
|
|
6
|
+
type SceneMap = any
|
|
8
7
|
|
|
9
8
|
export interface RpgClientEngineHooks {
|
|
10
9
|
/**
|
|
@@ -13,7 +12,7 @@ export interface RpgClientEngineHooks {
|
|
|
13
12
|
* @prop { (engine: RpgClientEngine) => boolean | any } [onStart]
|
|
14
13
|
* @memberof RpgEngineHooks
|
|
15
14
|
*/
|
|
16
|
-
onStart?: (engine: RpgClientEngine) => boolean | void
|
|
15
|
+
onStart?: (engine: RpgClientEngine) => boolean | void
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Each frame
|
|
@@ -66,36 +65,6 @@ export interface RpgClientEngineHooks {
|
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
export interface RpgSpriteHooks {
|
|
69
|
-
/**
|
|
70
|
-
* Array of components to render behind the sprite
|
|
71
|
-
* These components will be displayed with a lower z-index than the sprite itself
|
|
72
|
-
*
|
|
73
|
-
* @prop { ComponentFunction[] } [componentsBehind]
|
|
74
|
-
* @memberof RpgSpriteHooks
|
|
75
|
-
* @example
|
|
76
|
-
* ```ts
|
|
77
|
-
* const sprite: RpgSpriteHooks = {
|
|
78
|
-
* componentsBehind: [ShadowComponent, AuraComponent]
|
|
79
|
-
* }
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
componentsBehind?: ComponentFunction[]
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Array of components to render in front of the sprite
|
|
86
|
-
* These components will be displayed with a higher z-index than the sprite itself
|
|
87
|
-
*
|
|
88
|
-
* @prop { ComponentFunction[] } [componentsInFront]
|
|
89
|
-
* @memberof RpgSpriteHooks
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* const sprite: RpgSpriteHooks = {
|
|
93
|
-
* componentsInFront: [HealthBarComponent, StatusEffectComponent]
|
|
94
|
-
* }
|
|
95
|
-
* ```
|
|
96
|
-
*/
|
|
97
|
-
componentsInFront?: ComponentFunction[]
|
|
98
|
-
|
|
99
68
|
/**
|
|
100
69
|
* As soon as the sprite is initialized
|
|
101
70
|
*
|
|
@@ -209,13 +178,14 @@ export interface RpgClient {
|
|
|
209
178
|
* @example
|
|
210
179
|
*
|
|
211
180
|
* ```ts
|
|
212
|
-
* import { RpgClient,
|
|
181
|
+
* import { RpgClient, RpgModule } from '@rpgjs/client'
|
|
213
182
|
*
|
|
214
|
-
*
|
|
183
|
+
* @RpgModule<RpgClient>({
|
|
215
184
|
* hooks: {
|
|
216
185
|
* player: ['onAuth']
|
|
217
186
|
* }
|
|
218
187
|
* })
|
|
188
|
+
* class RpgClientEngine { }
|
|
219
189
|
* ```
|
|
220
190
|
*
|
|
221
191
|
* Emit the hook:
|
|
@@ -254,7 +224,7 @@ export interface RpgClient {
|
|
|
254
224
|
* Object containing the hooks concerning the engine
|
|
255
225
|
*
|
|
256
226
|
* ```ts
|
|
257
|
-
* import { RpgClientEngine, RpgClientEngineHooks,
|
|
227
|
+
* import { RpgClientEngine, RpgClientEngineHooks, RpgModule, RpgClient } from '@rpgjs/client'
|
|
258
228
|
*
|
|
259
229
|
* const engine: RpgClientEngineHooks = {
|
|
260
230
|
* onConnected(engine: RpgClientEngine) {
|
|
@@ -262,9 +232,10 @@ export interface RpgClient {
|
|
|
262
232
|
* }
|
|
263
233
|
* }
|
|
264
234
|
*
|
|
265
|
-
*
|
|
235
|
+
* @RpgModule<RpgClient>({
|
|
266
236
|
* engine
|
|
267
237
|
* })
|
|
238
|
+
* class RpgClientModule {}
|
|
268
239
|
* ```
|
|
269
240
|
*
|
|
270
241
|
* @prop {RpgClientEngineHooks} [engine]
|
|
@@ -274,32 +245,29 @@ export interface RpgClient {
|
|
|
274
245
|
|
|
275
246
|
/**
|
|
276
247
|
* Array containing the list of spritesheets
|
|
277
|
-
*
|
|
248
|
+
* An element contains a class with the `@Spritesheet` decorator
|
|
278
249
|
*
|
|
279
250
|
* ```ts
|
|
280
|
-
* import {
|
|
251
|
+
* import { Spritesheet, Animation, Direction, RpgClient, RpgModule } from '@rpgjs/client'
|
|
252
|
+
*
|
|
253
|
+
* @Spritesheet({
|
|
254
|
+
* id: 'chest',
|
|
255
|
+
* image: require('./assets/chest.png'),
|
|
256
|
+
* // other options
|
|
257
|
+
* })
|
|
258
|
+
* class Chest { }
|
|
281
259
|
*
|
|
282
|
-
*
|
|
260
|
+
* @RpgModule<RpgClient>({
|
|
283
261
|
* spritesheets: [
|
|
284
|
-
*
|
|
285
|
-
* id: 'chest',
|
|
286
|
-
* image: require('./assets/chest.png'),
|
|
287
|
-
* framesWidth: 32,
|
|
288
|
-
* framesHeight: 32,
|
|
289
|
-
* animations: {
|
|
290
|
-
* default: {
|
|
291
|
-
* frames: [0, 1, 2],
|
|
292
|
-
* duration: 1000
|
|
293
|
-
* }
|
|
294
|
-
* }
|
|
295
|
-
* }
|
|
262
|
+
* Chest
|
|
296
263
|
* ]
|
|
297
264
|
* })
|
|
265
|
+
* class RpgClientEngine {}
|
|
298
266
|
* ```
|
|
299
267
|
*
|
|
300
268
|
* [Guide: Create Sprite](/guide/create-sprite.html)
|
|
301
269
|
*
|
|
302
|
-
* @prop {Array<
|
|
270
|
+
* @prop {Array<Class>} [spritesheets]
|
|
303
271
|
* @memberof RpgClient
|
|
304
272
|
* */
|
|
305
273
|
spritesheets?: any[],
|
|
@@ -307,49 +275,72 @@ export interface RpgClient {
|
|
|
307
275
|
/**
|
|
308
276
|
* Array containing the list of VueJS components
|
|
309
277
|
*
|
|
278
|
+
* ```ts
|
|
279
|
+
* import { RpgClient, RpgModule } from '@rpgjs/client'
|
|
280
|
+
*
|
|
281
|
+
* const component = {
|
|
282
|
+
* name: 'my-gui',
|
|
283
|
+
* template: `
|
|
284
|
+
* <div>
|
|
285
|
+
* Component
|
|
286
|
+
* </div>
|
|
287
|
+
* `
|
|
288
|
+
* }
|
|
289
|
+
*
|
|
290
|
+
* @RpgModule<RpgClient>({
|
|
291
|
+
* gui: [
|
|
292
|
+
* component
|
|
293
|
+
* ]
|
|
294
|
+
* })
|
|
295
|
+
* class RpgClientEngine {}
|
|
296
|
+
* ```
|
|
310
297
|
*
|
|
311
298
|
* [Guide: Create GUI](/guide/create-gui.html)
|
|
312
299
|
*
|
|
313
|
-
* @prop {Array<Component of
|
|
300
|
+
* @prop {Array<Component of VueJS>} [gui]
|
|
314
301
|
* @memberof RpgClient
|
|
315
302
|
* */
|
|
316
|
-
gui?:
|
|
303
|
+
gui?: any[],
|
|
317
304
|
|
|
318
305
|
/**
|
|
319
306
|
* Array containing the list of sounds
|
|
320
|
-
*
|
|
307
|
+
* An element contains a class with the `@Sound` decorator
|
|
321
308
|
*
|
|
322
309
|
* ```ts
|
|
323
|
-
* import {
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
* sounds:
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
310
|
+
* import { Sound, RpgModule, RpgClient } from '@rpgjs/client'
|
|
311
|
+
*
|
|
312
|
+
* @Sound({
|
|
313
|
+
* sounds: {
|
|
314
|
+
* town: require('./assets/Town_Theme.ogg')
|
|
315
|
+
* }
|
|
316
|
+
* })
|
|
317
|
+
* class Sounds {}
|
|
318
|
+
*
|
|
319
|
+
* @RpgModule<RpgClient>({
|
|
320
|
+
* sounds: [ Sounds ]
|
|
332
321
|
* })
|
|
322
|
+
* class RpgClientEngine {}
|
|
333
323
|
* ```
|
|
334
324
|
*
|
|
335
|
-
* @prop {Array<
|
|
325
|
+
* @prop {Array<Class>} [sounds]
|
|
336
326
|
* @memberof RpgClient
|
|
337
327
|
* */
|
|
338
|
-
sounds?:
|
|
328
|
+
sounds?: RpgClass[],
|
|
339
329
|
|
|
340
330
|
/**
|
|
341
331
|
* Give the `RpgSprite` class. A Sprite represents a player or an event
|
|
342
332
|
*
|
|
343
333
|
* ```ts
|
|
344
|
-
* import { RpgSprite, RpgSpriteHooks, RpgClient,
|
|
334
|
+
* import { RpgSprite, RpgSpriteHooks, RpgClient, RpgModule } from '@rpgjs/client'
|
|
345
335
|
*
|
|
346
336
|
* export const sprite: RpgSpriteHooks = {
|
|
347
337
|
* onInit(sprite: RpgSprite) {}
|
|
348
338
|
* }
|
|
349
339
|
*
|
|
350
|
-
*
|
|
340
|
+
* @RpgModule<RpgClient>({
|
|
351
341
|
* sprite
|
|
352
342
|
* })
|
|
343
|
+
* class RpgClientEngine {}
|
|
353
344
|
* ```
|
|
354
345
|
*
|
|
355
346
|
* @prop {RpgSpriteHooks} [sprite]
|
|
@@ -361,18 +352,19 @@ export interface RpgClient {
|
|
|
361
352
|
* Reference the scenes of the game. Here you can put your own class that inherits RpgSceneMap
|
|
362
353
|
*
|
|
363
354
|
* ```ts
|
|
364
|
-
* import { RpgSceneMapHooks, RpgClient,
|
|
355
|
+
* import { RpgSceneMapHooks, RpgClient, RpgModule } from '@rpgjs/client'
|
|
365
356
|
*
|
|
366
357
|
* export const sceneMap: RpgSceneMapHooks = {
|
|
367
358
|
*
|
|
368
359
|
* }
|
|
369
360
|
*
|
|
370
|
-
*
|
|
361
|
+
* @RpgModule<RpgClient>({
|
|
371
362
|
* scenes: {
|
|
372
363
|
* // If you put the RpgSceneMap scene, Thhe key is called mandatory `map`
|
|
373
364
|
* map: sceneMap
|
|
374
365
|
* }
|
|
375
366
|
* })
|
|
367
|
+
* class RpgClientEngine {}
|
|
376
368
|
* ```
|
|
377
369
|
*
|
|
378
370
|
* @prop { [sceneName: string]: RpgSceneMapHooks } [scenes]
|
|
@@ -382,34 +374,8 @@ export interface RpgClient {
|
|
|
382
374
|
map: RpgSceneMapHooks
|
|
383
375
|
}
|
|
384
376
|
|
|
385
|
-
|
|
386
|
-
* Array containing the list of component animations
|
|
387
|
-
* Each element defines a temporary component to display for animations like hits, effects, etc.
|
|
388
|
-
*
|
|
389
|
-
* ```ts
|
|
390
|
-
* import { defineModule, RpgClient } from '@rpgjs/client'
|
|
391
|
-
* import HitComponent from './hit.ce'
|
|
392
|
-
* import ExplosionComponent from './explosion.ce'
|
|
393
|
-
*
|
|
394
|
-
* defineModule<RpgClient>({
|
|
395
|
-
* componentAnimations: [
|
|
396
|
-
* {
|
|
397
|
-
* id: 'hit',
|
|
398
|
-
* component: HitComponent
|
|
399
|
-
* },
|
|
400
|
-
* {
|
|
401
|
-
* id: 'explosion',
|
|
402
|
-
* component: ExplosionComponent
|
|
403
|
-
* }
|
|
404
|
-
* ]
|
|
405
|
-
* })
|
|
406
|
-
* ```
|
|
407
|
-
*
|
|
408
|
-
* @prop {Array<{id: string, component: ComponentFunction}>} [componentAnimations]
|
|
409
|
-
* @memberof RpgClient
|
|
410
|
-
* */
|
|
411
|
-
componentAnimations?: {
|
|
377
|
+
effects?: {
|
|
412
378
|
id: string,
|
|
413
|
-
component:
|
|
379
|
+
component: any
|
|
414
380
|
}[]
|
|
415
381
|
}
|
package/src/RpgClientEngine.ts
CHANGED
|
@@ -7,11 +7,10 @@ import { Hooks, ModulesToken } from "@rpgjs/common";
|
|
|
7
7
|
import { load } from "@signe/sync";
|
|
8
8
|
import { RpgClientMap } from "./Game/Map"
|
|
9
9
|
import { RpgGui } from "./Gui/Gui";
|
|
10
|
-
import {
|
|
11
|
-
import { lastValueFrom
|
|
10
|
+
import { EffectManager } from "./Game/EffectManager";
|
|
11
|
+
import { lastValueFrom } from "rxjs";
|
|
12
12
|
import { GlobalConfigToken } from "./module";
|
|
13
|
-
import
|
|
14
|
-
import { PrebuiltComponentAnimations } from "./components/animations";
|
|
13
|
+
import { ClientIo } from "@signe/room";
|
|
15
14
|
|
|
16
15
|
export class RpgClientEngine<T = any> {
|
|
17
16
|
private guiService: RpgGui;
|
|
@@ -23,21 +22,17 @@ export class RpgClientEngine<T = any> {
|
|
|
23
22
|
public globalConfig: T;
|
|
24
23
|
public sceneComponent: any;
|
|
25
24
|
stopProcessingInput = false;
|
|
25
|
+
|
|
26
26
|
width = signal("100%");
|
|
27
27
|
height = signal("100%");
|
|
28
28
|
spritesheets: Map<string, any> = new Map();
|
|
29
29
|
sounds: Map<string, any> = new Map();
|
|
30
|
-
|
|
30
|
+
effects: any[] = [];
|
|
31
31
|
particleSettings: {
|
|
32
32
|
emitters: any[]
|
|
33
33
|
} = {
|
|
34
34
|
emitters: []
|
|
35
35
|
}
|
|
36
|
-
renderer: PIXI.Renderer;
|
|
37
|
-
tick: Observable<number>;
|
|
38
|
-
playerIdSignal = signal<string | null>(null);
|
|
39
|
-
spriteComponentsBehind = signal<any[]>([]);
|
|
40
|
-
spriteComponentsInFront = signal<any[]>([]);
|
|
41
36
|
|
|
42
37
|
constructor(public context: Context) {
|
|
43
38
|
this.webSocket = inject(context, WebSocketToken);
|
|
@@ -45,37 +40,20 @@ export class RpgClientEngine<T = any> {
|
|
|
45
40
|
this.loadMapService = inject(context, LoadMapToken);
|
|
46
41
|
this.hooks = inject<Hooks>(context, ModulesToken);
|
|
47
42
|
this.globalConfig = inject(context, GlobalConfigToken)
|
|
48
|
-
|
|
49
|
-
this.addComponentAnimation({
|
|
50
|
-
id: "animation",
|
|
51
|
-
component: PrebuiltComponentAnimations.Animation
|
|
52
|
-
})
|
|
53
43
|
}
|
|
54
44
|
|
|
55
45
|
async start() {
|
|
56
46
|
this.selector = document.body.querySelector("#rpg") as HTMLElement;
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
this.renderer = app.renderer as PIXI.Renderer;
|
|
60
|
-
this.tick = canvasElement?.propObservables?.context['tick'].observable
|
|
48
|
+
await bootstrapCanvas(this.selector, Canvas);
|
|
61
49
|
|
|
62
50
|
await lastValueFrom(this.hooks.callHooks("client-engine-onStart", this));
|
|
63
51
|
|
|
64
|
-
// wondow is resize
|
|
65
|
-
window.addEventListener('resize', () => {
|
|
66
|
-
this.hooks.callHooks("client-engine-onWindowResize", this).subscribe();
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
this.tick.subscribe((tick) => {
|
|
70
|
-
this.hooks.callHooks("client-engine-onStep", this, tick).subscribe();
|
|
71
|
-
})
|
|
72
|
-
|
|
73
52
|
this.hooks.callHooks("client-spritesheets-load", this).subscribe();
|
|
74
53
|
this.hooks.callHooks("client-sounds-load", this).subscribe();
|
|
75
54
|
this.hooks.callHooks("client-gui-load", this).subscribe();
|
|
76
55
|
this.hooks.callHooks("client-particles-load", this).subscribe();
|
|
77
|
-
this.hooks.callHooks("client-
|
|
78
|
-
this.hooks.callHooks("client-sprite-load", this).subscribe();
|
|
56
|
+
this.hooks.callHooks("client-effects-load", this).subscribe();
|
|
79
57
|
|
|
80
58
|
|
|
81
59
|
await this.webSocket.connection(() => {
|
|
@@ -86,8 +64,6 @@ export class RpgClientEngine<T = any> {
|
|
|
86
64
|
|
|
87
65
|
private initListeners() {
|
|
88
66
|
this.webSocket.on("sync", (data) => {
|
|
89
|
-
if (data.pId) this.playerIdSignal.set(data.pId)
|
|
90
|
-
this.hooks.callHooks("client-sceneMap-onChanges", this.sceneMap, { partial: data }).subscribe();
|
|
91
67
|
load(this.sceneMap, data, true);
|
|
92
68
|
});
|
|
93
69
|
|
|
@@ -95,32 +71,14 @@ export class RpgClientEngine<T = any> {
|
|
|
95
71
|
this.loadScene(data.mapId);
|
|
96
72
|
});
|
|
97
73
|
|
|
98
|
-
this.webSocket.on("
|
|
99
|
-
const { params, object,
|
|
100
|
-
if (!object
|
|
101
|
-
throw new Error("
|
|
74
|
+
this.webSocket.on("showEffect", (data) => {
|
|
75
|
+
const { params, object, id } = data;
|
|
76
|
+
if (!object) {
|
|
77
|
+
throw new Error("Object not found");
|
|
102
78
|
}
|
|
103
|
-
const player = object ? this.sceneMap.getObjectById(object) : undefined;
|
|
104
|
-
this.getComponentAnimation(id).displayEffect(params, player || position)
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
this.webSocket.on("setAnimation", (data) => {
|
|
108
|
-
const { animationName, nbTimes, object } = data;
|
|
109
79
|
const player = this.sceneMap.getObjectById(object);
|
|
110
|
-
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
this.webSocket.on('open', () => {
|
|
114
|
-
this.hooks.callHooks("client-engine-onConnected", this, this.socket).subscribe();
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
this.webSocket.on('close', () => {
|
|
118
|
-
this.hooks.callHooks("client-engine-onDisconnected", this, this.socket).subscribe();
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
this.webSocket.on('error', (error) => {
|
|
122
|
-
this.hooks.callHooks("client-engine-onConnectError", this, error, this.socket).subscribe();
|
|
123
|
-
})
|
|
80
|
+
this.getEffect(id).displayEffect(params, player)
|
|
81
|
+
});
|
|
124
82
|
}
|
|
125
83
|
|
|
126
84
|
private async loadScene(mapId: string) {
|
|
@@ -150,127 +108,34 @@ export class RpgClientEngine<T = any> {
|
|
|
150
108
|
return particle;
|
|
151
109
|
}
|
|
152
110
|
|
|
153
|
-
|
|
154
|
-
* Add a component to render behind sprites
|
|
155
|
-
* Components added with this method will be displayed with a lower z-index than the sprite
|
|
156
|
-
*
|
|
157
|
-
* @param component - The component to add behind sprites
|
|
158
|
-
* @returns The added component
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* ```ts
|
|
162
|
-
* // Add a shadow component behind all sprites
|
|
163
|
-
* engine.addSpriteComponentBehind(ShadowComponent);
|
|
164
|
-
* ```
|
|
165
|
-
*/
|
|
166
|
-
addSpriteComponentBehind(component: any) {
|
|
167
|
-
this.spriteComponentsBehind.update((components: any[]) => [...components, component])
|
|
168
|
-
return component
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Add a component to render in front of sprites
|
|
173
|
-
* Components added with this method will be displayed with a higher z-index than the sprite
|
|
174
|
-
*
|
|
175
|
-
* @param component - The component to add in front of sprites
|
|
176
|
-
* @returns The added component
|
|
177
|
-
*
|
|
178
|
-
* @example
|
|
179
|
-
* ```ts
|
|
180
|
-
* // Add a health bar component in front of all sprites
|
|
181
|
-
* engine.addSpriteComponentInFront(HealthBarComponent);
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
addSpriteComponentInFront(component: any) {
|
|
185
|
-
this.spriteComponentsInFront.update((components: any[]) => [...components, component])
|
|
186
|
-
return component
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Add a component animation to the engine
|
|
191
|
-
*
|
|
192
|
-
* Component animations are temporary visual effects that can be displayed
|
|
193
|
-
* on sprites or objects, such as hit indicators, spell effects, or status animations.
|
|
194
|
-
*
|
|
195
|
-
* @param componentAnimation - The component animation configuration
|
|
196
|
-
* @param componentAnimation.id - Unique identifier for the animation
|
|
197
|
-
* @param componentAnimation.component - The component function to render
|
|
198
|
-
* @returns The added component animation configuration
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```ts
|
|
202
|
-
* // Add a hit animation component
|
|
203
|
-
* engine.addComponentAnimation({
|
|
204
|
-
* id: 'hit',
|
|
205
|
-
* component: HitComponent
|
|
206
|
-
* });
|
|
207
|
-
*
|
|
208
|
-
* // Add an explosion effect component
|
|
209
|
-
* engine.addComponentAnimation({
|
|
210
|
-
* id: 'explosion',
|
|
211
|
-
* component: ExplosionComponent
|
|
212
|
-
* });
|
|
213
|
-
* ```
|
|
214
|
-
*/
|
|
215
|
-
addComponentAnimation(componentAnimation: {
|
|
111
|
+
addEffect(effect: {
|
|
216
112
|
component: any,
|
|
217
113
|
id: string
|
|
218
114
|
}) {
|
|
219
|
-
const instance = new
|
|
220
|
-
this.
|
|
221
|
-
id:
|
|
222
|
-
component:
|
|
115
|
+
const instance = new EffectManager()
|
|
116
|
+
this.effects.push({
|
|
117
|
+
id: effect.id,
|
|
118
|
+
component: effect.component,
|
|
223
119
|
instance: instance,
|
|
224
120
|
current: instance.current
|
|
225
121
|
})
|
|
226
|
-
return
|
|
122
|
+
return effect;
|
|
227
123
|
}
|
|
228
124
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
* which can be used to display the animation on sprites or objects.
|
|
234
|
-
*
|
|
235
|
-
* @param id - The unique identifier of the component animation
|
|
236
|
-
* @returns The EffectManager instance for the animation
|
|
237
|
-
* @throws Error if the component animation is not found
|
|
238
|
-
*
|
|
239
|
-
* @example
|
|
240
|
-
* ```ts
|
|
241
|
-
* // Get the hit animation and display it
|
|
242
|
-
* const hitAnimation = engine.getComponentAnimation('hit');
|
|
243
|
-
* hitAnimation.displayEffect({ text: "Critical!" }, player);
|
|
244
|
-
* ```
|
|
245
|
-
*/
|
|
246
|
-
getComponentAnimation(id: string): AnimationManager {
|
|
247
|
-
const componentAnimation = this.componentAnimations.find((componentAnimation) => componentAnimation.id === id)
|
|
248
|
-
if (!componentAnimation) {
|
|
249
|
-
throw new Error(`Component animation with id ${id} not found`)
|
|
125
|
+
getEffect(id: string): EffectManager {
|
|
126
|
+
const effect = this.effects.find((effect) => effect.id === id)
|
|
127
|
+
if (!effect) {
|
|
128
|
+
throw new Error(`Effect with id ${id} not found`)
|
|
250
129
|
}
|
|
251
|
-
return
|
|
130
|
+
return effect.instance
|
|
252
131
|
}
|
|
253
132
|
|
|
254
133
|
processInput({ input }: { input: number }) {
|
|
255
|
-
this.hooks.callHooks("client-engine-onInput", this, { input, playerId: this.playerId }).subscribe();
|
|
256
134
|
this.webSocket.emit('move', { input })
|
|
257
135
|
}
|
|
258
136
|
|
|
259
137
|
processAction({ action }: { action: number }) {
|
|
260
138
|
if (this.stopProcessingInput) return;
|
|
261
|
-
this.hooks.callHooks("client-engine-onInput", this, { input: 'action', playerId: this.playerId }).subscribe();
|
|
262
139
|
this.webSocket.emit('action', { action })
|
|
263
140
|
}
|
|
264
|
-
|
|
265
|
-
get PIXI() {
|
|
266
|
-
return PIXI
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
get socket() {
|
|
270
|
-
return this.webSocket
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
get playerId() {
|
|
274
|
-
return this.playerIdSignal()
|
|
275
|
-
}
|
|
276
141
|
}
|
|
@@ -1,57 +1,52 @@
|
|
|
1
1
|
<Container x y zIndex={y} viewportFollow={isMe} controls>
|
|
2
|
-
@for (component of componentsBehind) {
|
|
3
|
-
<Container>
|
|
4
|
-
<component object />
|
|
5
|
-
</Container>
|
|
6
|
-
}
|
|
7
2
|
<Particle emit={@emitParticleTrigger} settings={@particleSettings} zIndex={1000} name={particleName} />
|
|
8
|
-
|
|
9
|
-
@
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
@for (graphicId of graphics) {
|
|
4
|
+
<Sprite sheet={@sheet(@graphicId)} direction tint />
|
|
5
|
+
}
|
|
6
|
+
<!-- <Ellipse
|
|
7
|
+
x={shadow.@x}
|
|
8
|
+
y={shadow.@y}
|
|
9
|
+
width={shadow.@width}
|
|
10
|
+
height={shadow.@height}
|
|
11
|
+
color="black"
|
|
12
|
+
blur={10}
|
|
13
|
+
alpha={0.5}
|
|
14
|
+
/> -->
|
|
18
15
|
</Container>
|
|
19
16
|
|
|
20
17
|
<script>
|
|
21
|
-
import { signal, effect, mount, computed
|
|
18
|
+
import { signal, effect, mount, computed } from "canvasengine";
|
|
22
19
|
import { Particle } from "@canvasengine/presets";
|
|
23
|
-
import { GameEngineToken
|
|
20
|
+
import { GameEngineToken } from "@rpgjs/common";
|
|
24
21
|
import { RpgClientEngine } from "../RpgClientEngine";
|
|
25
22
|
import { inject } from "../core/inject";
|
|
26
23
|
import { Direction } from "@rpgjs/common";
|
|
27
24
|
import Hit from "./effects/hit.ce";
|
|
28
25
|
|
|
29
|
-
const { object, id } = defineProps();
|
|
30
|
-
|
|
26
|
+
const { object, id, isMe } = defineProps();
|
|
27
|
+
|
|
31
28
|
const client = inject(RpgClientEngine);
|
|
32
|
-
const hooks = inject(ModulesToken);
|
|
33
29
|
|
|
34
30
|
const spritesheets = client.spritesheets;
|
|
35
|
-
const playerId = client.playerId;
|
|
36
|
-
const componentsBehind = client.spriteComponentsBehind;
|
|
37
|
-
const componentsInFront = client.spriteComponentsInFront;
|
|
38
|
-
const isMe = computed(() => id() === playerId);
|
|
39
|
-
|
|
40
|
-
const {
|
|
41
|
-
x,
|
|
42
|
-
y,
|
|
43
|
-
tint,
|
|
44
|
-
direction,
|
|
45
|
-
animationName,
|
|
46
|
-
animationCurrentIndex,
|
|
47
|
-
emitParticleTrigger,
|
|
48
|
-
particleName,
|
|
49
|
-
graphics,
|
|
50
|
-
hitbox
|
|
51
|
-
} = object;
|
|
52
31
|
|
|
32
|
+
const x = object.x;
|
|
33
|
+
const y = object.y;
|
|
34
|
+
const tint = object.tint;
|
|
35
|
+
const direction = object.direction;
|
|
36
|
+
const animationName = object.animationName;
|
|
37
|
+
const emitParticleTrigger = object.emitParticleTrigger;
|
|
53
38
|
const particleSettings = client.particleSettings;
|
|
39
|
+
const particleName = object.particleName;
|
|
40
|
+
const graphics = object.graphics;
|
|
54
41
|
|
|
42
|
+
const hitbox = object.hitbox;
|
|
43
|
+
const widthShadow = 10;
|
|
44
|
+
const shadow = computed(() => ({
|
|
45
|
+
x: hitbox().w / 2,
|
|
46
|
+
y: hitbox().h - (hitbox().h / 2),
|
|
47
|
+
width: hitbox().w + widthShadow,
|
|
48
|
+
height: hitbox().h,
|
|
49
|
+
}))
|
|
55
50
|
const canControls = () => isMe() && object.canMove()
|
|
56
51
|
const keyboardControls = client.globalConfig.keyboardControls;
|
|
57
52
|
|
|
@@ -89,7 +84,7 @@
|
|
|
89
84
|
keyDown() {
|
|
90
85
|
if (canControls()) {
|
|
91
86
|
client.processAction({ action: 'action' })
|
|
92
|
-
|
|
87
|
+
// particleName.set('hit')
|
|
93
88
|
// emitParticleTrigger.start()
|
|
94
89
|
// object.flash('red')
|
|
95
90
|
}
|
|
@@ -104,42 +99,6 @@
|
|
|
104
99
|
params: {
|
|
105
100
|
direction
|
|
106
101
|
},
|
|
107
|
-
onFinish() {
|
|
108
|
-
animationCurrentIndex.update(index => index + 1)
|
|
109
|
-
}
|
|
110
102
|
};
|
|
111
103
|
}
|
|
112
|
-
|
|
113
|
-
// Track animation changes to reset animation state when needed
|
|
114
|
-
let previousAnimationName = animationName();
|
|
115
|
-
effect(() => {
|
|
116
|
-
const currentAnimationName = animationName();
|
|
117
|
-
|
|
118
|
-
// If animation changed externally (not through setAnimation), reset the state
|
|
119
|
-
if (currentAnimationName !== previousAnimationName && object.animationIsPlaying && object.animationIsPlaying()) {
|
|
120
|
-
// Check if this is a movement animation (walk, stand) that should interrupt custom animations
|
|
121
|
-
const movementAnimations = ['walk', 'stand'];
|
|
122
|
-
if (movementAnimations.includes(currentAnimationName)) {
|
|
123
|
-
if (typeof object.resetAnimationState === 'function') {
|
|
124
|
-
object.resetAnimationState();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
previousAnimationName = currentAnimationName;
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
mount((element) => {
|
|
133
|
-
hooks.callHooks("client-sprite-onInit", element.componentInstance)
|
|
134
|
-
hooks.callHooks("client-sceneMap-onAddSprite", client.sceneMap, element.componentInstance)
|
|
135
|
-
|
|
136
|
-
return () => {
|
|
137
|
-
hooks.callHooks("client-sprite-onDestroy", element.componentInstance)
|
|
138
|
-
hooks.callHooks("client-sceneMap-onRemoveSprite", client.sceneMap, element.componentInstance)
|
|
139
|
-
}
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
tick(() => {
|
|
143
|
-
hooks.callHooks("client-sprite-onUpdate")
|
|
144
|
-
})
|
|
145
104
|
</script>
|