@rpgjs/client 3.3.2 → 4.0.0-beta.3

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.
Files changed (164) hide show
  1. package/LICENSE +19 -0
  2. package/lib/Components/AbstractComponent.d.ts +3 -2
  3. package/lib/Components/AbstractComponent.js +17 -28
  4. package/lib/Components/AbstractComponent.js.map +1 -1
  5. package/lib/Components/BarComponent.d.ts +2 -1
  6. package/lib/Components/BarComponent.js +32 -33
  7. package/lib/Components/BarComponent.js.map +1 -1
  8. package/lib/Components/Component.d.ts +3 -3
  9. package/lib/Components/Component.js +84 -96
  10. package/lib/Components/Component.js.map +1 -1
  11. package/lib/Components/DebugComponent.d.ts +2 -1
  12. package/lib/Components/DebugComponent.js +9 -10
  13. package/lib/Components/DebugComponent.js.map +1 -1
  14. package/lib/Components/ImageComponent.d.ts +2 -1
  15. package/lib/Components/ImageComponent.js +5 -7
  16. package/lib/Components/ImageComponent.js.map +1 -1
  17. package/lib/Components/ShapeComponent.d.ts +2 -1
  18. package/lib/Components/ShapeComponent.js +14 -14
  19. package/lib/Components/ShapeComponent.js.map +1 -1
  20. package/lib/Components/TextComponent.d.ts +3 -2
  21. package/lib/Components/TextComponent.js +10 -9
  22. package/lib/Components/TextComponent.js.map +1 -1
  23. package/lib/Components/TileComponent.d.ts +2 -1
  24. package/lib/Components/TileComponent.js +12 -16
  25. package/lib/Components/TileComponent.js.map +1 -1
  26. package/lib/Effects/Animation.d.ts +10 -9
  27. package/lib/Effects/Animation.js +36 -36
  28. package/lib/Effects/Animation.js.map +1 -1
  29. package/lib/Effects/AnimationCharacter.js +2 -5
  30. package/lib/Effects/AnimationCharacter.js.map +1 -1
  31. package/lib/Effects/Spinner.d.ts +3 -2
  32. package/lib/Effects/Spinner.js +2 -5
  33. package/lib/Effects/Spinner.js.map +1 -1
  34. package/lib/Effects/Timeline.d.ts +1 -1
  35. package/lib/Effects/Timeline.js +6 -10
  36. package/lib/Effects/Timeline.js.map +1 -1
  37. package/lib/Effects/TransitionScene.d.ts +2 -1
  38. package/lib/Effects/TransitionScene.js +3 -7
  39. package/lib/Effects/TransitionScene.js.map +1 -1
  40. package/lib/GameEngine.js +51 -26
  41. package/lib/GameEngine.js.map +1 -1
  42. package/lib/Interfaces/Character.js +1 -2
  43. package/lib/Interfaces/Scene.js +1 -2
  44. package/lib/KeyboardControls.d.ts +2 -1
  45. package/lib/KeyboardControls.js +47 -45
  46. package/lib/KeyboardControls.js.map +1 -1
  47. package/lib/Logger.js +1 -5
  48. package/lib/Logger.js.map +1 -1
  49. package/lib/Presets/AnimationSpritesheet.js +9 -13
  50. package/lib/Presets/AnimationSpritesheet.js.map +1 -1
  51. package/lib/Presets/Scene.js +2 -5
  52. package/lib/Presets/Scene.js.map +1 -1
  53. package/lib/Renderer.d.ts +5 -3
  54. package/lib/Renderer.js +68 -60
  55. package/lib/Renderer.js.map +1 -1
  56. package/lib/Resources.js +1 -5
  57. package/lib/Resources.js.map +1 -1
  58. package/lib/RpgClient.d.ts +3 -2
  59. package/lib/RpgClient.js +1 -2
  60. package/lib/RpgClientEngine.d.ts +2 -1
  61. package/lib/RpgClientEngine.js +192 -176
  62. package/lib/RpgClientEngine.js.map +1 -1
  63. package/lib/RpgGui.js +40 -41
  64. package/lib/RpgGui.js.map +1 -1
  65. package/lib/Scene/EventLayer.d.ts +4 -0
  66. package/lib/Scene/EventLayer.js +8 -0
  67. package/lib/Scene/EventLayer.js.map +1 -0
  68. package/lib/Scene/Map.d.ts +17 -3
  69. package/lib/Scene/Map.js +157 -113
  70. package/lib/Scene/Map.js.map +1 -1
  71. package/lib/Scene/Scene.d.ts +3 -3
  72. package/lib/Scene/Scene.js +24 -20
  73. package/lib/Scene/Scene.js.map +1 -1
  74. package/lib/Scene/SceneData.js +1 -5
  75. package/lib/Scene/SceneData.js.map +1 -1
  76. package/lib/Sound/RpgSound.js +8 -11
  77. package/lib/Sound/RpgSound.js.map +1 -1
  78. package/lib/Sound/Sound.d.ts +2 -2
  79. package/lib/Sound/Sound.js +1 -5
  80. package/lib/Sound/Sound.js.map +1 -1
  81. package/lib/Sound/Sounds.js +4 -8
  82. package/lib/Sound/Sounds.js.map +1 -1
  83. package/lib/Sprite/Character.d.ts +3 -2
  84. package/lib/Sprite/Character.js +15 -16
  85. package/lib/Sprite/Character.js.map +1 -1
  86. package/lib/Sprite/Player.js +2 -9
  87. package/lib/Sprite/Player.js.map +1 -1
  88. package/lib/Sprite/Spritesheet.d.ts +4 -4
  89. package/lib/Sprite/Spritesheet.js +1 -5
  90. package/lib/Sprite/Spritesheet.js.map +1 -1
  91. package/lib/Sprite/Spritesheets.js +4 -8
  92. package/lib/Sprite/Spritesheets.js.map +1 -1
  93. package/lib/Tilemap/CommonLayer.d.ts +2 -1
  94. package/lib/Tilemap/CommonLayer.js +7 -11
  95. package/lib/Tilemap/CommonLayer.js.map +1 -1
  96. package/lib/Tilemap/ImageLayer.js +5 -7
  97. package/lib/Tilemap/ImageLayer.js.map +1 -1
  98. package/lib/Tilemap/Tile.d.ts +5 -5
  99. package/lib/Tilemap/Tile.js +19 -21
  100. package/lib/Tilemap/Tile.js.map +1 -1
  101. package/lib/Tilemap/TileLayer.d.ts +0 -7
  102. package/lib/Tilemap/TileLayer.js +27 -29
  103. package/lib/Tilemap/TileLayer.js.map +1 -1
  104. package/lib/Tilemap/TileSet.d.ts +2 -1
  105. package/lib/Tilemap/TileSet.js +9 -12
  106. package/lib/Tilemap/TileSet.js.map +1 -1
  107. package/lib/Tilemap/index.d.ts +3 -11
  108. package/lib/Tilemap/index.js +22 -61
  109. package/lib/Tilemap/index.js.map +1 -1
  110. package/lib/clientEntryPoint.js +26 -28
  111. package/lib/clientEntryPoint.js.map +1 -1
  112. package/lib/index.js +21 -75
  113. package/lib/index.js.map +1 -1
  114. package/package.json +19 -19
  115. package/src/Components/AbstractComponent.ts +120 -0
  116. package/src/Components/BarComponent.ts +179 -0
  117. package/src/Components/Component.ts +506 -0
  118. package/src/Components/DebugComponent.ts +36 -0
  119. package/src/Components/ImageComponent.ts +30 -0
  120. package/src/Components/ShapeComponent.ts +64 -0
  121. package/src/Components/TextComponent.ts +33 -0
  122. package/src/Components/TileComponent.ts +43 -0
  123. package/src/Effects/Animation.ts +297 -0
  124. package/src/Effects/AnimationCharacter.ts +7 -0
  125. package/src/Effects/Spinner.ts +19 -0
  126. package/src/Effects/Timeline.ts +294 -0
  127. package/src/Effects/TransitionScene.ts +57 -0
  128. package/src/GameEngine.ts +284 -0
  129. package/src/Interfaces/Character.ts +7 -0
  130. package/src/Interfaces/Scene.ts +9 -0
  131. package/src/KeyboardControls.ts +552 -0
  132. package/src/Logger.ts +3 -0
  133. package/src/Presets/AnimationSpritesheet.ts +36 -0
  134. package/src/Presets/Scene.ts +3 -0
  135. package/src/Renderer.ts +263 -0
  136. package/src/Resources.ts +40 -0
  137. package/src/RpgClient.ts +333 -0
  138. package/src/RpgClientEngine.ts +709 -0
  139. package/src/RpgGui.ts +553 -0
  140. package/src/RpgGuiCompiled.ts +43 -0
  141. package/src/Scene/EventLayer.ts +9 -0
  142. package/src/Scene/Map.ts +393 -0
  143. package/src/Scene/Scene.ts +270 -0
  144. package/src/Scene/SceneData.ts +13 -0
  145. package/src/Sound/RpgSound.ts +50 -0
  146. package/src/Sound/Sound.ts +91 -0
  147. package/src/Sound/Sounds.ts +7 -0
  148. package/src/Sprite/Character.ts +149 -0
  149. package/src/Sprite/Player.ts +3 -0
  150. package/src/Sprite/Spritesheet.ts +392 -0
  151. package/src/Sprite/Spritesheets.ts +8 -0
  152. package/src/Tilemap/CommonLayer.ts +20 -0
  153. package/src/Tilemap/ImageLayer.ts +20 -0
  154. package/src/Tilemap/Tile.ts +80 -0
  155. package/src/Tilemap/TileLayer.ts +142 -0
  156. package/src/Tilemap/TileSet.ts +40 -0
  157. package/src/Tilemap/index.ts +173 -0
  158. package/src/clientEntryPoint.ts +141 -0
  159. package/src/index.ts +25 -0
  160. package/src/types/howler.d.ts +73 -0
  161. package/tsconfig.json +30 -0
  162. package/lib/Components/ColorComponent.d.ts +0 -9
  163. package/lib/Components/ColorComponent.js +0 -18
  164. package/lib/Components/ColorComponent.js.map +0 -1
@@ -0,0 +1,506 @@
1
+ import { Direction, HookClient, RpgCommonPlayer, RpgPlugin, RpgShape, Utils } from "@rpgjs/common"
2
+ import { ComponentObject, LayoutObject, LayoutOptions, LayoutPositionEnum, PlayerType, PositionXY } from "@rpgjs/types"
3
+ import { Subject, Subscription, map, filter, tap, distinctUntilChanged, takeUntil, finalize } from "rxjs"
4
+ import { log } from "../Logger"
5
+ import { Scene } from "../Scene/Scene"
6
+ import { RpgSprite } from "../Sprite/Player"
7
+ import { AbstractComponent } from "./AbstractComponent"
8
+ import { BarComponent } from "./BarComponent"
9
+ import { ShapeComponent } from "./ShapeComponent"
10
+ import { DebugComponent } from "./DebugComponent"
11
+ import { ImageComponent } from "./ImageComponent"
12
+ import { TextComponent } from "./TextComponent"
13
+ import { TileComponent } from "./TileComponent"
14
+ import { Container, Sprite } from "pixi.js"
15
+
16
+ type SpriteInfo = {
17
+ width: number,
18
+ height: number,
19
+ x: number,
20
+ y: number,
21
+ anchor: { x: number, y: number },
22
+ spriteWidth: number
23
+ spriteHeight: number
24
+ }
25
+
26
+ export interface IComponent {
27
+ id: string,
28
+ value: any
29
+ }
30
+
31
+ const layoutObject = {
32
+ lines: []
33
+ }
34
+
35
+ const layoutTypes: LayoutPositionEnum[] = ['top', 'bottom', 'left', 'right']
36
+
37
+ export class RpgComponent<T = any> extends Container {
38
+ /** @internal */
39
+ tilesOverlay: any
40
+ /** @internal */
41
+ h: number = 1
42
+ /** @internal */
43
+ w: number = 1
44
+ protected _x: number = 0
45
+ protected _y: number = 0
46
+ private _rotation: number = 0
47
+ protected teleported: number = 0
48
+ protected map: string = ''
49
+ protected z: number = 0
50
+ protected fixed: boolean = false
51
+ private components: LayoutObject<any> = {
52
+ top: layoutObject,
53
+ bottom: layoutObject,
54
+ left: layoutObject,
55
+ right: layoutObject,
56
+ center: layoutObject
57
+ }
58
+ private direction: number = 0
59
+ private container: Container = new Container()
60
+
61
+ private containersLayout: {
62
+ [key in LayoutPositionEnum]: Container
63
+ } = {} as any
64
+
65
+ private subscriptionGraphic: Subscription
66
+ private layoutNotifierClear: { [key in LayoutPositionEnum]: Subject<void> } = {
67
+ top: new Subject(),
68
+ bottom: new Subject(),
69
+ left: new Subject(),
70
+ right: new Subject(),
71
+ center: new Subject()
72
+ }
73
+ private registerComponents: Map<string, any> = new Map()
74
+ private dragMode?: {
75
+ data: any,
76
+ dragging: boolean
77
+ }
78
+
79
+ readonly game = this.scene.game
80
+ readonly id: string = this.data.id
81
+
82
+ constructor(private data: RpgCommonPlayer | RpgShape, private scene: Scene) {
83
+ super()
84
+ this.setPosition(false)
85
+ this.registerComponents.set(RpgSprite.id, RpgSprite)
86
+ this.registerComponents.set(TextComponent.id, TextComponent)
87
+ this.registerComponents.set(ShapeComponent.id, ShapeComponent)
88
+ this.registerComponents.set(TileComponent.id, TileComponent)
89
+ this.registerComponents.set(ImageComponent.id, ImageComponent)
90
+ this.registerComponents.set(BarComponent.id, BarComponent)
91
+ this.registerComponents.set(DebugComponent.id, DebugComponent)
92
+
93
+ this.addChild(this.container)
94
+
95
+ for (let layout of [...layoutTypes, 'center']) {
96
+ this.containersLayout[layout] = new Container()
97
+ this.container.addChild(this.containersLayout[layout])
98
+ }
99
+
100
+ RpgPlugin.emit(HookClient.AddSprite, this)
101
+ RpgPlugin.emit(HookClient.SceneAddSprite, [this.scene, this], true)
102
+
103
+ this.game.listenObject(data.id)
104
+ .pipe(
105
+ takeUntil(this.game.getDeleteNotifier(data.id)),
106
+ map(object => object?.paramsChanged),
107
+ tap(() => {
108
+ RpgPlugin.emit(HookClient.ChangesSprite, [this, this.logic?.['paramsChanged'], this.logic?.['prevParamsChanged']], true)
109
+ }),
110
+ filter(object => {
111
+ return this.logic?.['componentChanged']
112
+ })
113
+ )
114
+ .subscribe((val) => {
115
+ if (this.logic) {
116
+ this.updateComponents(this.logic?.['componentChanged'])
117
+ this.logic['componentChanged'] = undefined
118
+ }
119
+ })
120
+
121
+ }
122
+
123
+ /**
124
+ * the direction of the sprite
125
+ *
126
+ * @prop {Direction} dir
127
+ * @readonly
128
+ * @memberof RpgSprite
129
+ * */
130
+ get dir(): Direction {
131
+ return this.direction
132
+ }
133
+
134
+ /**
135
+ * To know if the sprite is a player
136
+ *
137
+ * @prop {boolean} isPlayer
138
+ * @readonly
139
+ * @memberof RpgSprite
140
+ * */
141
+ get isPlayer(): boolean {
142
+ return this.data.type == PlayerType.Player
143
+ }
144
+
145
+ /**
146
+ * To know if the sprite is an event
147
+ *
148
+ * @prop {boolean} isEvent
149
+ * @readonly
150
+ * @memberof RpgSprite
151
+ * */
152
+ get isEvent(): boolean {
153
+ return this.data.type == PlayerType.Event
154
+ }
155
+
156
+ /**
157
+ * To know if the sprite is a shape
158
+ *
159
+ * @prop {boolean} isShape
160
+ * @since 3.0.0-rc
161
+ * @readonly
162
+ * @memberof RpgSprite
163
+ * */
164
+ get isShape(): boolean {
165
+ return Utils.isInstanceOf(this.data, RpgShape)
166
+ }
167
+
168
+ /**
169
+ * To know if the sprite is the sprite controlled by the player
170
+ *
171
+ * @prop {boolean} isCurrentPlayer
172
+ * @readonly
173
+ * @memberof RpgSprite
174
+ * */
175
+ get isCurrentPlayer(): boolean {
176
+ return this.data.id === this.scene.game.playerId
177
+ }
178
+
179
+ /**
180
+ * Retrieves the logic of the sprite
181
+ *
182
+ * @prop {RpgSpriteLogic} logic
183
+ * @readonly
184
+ * @since 3.0.0-beta.4
185
+ * @memberof RpgSprite
186
+ * */
187
+ get logic(): RpgCommonPlayer | RpgShape | null {
188
+ return this.scene.game.world.getAll(this.data.id)
189
+ }
190
+
191
+ get guiDisplay(): boolean {
192
+ return (this.logic as RpgCommonPlayer).guiDisplay
193
+ }
194
+
195
+ set guiDisplay(val: boolean) {
196
+ (this.logic as RpgCommonPlayer).guiDisplay = val
197
+ }
198
+
199
+ setPosition(smooth: boolean = true) {
200
+ if (this.isShape) {
201
+ const { width, height, x, y } = this.data as RpgShape
202
+ this.w = width
203
+ this.h = height
204
+ this._x = Math.floor(x)
205
+ this._y = Math.floor(y)
206
+ }
207
+ else {
208
+ const { position, direction } = this.data as RpgCommonPlayer
209
+ this._x = Math.floor(position?.x ?? 0)
210
+ this._y = Math.floor(position?.y ?? 0)
211
+ this.z = Math.floor(position?.z ?? 0)
212
+ this.direction = direction
213
+ }
214
+ this._rotation = this.data['rotation'] ?? 0
215
+ if (!smooth) {
216
+ this.x = this._x
217
+ this.y = this._y
218
+ this.angle = this._rotation
219
+ }
220
+ }
221
+
222
+ // TODO
223
+ /*drag() {
224
+ this.interactive = true
225
+ const filter = new filters.ColorMatrixFilter();
226
+
227
+ const onDragEnd = () => {
228
+ if (!this.dragMode) return
229
+ this.dragMode.dragging = false
230
+ this.dragMode.data = null
231
+ }
232
+
233
+ this
234
+ .on('pointerdown', (event) => {
235
+ this.dragMode = {
236
+ data: event.data,
237
+ dragging: true
238
+ }
239
+ })
240
+ .on('pointerup', onDragEnd)
241
+ .on('pointerupoutside', onDragEnd)
242
+ .on('pointermove', () => {
243
+ if (!this.dragMode) return
244
+ const { dragging, data } = this.dragMode
245
+ if (dragging) {
246
+ const newPosition = data.getLocalPosition(this.parent)
247
+ this.x = newPosition.x
248
+ this.y = newPosition.y
249
+ }
250
+ })
251
+ }*/
252
+
253
+ update(obj: any, objChanged: any, time: number, deltaRatio: number): { moving: boolean } {
254
+ if (this.dragMode?.dragging) return { moving: true }
255
+
256
+ const { speed, teleported, map, fixed, rotation } = obj
257
+ this.data = obj
258
+ this.setPosition()
259
+ const renderSpeed = speed * deltaRatio
260
+ if (this._rotation != this.angle) {
261
+ this.angle += Math.min(renderSpeed, this._rotation - this.angle)
262
+ }
263
+
264
+ let moving = false
265
+
266
+ if (!fixed) {
267
+ if (teleported != this.teleported || map != this.map) {
268
+ this.x = this._x
269
+ this.y = this._y
270
+ this.teleported = teleported
271
+ this.map = map
272
+ }
273
+
274
+ this.parent.parent.zIndex = this._y
275
+
276
+ obj.posX = this._x
277
+ obj.posY = this._y
278
+
279
+ if (this._x > this.x) {
280
+ this.x += Math.min(renderSpeed, this._x - this.x)
281
+ moving = true
282
+ }
283
+
284
+ if (this._x < this.x) {
285
+ this.x -= Math.min(renderSpeed, this.x - this._x)
286
+ moving = true
287
+ }
288
+
289
+ if (this._y > this.y) {
290
+ this.y += Math.min(renderSpeed, this._y - this.y)
291
+ moving = true
292
+ }
293
+
294
+ if (this._y < this.y) {
295
+ this.y -= Math.min(renderSpeed, this.y - this._y)
296
+ moving = true
297
+ }
298
+ }
299
+
300
+ this.callMethodInComponents('update', [obj, { moving }, deltaRatio])
301
+ this.onUpdate(obj)
302
+
303
+ return {
304
+ moving
305
+ }
306
+ }
307
+
308
+ showAnimation(graphic: string | string[], animationName: string) {
309
+ return this.callMethodInComponents('showAnimation', [graphic, animationName])
310
+ }
311
+
312
+ /**
313
+ * Recover the position according to the graphic
314
+ * Normally, the position is that of the hitbox but, we retrieve the top left corner of the graphic
315
+ *
316
+ * You can also pass the `middle` value as first parameter to retrieve the positions from the middle of the sprite
317
+ *
318
+ * @title Get Positions of Graphic
319
+ * @method sprite.getPositionsOfGraphic(align)
320
+ * @param {string} [align] middle
321
+ * @returns { x: number, y: number }
322
+ * @memberof RpgSprite
323
+ */
324
+ getPositionsOfGraphic(align: string): PositionXY {
325
+ let sprite: RpgSprite | undefined
326
+ // if no component (no graphic for example)
327
+ if (this.components.center?.lines.length !== 0) {
328
+ sprite = this.containersLayout.center.getChildAt(0) as RpgSprite
329
+ }
330
+ const isMiddle = align == 'middle'
331
+ return {
332
+ x: this.x - this.w * (sprite?.anchor.x ?? 1) + (isMiddle ? this.w / 2 : 0),
333
+ y: this.y - this.h * (sprite?.anchor.y ?? 1) + (isMiddle ? this.h / 2 : 0)
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Get the container by position (center, left, right, top, bottom)
339
+ *
340
+ * @param {LayoutPositionEnum} [position=center]
341
+ * @returns {PIXI.Container}
342
+ *
343
+ * */
344
+ getLayoutContainer(position: LayoutPositionEnum = 'center'): Container {
345
+ return this.containersLayout[position]
346
+ }
347
+
348
+ /**
349
+ * Get Current Scene. Scene is a map, battle, menu, etc.
350
+ * @returns {T}
351
+ */
352
+ getScene<T>(): T {
353
+ return this.scene as any
354
+ }
355
+
356
+ // Hooks
357
+ onInit() { }
358
+ onUpdate(obj) { }
359
+ onMove() { }
360
+ onChanges(data, old) { }
361
+
362
+ private callMethodInComponents(name: string, params: unknown[]) {
363
+ for (let component of this.getLayoutContainer().children) {
364
+ if (component[name]) component[name](...params)
365
+ }
366
+ }
367
+
368
+ private createGrid(position: LayoutPositionEnum, gridArray: any, options: LayoutOptions, sprite: SpriteInfo): Container {
369
+ const gridContainer = new Sprite();
370
+ const { height, spriteWidth, spriteHeight } = sprite
371
+ const width = options.width ?? spriteWidth ?? sprite.width
372
+ const gridHeight = options.height ?? 20
373
+ const hitBoxWidth = this.logic?.hitbox.w ?? 0
374
+ const middleWidth = hitBoxWidth / 2 - width / 2
375
+ const posX = gridContainer.x + (options.marginLeft ?? 0) - (options.marginRight ?? 0)
376
+ const posY = gridContainer.y + (this.logic?.hitbox.h ?? 0) + (options.marginTop ?? 0) - (options.marginBottom ?? 0)
377
+
378
+ switch (position) {
379
+ case 'top':
380
+ gridContainer.x = posX + middleWidth
381
+ gridContainer.y = posY - spriteHeight
382
+ gridContainer.y -= (gridArray.length * gridHeight)
383
+ break;
384
+ case 'bottom':
385
+ gridContainer.x = posX + middleWidth
386
+ gridContainer.y = posY
387
+ break;
388
+ case 'left':
389
+ gridContainer.x = posX - width - (hitBoxWidth < spriteWidth ? hitBoxWidth / 2 : 0)
390
+ gridContainer.y = posY - spriteHeight
391
+ break;
392
+ case 'right':
393
+ gridContainer.x = posX + width + (hitBoxWidth > spriteWidth ? hitBoxWidth / 2 : 0)
394
+ gridContainer.y = posY - spriteHeight
395
+ }
396
+
397
+ for (let y = 0; y < gridArray.length; y++) {
398
+ const columns = gridArray[y].col.length;
399
+ const cellWidth = (width / columns);
400
+ for (let x = 0; x < columns; x++) {
401
+ const params: ComponentObject<any> = gridArray[y].col[x];
402
+ const component = this.applyComponent(params)
403
+ component.onRender$
404
+ .pipe(
405
+ takeUntil(this.layoutNotifierClear[position]),
406
+ finalize(() => {
407
+ component.onRemove()
408
+ })
409
+ )
410
+ .subscribe(() => {
411
+ component.x = Math.round((x * cellWidth) + (cellWidth / 2) - (component.width / 2))
412
+ component.y = Math.round((y * gridHeight) + (gridHeight / 2) - (component.height / 2))
413
+ })
414
+ component.onInit({
415
+ width: cellWidth,
416
+ height: gridHeight
417
+ })
418
+ gridContainer.addChild(component)
419
+ }
420
+ }
421
+
422
+ return gridContainer
423
+ }
424
+
425
+ private applyComponent(component: ComponentObject<any>): AbstractComponent<any, any> {
426
+ const compClass = this.registerComponents.get(component.id)
427
+ if (!compClass) {
428
+ throw log(`Impossible to find ${component.id} component`)
429
+ }
430
+ return new compClass(this, component.value)
431
+ }
432
+
433
+ private createComponentCenter(components: LayoutObject<any>) {
434
+ const lines = components.center?.lines || []
435
+
436
+ this.getLayoutContainer().removeChildren()
437
+
438
+ for (let { col } of lines) {
439
+ for (let component of col) {
440
+ const instance = this.applyComponent(component)
441
+ if (instance.onInit) instance.onInit({
442
+ width: this.logic?.width ?? this.width,
443
+ height: this.logic?.height ?? this.height
444
+ })
445
+ this.getLayoutContainer().addChild(instance)
446
+ }
447
+ }
448
+
449
+ this.components = components
450
+ }
451
+
452
+ private refreshComponents(components: LayoutObject<any>, sprite: SpriteInfo) {
453
+ for (let type of layoutTypes) {
454
+ const layout = components[type]
455
+ if (layout?.lines) {
456
+ const layoutContainer = this.getLayoutContainer(type)
457
+ layoutContainer.removeChildren()
458
+ this.layoutNotifierClear[type].next()
459
+ layoutContainer.addChild(this.createGrid(type, layout.lines, layout, sprite))
460
+ }
461
+ }
462
+ }
463
+
464
+ private updateComponents(components: LayoutObject<any>) {
465
+ const graphicChanged: boolean = !!components.center?.lines
466
+
467
+ if (graphicChanged) {
468
+ this.createComponentCenter(components)
469
+ }
470
+
471
+ if (this.subscriptionGraphic) this.subscriptionGraphic.unsubscribe()
472
+
473
+ const child = this.getLayoutContainer().children[0]
474
+
475
+ if (child instanceof RpgSprite) {
476
+ this.subscriptionGraphic = (child as RpgSprite).animationSprite()
477
+ .pipe(
478
+ takeUntil(this.game.getDeleteNotifier(this.id)),
479
+ filter((sprite: any) => sprite),
480
+ distinctUntilChanged((p: any, q: any) =>
481
+ p.width === q.width &&
482
+ p.height === q.height &&
483
+ p.anchor.x === q.anchor.x &&
484
+ p.anchor.y === q.anchor.y),
485
+ )
486
+ .subscribe((sprite) => {
487
+ this.refreshComponents(components, sprite)
488
+ })
489
+ }
490
+ else {
491
+ this.refreshComponents(components, {
492
+ width: this.data.width,
493
+ height: this.data.height,
494
+ anchor: {
495
+ x: 0,
496
+ y: 0
497
+ },
498
+ x: 0,
499
+ y: 0,
500
+ spriteHeight: this.data.height,
501
+ spriteWidth: this.data.width
502
+ })
503
+ }
504
+
505
+ }
506
+ }
@@ -0,0 +1,36 @@
1
+ import { Utils } from "@rpgjs/common"
2
+ import { AbstractComponent, CellInfo } from "./AbstractComponent"
3
+ import { DebugComponentObject } from "@rpgjs/types"
4
+ import { Graphics } from "pixi.js"
5
+
6
+ export class DebugComponent extends AbstractComponent<DebugComponentObject, Graphics> {
7
+ static readonly id: string = 'debug'
8
+ color: string = '#ff0000'
9
+ cacheParams: string[] = ['map', 'position.x', 'position.y']
10
+ private container: Graphics = new Graphics()
11
+
12
+ onInit(cell: CellInfo) {
13
+ this.addChild(this.container)
14
+ this.updateRender(this.component.logic)
15
+ this.eventMode = 'static'
16
+ this.on('pointerdown', () => {
17
+ console.log(this.component.logic)
18
+ })
19
+ super.onInit(cell)
20
+ }
21
+
22
+ updateRender(object: any) {
23
+ const hitbox = object.hitbox
24
+ const { pos, w, h } = hitbox
25
+ this.container.clear()
26
+ const { value: color, alpha } = Utils.hexaToNumber(this.color)
27
+ this.container.beginFill(color, alpha)
28
+ this.container.drawRect(
29
+ 0,
30
+ 0,
31
+ w,
32
+ h
33
+ );
34
+ this.container.endFill()
35
+ }
36
+ }
@@ -0,0 +1,30 @@
1
+ import { Container, Sprite } from "pixi.js"
2
+ import { ImageComponentObject } from "@rpgjs/types"
3
+ import { SceneMap } from "../Scene/Map"
4
+ import { AbstractComponent, CellInfo } from "./AbstractComponent"
5
+
6
+ export class ImageComponent extends AbstractComponent<ImageComponentObject, Container> {
7
+ static readonly id: string = 'image'
8
+ cacheParams: string[] = []
9
+ source: string = ''
10
+
11
+ onInit(cell: CellInfo) {
12
+ super.onInit(cell)
13
+ this.setImage()
14
+ }
15
+
16
+ private setImage() {
17
+ if (typeof this.value == 'string') {
18
+ this.source = this.value
19
+ } else {
20
+ this.source = this.value.source
21
+ }
22
+ this.updateRender({})
23
+ }
24
+
25
+ updateRender(object: any) {
26
+ this.removeChildren()
27
+ const engine = this.component.getScene<SceneMap>().game.clientEngine
28
+ this.addChild(Sprite.from(engine.getResourceUrl(this.source)))
29
+ }
30
+ }
@@ -0,0 +1,64 @@
1
+ import { Utils } from "@rpgjs/common"
2
+ import { AbstractComponent, CellInfo } from "./AbstractComponent"
3
+ import { ShapeComponentObject } from "@rpgjs/types"
4
+ import { Graphics } from "pixi.js"
5
+
6
+ export class ShapeComponent extends AbstractComponent<ShapeComponentObject, Graphics> {
7
+ static readonly id: string = 'shape'
8
+ private type: ShapeComponentObject['value']['type'] = this.value.type
9
+ private container: Graphics = new Graphics()
10
+ cacheParams: string[] = []
11
+
12
+ onInit(cell: CellInfo) {
13
+ this.cell = cell
14
+ this.updateRender(this.component.logic)
15
+ this.addChild(this.container)
16
+ super.onInit(cell)
17
+ }
18
+
19
+ updateRender(object: any) {
20
+ const value = this.value as any
21
+ const height = this.getValue(object, value.height) ?? this.cell?.height ?? 0
22
+ const width = this.getValue(object, value.width) ?? this.cell?.width ?? 0
23
+
24
+ this.container.clear()
25
+ const { value: color, alpha } = Utils.hexaToNumber(this.value.fill)
26
+ this.container.beginFill(color, alpha)
27
+
28
+ if (value.line) {
29
+ const { value: color, alpha } = Utils.hexaToNumber(value.line.color ?? this.value.fill)
30
+ this.container.lineStyle(
31
+ this.getValue(object, value.line.width) ?? 1,
32
+ color,
33
+ this.getValue(object, value.line.alpha) ?? alpha
34
+ )
35
+ }
36
+
37
+ switch (this.type) {
38
+ case 'circle':
39
+ this.container.drawCircle(0, 0, this.getValue(object, value.radius))
40
+ break;
41
+ case 'ellipse':
42
+ this.container.drawEllipse(0, 0, width, height)
43
+ break;
44
+ case 'line':
45
+ if (!value.line) {
46
+ this.container.lineStyle(1, color, alpha)
47
+ }
48
+ this.container.moveTo(this.getValue(object, value.x1), this.getValue(object, value.y1))
49
+ this.container.lineTo(this.getValue(object, value.x2), this.getValue(object, value.y2))
50
+ break;
51
+ case 'polygon':
52
+ this.container.drawPolygon(value.points)
53
+ break;
54
+ case 'rounded-rect':
55
+ this.container.drawRoundedRect(0, 0, width, height, value.radius)
56
+ break;
57
+ default:
58
+ this.container.drawRect(0, 0, width, height)
59
+ break;
60
+ }
61
+
62
+ this.container.endFill()
63
+ }
64
+ }
@@ -0,0 +1,33 @@
1
+ import { TextComponentObject } from "@rpgjs/types"
2
+ import { Graphics, Text } from "pixi.js"
3
+ import { AbstractComponent } from "./AbstractComponent"
4
+
5
+ export class TextComponent extends AbstractComponent<TextComponentObject, Text> {
6
+ static readonly id: string = 'text'
7
+ cacheParams: string[] = []
8
+ private container: Text = new Text('')
9
+ private originValue: string = ''
10
+
11
+ onInit(cell: Graphics) {
12
+ if (typeof this.value == 'string') {
13
+ this.container.text = this.value
14
+ } else if (this.value.style) {
15
+ this.container.style = this.value.style
16
+ this.container.text = this.value.text
17
+ }
18
+ this.container.style = {
19
+ ...this.container.style,
20
+ wordWrapWidth: cell.width
21
+ }
22
+ this.parseTextAndCache(this.container.text)
23
+ this.originValue = this.container.text
24
+ // first render for replace variable and remove {}
25
+ this.updateRender(this.component.logic)
26
+ this.addChild(this.container)
27
+ super.onInit(cell)
28
+ }
29
+
30
+ updateRender(object: any) {
31
+ this.container.text = this.replaceText(object, this.originValue)
32
+ }
33
+ }