route-graphics 0.0.8 → 0.0.9

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/README.md CHANGED
@@ -1,118 +1,999 @@
1
- # RouteGraphics
1
+ ## Overview
2
2
 
3
- A 2D graphics rendering interface that takes JSON input and renders pixels using PixiJS.
3
+ Route Graphics is a declarative UI system that enables developers to create rich, interactive 2D interfaces through JSON configurations. Instead of manipulating DOM elements directly, you define your interface structure using JSON, and Route Graphics handles the rendering, animations, audio, and interactions automatically.
4
4
 
5
- ⚠️ **Warning: This library is under active development and will have breaking changes in future versions.**
5
+ ## Typical Usage Patterns
6
6
 
7
- ## Installation
7
+ ### How It Works
8
+
9
+ Route Graphics follows a **render cycle** where:
10
+
11
+ 1. **Parser Functions** convert your JSON input into Abstract Syntax Trees (AST)
12
+ 2. **Element Functions** handle the lifecycle:
13
+ - **Add Functions**: Create new visual elements when they appear in the state
14
+ - **Update Functions**: Modify existing elements when their properties change
15
+ - **Delete Functions**: Remove elements when they're no longer in the state
16
+ 3. **Animation Functions** apply smooth transitions between states
17
+ 4. **Audio Functions** handle sound effects and background music
18
+
19
+ ## Architecture Overview
20
+
21
+ Route Graphics follows a modular plugin architecture with three main plugin categories:
22
+
23
+ 1. **Element Plugins** - Render visual elements with add/update/delete functions
24
+ 2. **Audio Plugins** - Handle audio playback
25
+ 3. **Animation Plugins** - Handle dynamic content and transitions
26
+
27
+ ## Getting Started
28
+
29
+ ### Installation
8
30
 
9
31
  ```bash
10
- npm install route-graphics
32
+ bun install route-graphics
11
33
  ```
12
34
 
13
- ## Usage
35
+ ### Basic Usage
14
36
 
15
37
  ```javascript
16
- import RouteGraphics, {
17
- SpriteRendererPlugin,
18
- TextRendererPlugin,
19
- ContainerRendererPlugin,
20
- TextRevealingRendererPlugin,
21
- GraphicsRendererPlugin,
22
- AudioPlugin,
23
- SliderRendererPlugin,
24
- KeyframeTransitionPlugin,
38
+ import createRouteGraphics, {
39
+ textPlugin,
40
+ rectPlugin,
41
+ spritePlugin,
42
+ sliderPlugin,
43
+ containerPlugin,
44
+ textRevealingPlugin,
45
+ tweenPlugin,
46
+ soundPlugin,
25
47
  createAssetBufferManager,
26
48
  } from 'route-graphics';
27
49
 
28
- // Load assets
50
+ // Define assets with URL and type
29
51
  const assets = {
30
- "file:bg1": {
31
- url: "/public/slider-bar.png",
52
+ "circle-red": {
53
+ url: "/public/circle-red.png",
32
54
  type: "image/png",
33
55
  },
34
- "file:circle-red": {
35
- url: "/public/circle-red.png",
56
+ "circle-blue": {
57
+ url: "/public/circle-blue.png",
58
+ type: "image/png",
59
+ },
60
+ "circle-green": {
61
+ url: "/public/circle-green.png",
36
62
  type: "image/png",
37
63
  },
38
- "file:bgm-1": {
64
+ "slider": {
65
+ url: "/public/slider.png",
66
+ type: "image/png",
67
+ },
68
+ "bgm-1": {
39
69
  url: "/public/bgm-1.mp3",
40
70
  type: "audio/mpeg",
41
71
  },
72
+ "bgm-2": {
73
+ url: "/public/bgm-2.mp3",
74
+ type: "audio/mpeg",
75
+ }
42
76
  };
43
77
 
78
+ // Load assets using asset buffer manager
44
79
  const assetBufferManager = createAssetBufferManager();
45
80
  await assetBufferManager.load(assets);
46
81
  const assetBufferMap = assetBufferManager.getBufferMap();
47
82
 
48
- // Initialize RouteGraphics
49
- const app = new RouteGraphics();
83
+ // Create and initialize app
84
+ const app = createRouteGraphics();
50
85
  await app.init({
51
- width: 1920,
52
- height: 1080,
53
- eventHandler: (event, data) => {
54
- // Handle events
55
- },
56
- plugins: [
57
- new SpriteRendererPlugin(),
58
- new TextRendererPlugin(),
59
- new ContainerRendererPlugin(),
60
- new TextRevealingRendererPlugin(),
61
- new GraphicsRendererPlugin(),
62
- new AudioPlugin(),
63
- new SliderRendererPlugin(),
64
- new KeyframeTransitionPlugin(),
65
- ],
86
+ width: 1280,
87
+ height: 720,
88
+ plugins: {
89
+ elements: [
90
+ textPlugin,
91
+ rectPlugin,
92
+ spritePlugin,
93
+ sliderPlugin,
94
+ containerPlugin,
95
+ textRevealingPlugin
96
+ ],
97
+ animations: [
98
+ tweenPlugin
99
+ ],
100
+ audios: [
101
+ soundPlugin
102
+ ],
103
+ },
104
+ eventHandler: (eventName, payload) => {
105
+ console.log('Event:', eventName, payload);
106
+ }
66
107
  });
67
108
 
68
- // Load assets and render
109
+ // Load assets into the app and add to DOM
69
110
  await app.loadAssets(assetBufferMap);
70
111
  document.body.appendChild(app.canvas);
71
112
 
72
- // Render frame with elements and transitions
113
+ // Render your UI
73
114
  app.render({
74
115
  elements: [
75
116
  {
76
117
  id: "sprite1",
77
118
  type: "sprite",
78
- texture: "file:circle-red",
119
+ src: "file:circle-red",
120
+ x: 100,
121
+ y: 100,
122
+ width: 64,
123
+ height: 64,
124
+ hover: {
125
+ imageSrc: "file:circle-blue",
126
+ soundSrc: "file:hover-sound"
127
+ },
128
+ click: {
129
+ action: "handleClick",
130
+ soundSrc: "file:click-sound"
131
+ }
132
+ }
133
+ ],
134
+ animations: [
135
+ {
136
+ id: "fadeIn",
137
+ targetId: "sprite1",
138
+ type: "tween",
139
+ properties: {
140
+ alpha: {
141
+ initialValue: 0,
142
+ keyframes: [
143
+ { duration: 1000, value: 1, easing: "linear" }
144
+ ]
145
+ }
146
+ }
147
+ }
148
+ ],
149
+ audio: [
150
+ {
151
+ id: "bgMusic",
152
+ type: "sound",
153
+ src: "file:bgm-1",
154
+ volume: 600,
155
+ loop: true
156
+ }
157
+ ]
158
+ });
159
+ ```
160
+
161
+ ## Architecture Overview
162
+
163
+ Route Graphics follows a modular plugin architecture with three main plugin categories:
164
+
165
+ 1. **Parser Plugins** - Convert JSON to Abstract Syntax Trees (AST)
166
+ 2. **Element Plugins** - Render visual elements (add/update/delete)
167
+ 3. **Audio & Animation Plugins** - Handle dynamic content
168
+
169
+
170
+ ### The Render Function
171
+
172
+ The main `render()` function is called whenever you want to update your interface. It automatically:
173
+ - Compares the previous state with the new state
174
+ - Determines which elements to add, update, or remove
175
+ - Executes the appropriate element functions
176
+ - Applies animations and audio effects
177
+
178
+ ```javascript
179
+ // Initial render
180
+ routeGraphics.render(initialState);
181
+
182
+ // Update with new elements
183
+ routeGraphics.render(updatedState); // Automatically adds/updates/removes elements
184
+ ```
185
+
186
+ **Example Lifecycle:**
187
+ ```javascript
188
+ // State 1: Show a button
189
+ const state1 = {
190
+ elements: [{
191
+ id: "button1",
192
+ type: "rect",
193
+ width: 100, height: 40,
194
+ fill: "blue"
195
+ }]
196
+ };
197
+
198
+ // State 2: Button changes color and moves
199
+ const state2 = {
200
+ elements: [{
201
+ id: "button1",
202
+ type: "rect",
203
+ width: 100, height: 40,
204
+ fill: "red", // Update: color changes
205
+ x: 50, y: 50 // Update: position moves
206
+ }]
207
+ };
208
+
209
+ // State 3: Button is gone
210
+ const state3 = {
211
+ elements: [] // Delete: button1 is removed
212
+ };
213
+ ```
214
+
215
+ ## Element Plugins
216
+
217
+ Element plugins handle the creation, updating, and deletion of visual elements. Each plugin follows a consistent interface:
218
+
219
+ ```javascript
220
+ createElementPlugin({
221
+ type: "element-type",
222
+ add: addFunction, // Create element
223
+ update: updateFunction, // Update existing element
224
+ delete: deleteFunction // Remove element
225
+ });
226
+ ```
227
+
228
+ ### Available Element Plugins
229
+
230
+ #### Sprite Plugin
231
+ Renders image-based sprites with rich interactions.
232
+
233
+ **Required Properties:**
234
+ - `id`, `type`, `x`, `y`, `width`, `height`
235
+
236
+ **Optional Properties:**
237
+ - `src`: Source of the sprite image (asset alias)
238
+ - `anchorX`, `anchorY`: Anchor points (default: 0)
239
+ - `alpha`: Opacity/transparency (0-1, default: 1)
240
+
241
+ **Events:**
242
+ - **click**: Triggered when sprite is clicked
243
+ - `src` (string, optional): Change sprite image
244
+ - `soundSrc` (string, optional): Play sound effect
245
+ - `actionPayload` (object, optional): Custom data sent to event handler
246
+ - **hover**: Triggered when mouse enters/exits sprite
247
+ - `src` (string, optional): Change sprite image
248
+ - `soundSrc` (string, optional): Play sound effect
249
+ - `cursor` (string, optional): CSS cursor style
250
+ - `actionPayload` (object, optional): Custom data sent to event handler
251
+
252
+ **Example:**
253
+ ```yaml
254
+ id: character
255
+ type: sprite
256
+ x: 100
257
+ y: 100
258
+ width: 64
259
+ height: 64
260
+ src: hero-idle
261
+ hover:
262
+ src: hero-hover
263
+ cursor: pointer
264
+ soundSrc: hover-sound
265
+ actionPayload:
266
+ action: hoverHero
267
+ click:
268
+ src: hero-active
269
+ soundSrc: click-sound
270
+ actionPayload:
271
+ action: activateHero
272
+ ```
273
+
274
+ **Event Data Structure:**
275
+ - **Click Event:**
276
+ ```yaml
277
+ _event:
278
+ id: character
279
+ # All actionPayload properties are spread directly here
280
+ action: activateHero
281
+ ```
282
+ - **Hover Event:**
283
+ ```yaml
284
+ _event:
285
+ id: character
286
+ # All actionPayload properties are spread directly here
287
+ action: hoverHero
288
+ ```
289
+
290
+ #### Text Plugin
291
+ Renders styled text with comprehensive formatting options.
292
+
293
+ **Required Properties:**
294
+ - `id`, `type`, `x`, `y`
295
+
296
+ **Optional Properties:**
297
+ - `content`: Text content to display (default: "")
298
+ - `width`: Width constraint for text wrapping
299
+ - `anchorX`, `anchorY`: Anchor points (default: 0)
300
+ - `alpha`: Opacity (0-1, default: 1)
301
+ - `textStyle`: Complete text styling object
302
+
303
+ **TextStyle Options:**
304
+ - `fill`: Text color (default: "black")
305
+ - `fontFamily`: Font family
306
+ - `fontSize`: Font size in pixels (default: 16)
307
+ - `align`: Text alignment ["left", "center", "right"] (default: "left")
308
+ - `lineHeight`: Line height (default: 1.2)
309
+ - `wordWrap`: Enable word wrapping (default: true)
310
+ - `breakWords`: Allow breaking words (default: true)
311
+ - `strokeColor`: Text outline color
312
+ - `strokeWidth`: Text outline width
313
+
314
+ **Events:**
315
+ - **click**: Triggered when text is clicked
316
+ - `textStyle` (object, optional): Change text styling
317
+ - `soundSrc` (string, optional): Play sound effect
318
+ - `actionPayload` (object, optional): Custom data sent to event handler
319
+ - **hover**: Triggered when mouse enters/exits text
320
+ - `textStyle` (object, optional): Change text styling
321
+ - `soundSrc` (string, optional): Play sound effect
322
+ - `cursor` (string, optional): CSS cursor style
323
+ - `actionPayload` (object, optional): Custom data sent to event handler
324
+
325
+ **Example:**
326
+ ```yaml
327
+ id: title
328
+ type: text
329
+ x: 960
330
+ y: 100
331
+ content: Welcome to Route Graphics
332
+ textStyle:
333
+ fill: "#ffffff"
334
+ fontFamily: Arial
335
+ fontSize: 48
336
+ align: center
337
+ hover:
338
+ textStyle:
339
+ fill: "#ffff00"
340
+ cursor: pointer
341
+ soundSrc: hover-sound
342
+ actionPayload:
343
+ action: hoverTitle
344
+ click:
345
+ textStyle:
346
+ fill: "#00ff00"
347
+ soundSrc: click-sound
348
+ actionPayload:
349
+ action: clickTitle
350
+ ```
351
+
352
+ **Event Data Structure:**
353
+ - **Click Event:**
354
+ ```yaml
355
+ _event:
356
+ id: title
357
+ # All actionPayload properties are spread directly here
358
+ action: clickTitle
359
+ ```
360
+ - **Hover Event:**
361
+ ```yaml
362
+ _event:
363
+ id: title
364
+ # All actionPayload properties are spread directly here
365
+ action: hoverTitle
366
+ ```
367
+
368
+ #### Rectangle Plugin
369
+ Creates filled and bordered rectangles with rotation support.
370
+
371
+ **Required Properties:**
372
+ - `id`, `type`, `width`, `height`
373
+
374
+ **Optional Properties:**
375
+ - `x`, `y`: Position (default: 0)
376
+ - `anchorX`, `anchorY`: Anchor points (default: 0)
377
+ - `alpha`: Opacity (0-1, default: 1)
378
+ - `fill`: Fill color (default: "white")
379
+ - `rotation`: Rotation in degrees (default: 0)
380
+ - `border`: Border styling object
381
+
382
+ **Border Options:**
383
+ - `width`: Border width in pixels (default: 0)
384
+ - `color`: Border color (default: "black")
385
+ - `alpha`: Border opacity (0-1, default: 1)
386
+
387
+ **Events:**
388
+ - **click**: Triggered when rectangle is clicked
389
+ - `soundSrc` (string, optional): Play sound effect
390
+ - `actionPayload` (object, optional): Custom data sent to event handler
391
+ - **hover**: Triggered when mouse enters/exits rectangle
392
+ - `soundSrc` (string, optional): Play sound effect
393
+ - `cursor` (string, optional): CSS cursor style
394
+ - `actionPayload` (object, optional): Custom data sent to event handler
395
+
396
+ **Example:**
397
+ ```yaml
398
+ id: panel
399
+ type: rect
400
+ x: 50
401
+ y: 50
402
+ width: 400
403
+ height: 300
404
+ fill: "0x333333"
405
+ border:
406
+ width: 2
407
+ color: "0xffffff"
408
+ alpha: 0.8
409
+ alpha: 0.9
410
+ hover:
411
+ cursor: pointer
412
+ soundSrc: hover-sound
413
+ actionPayload:
414
+ action: hoverPanel
415
+ click:
416
+ soundSrc: click-sound
417
+ actionPayload:
418
+ action: clickPanel
419
+ ```
420
+
421
+ **Event Data Structure:**
422
+ For an element with `actionPayload: { action: "clickPanel", panelType: "settings" }`:
423
+
424
+ - **Click Event:**
425
+ ```yaml
426
+ _event:
427
+ id: panel
428
+ action: clickPanel
429
+ panelType: settings
430
+ ```
431
+
432
+ - **Hover Event:**
433
+ ```yaml
434
+ _event:
435
+ id: panel
436
+ action: hoverPanel
437
+ panelType: settings
438
+ ```
439
+
440
+ #### Container Plugin
441
+ Groups and manages layout of multiple elements.
442
+
443
+ **Required Properties:**
444
+ - `id`, `type`, `x`, `y`
445
+
446
+ **Optional Properties:**
447
+ - `width`, `height`: Container dimensions (calculated from children if not set)
448
+ - `anchorX`, `anchorY`: Anchor points (must be 0, 0.5, or 1 for containers)
449
+ - `alpha`: Opacity (0-1, default: 1)
450
+ - `children`: Array of child elements (default: [])
451
+ - `direction`: Layout layout ["absolute", "horizontal", "vertical"] (default: "absolute")
452
+ - `gap`: Spacing between children in pixels (default: 0)
453
+ - `rotation`: Rotation in degrees (default: 0)
454
+ - `scroll`: Enable scrolling for overflow content (default: false)
455
+
456
+ **Events:** None
457
+
458
+ **Layout Directions:**
459
+ - `horizontal`: Left-to-right arrangement
460
+ - `vertical`: Top-to-bottom arrangement
461
+
462
+ **Example:**
463
+ ```yaml
464
+ id: menu
465
+ type: container
466
+ x: 0
467
+ y: 0
468
+ width: 200
469
+ height: 400
470
+ direction: vertical
471
+ gap: 10
472
+ children:
473
+ - id: btn1
474
+ type: sprite
475
+ x: 0
476
+ y: 0
477
+ width: 200
478
+ height: 50
479
+ src: button-normal
480
+ - id: btn2
481
+ type: sprite
482
+ x: 0
483
+ y: 60
484
+ width: 200
485
+ height: 50
486
+ src: button-normal
487
+ ```
488
+
489
+ #### Text Revealing Plugin
490
+ Animated text display with typewriter effects.
491
+
492
+ **Required Properties:**
493
+ - `id`, `type`, `x`, `y`
494
+
495
+ **Optional Properties:**
496
+ - `content`: Array of text segments with individual styling
497
+ - `width`: Width constraint for text wrapping
498
+ - `anchorX`, `anchorY`: Anchor points (default: 0)
499
+ - `alpha`: Opacity (0-1, default: 1)
500
+ - `textStyle`: Default text styling for all segments
501
+ - `speed`: Animation speed (default: 50)
502
+ - `revealEffect`: Animation type ["typewriter", "none"] (default: "typewriter")
503
+ - `indicator`: Continuation indicator settings
504
+
505
+ **Content Structure:**
506
+ ```yaml
507
+ content:
508
+ - text: "Hello "
509
+ textStyle: # Optional individual styling
510
+ fill: red
511
+ furigana: # Optional Japanese annotations
512
+ text: "こ"
513
+ textStyle:
514
+ fontSize: 12
515
+ - text: "World!"
516
+ ```
517
+
518
+ **Indicator Options:**
519
+ - `revealing`: `src`, `width`, `height` - indicator during animation
520
+ - `complete`: `src`, `width`, `height` - indicator when finished
521
+ - `offset`: Distance between text and indicator (default: 12)
522
+
523
+ **Events:** None (Text Revealing elements do not support events)
524
+
525
+ **Example:**
526
+ ```yaml
527
+ id: story
528
+ type: textRevealing
529
+ x: 100
530
+ y: 200
531
+ content:
532
+ - text: "Hello "
533
+ textStyle:
534
+ fill: red
535
+ - text: "World!"
536
+ textStyle:
537
+ fill: blue
538
+ speed: 50
539
+ revealEffect: typewriter
540
+ ```
541
+
542
+ #### Slider Plugin
543
+ Interactive slider controls for value input.
544
+
545
+ **Required Properties:**
546
+ - `id`, `type`, `x`, `y`, `direction`, `thumbSrc`, `barSrc`
547
+
548
+ **Optional Properties:**
549
+ - `anchorX`, `anchorY`: Anchor points (default: 0)
550
+ - `alpha`: Opacity (0-1, default: 1)
551
+ - `width`, `height`: Slider dimensions
552
+ - `min`: Minimum value (default: 0)
553
+ - `max`: Maximum value (default: 100)
554
+ - `step`: Value increment (default: 1, minimum: 0)
555
+ - `initialValue`: Starting value (default: 0)
556
+
557
+ **Events:**
558
+ - **hover**: Triggered when mouse enters/exits slider
559
+ - `thumbSrc` (string, optional): Change thumb sprite image
560
+ - `barSrc` (string, optional): Change bar sprite image
561
+ - `soundSrc` (string, optional): Play sound effect
562
+ - `cursor` (string, optional): CSS cursor style
563
+ - **change**: Triggered during slider drag with current value
564
+ - `actionPayload` (object, optional): Custom data sent to event handler
565
+
566
+ **Example:**
567
+ ```yaml
568
+ id: volumeSlider
569
+ type: slider
570
+ x: 100
571
+ y: 500
572
+ direction: horizontal
573
+ thumbSrc: slider-thumb
574
+ barSrc: slider-bar
575
+ min: 0
576
+ max: 100
577
+ step: 1
578
+ initialValue: 50
579
+ hover:
580
+ thumbSrc: slider-thumb-hover
581
+ barSrc: slider-bar-hover
582
+ cursor: pointer
583
+ soundSrc: slider-hover
584
+ change:
585
+ actionPayload:
586
+ action: updateVolume
587
+ ```
588
+
589
+ **Event Data Structure:**
590
+ - **Hover Event:** None (slider hover doesn't trigger event data)
591
+ - **Change Event:** For a slider with `actionPayload: { action: "updateVolume" }` and current value of 75:
592
+ ```yaml
593
+ _event:
594
+ id: volumeSlider
595
+ value: 75
596
+ action: updateVolume
597
+ ```
598
+
599
+ ## Audio Plugin
600
+
601
+ Integrated audio system for sound effects and background music.
602
+
603
+ ### Sound Plugin Properties
604
+
605
+ **Required Properties:**
606
+ - `id`, `type`, `src`
607
+
608
+ **Optional Properties:**
609
+ - `volume`: Volume level (default: 800, minimum: 0)
610
+ - `loop`: Whether to loop the audio (default: false)
611
+ - `delay`: Delay before playing in milliseconds (default: 0)
612
+
613
+ **Volume Details:**
614
+ - 0 = muted
615
+ - 1000 = original full volume
616
+ - Values above 1000 = amplified (may clip)
617
+
618
+ **Example:**
619
+ ```yaml
620
+ id: bgMusic
621
+ type: sound
622
+ src: bgm-level1
623
+ volume: 800
624
+ loop: true
625
+ delay: 500
626
+ ```
627
+
628
+ ### Audio Integration
629
+
630
+ Audio integrates seamlessly with element interactions:
631
+
632
+ ```yaml
633
+ id: button
634
+ type: sprite
635
+ # ... other properties
636
+ hover:
637
+ soundSrc: file:hover-sound # Plays on hover
638
+ click:
639
+ soundSrc: file:click-sound # Plays on click
640
+ ```
641
+
642
+ ## Animation System
643
+
644
+ Keyframe-based animation system for smooth transitions and effects.
645
+
646
+ ### Tween Animation Plugin
647
+
648
+ **Properties:**
649
+ - `id`, `targetId`, `type`, `properties`
650
+
651
+ **Animatable Properties:**
652
+ - `alpha`, `x`, `y`, `scaleX`, `scaleY`, `rotation`
653
+
654
+ **Example:**
655
+ ```yaml
656
+ id: fadeSlide
657
+ targetId: myElement
658
+ type: tween
659
+ properties:
660
+ alpha:
661
+ initialValue: 0
662
+ keyframes:
663
+ - duration: 500
664
+ value: 1
665
+ easing: linear
666
+ - duration: 1000
667
+ value: 0.5
668
+ easing: linear
669
+ x:
670
+ initialValue: 100
671
+ keyframes:
672
+ - duration: 1500
673
+ value: 500
674
+ easing: linear
675
+ ```
676
+
677
+ ## Creating Custom Plugins
678
+
679
+ The plugin system makes it easy to add new element types, animations, or audio handlers.
680
+
681
+ ### Element Plugin Creation
682
+
683
+ ```javascript
684
+ import { createElementPlugin } from 'route-graphics';
685
+
686
+ // Create custom element plugin
687
+ const customPlugin = createElementPlugin({
688
+ type: "myCustomElement",
689
+ add: ({ element, app }) => {
690
+ // Creation logic - return a PIXI display object
691
+ const graphics = new Graphics();
692
+ graphics.beginFill(element.fill || 0xffffff);
693
+ graphics.drawRect(element.x, element.y, element.width, element.height);
694
+ graphics.endFill();
695
+ return graphics;
696
+ },
697
+ update: ({ element, app, displayObject }) => {
698
+ // Update logic - modify the display object
699
+ if (displayObject) {
700
+ displayObject.x = element.x;
701
+ displayObject.y = element.y;
702
+ displayObject.alpha = element.alpha ?? 1;
703
+ }
704
+ },
705
+ delete: ({ element, app, displayObject }) => {
706
+ // Cleanup logic
707
+ if (displayObject) {
708
+ displayObject.destroy();
709
+ }
710
+ },
711
+ // Optional: Parse function for JSON to AST conversion
712
+ parse: (element) => {
713
+ // Parse JSON element to AST format
714
+ return {
715
+ ...element,
716
+ parsed: true
717
+ };
718
+ }
719
+ });
720
+
721
+ // Register plugin in your app
722
+ await app.init({
723
+ // ... other config
724
+ plugins: {
725
+ elements: [
726
+ // ... existing plugins
727
+ customPlugin
728
+ ],
729
+ animations: [/* ... */],
730
+ audios: [/* ... */]
731
+ }
732
+ });
733
+ ```
734
+
735
+ ### Animation Plugin Creation
736
+
737
+ ```javascript
738
+ import { createAnimationPlugin } from 'route-graphics';
739
+
740
+ const customAnimationPlugin = createAnimationPlugin({
741
+ type: "myCustomAnimation",
742
+ add: ({ animation, app }) => {
743
+ // Animation creation logic
744
+ return {
745
+ animation,
746
+ startTime: Date.now(),
747
+ active: true
748
+ };
749
+ },
750
+ update: ({ animation, app, animationData }) => {
751
+ // Animation update logic
752
+ if (animationData.active) {
753
+ const elapsed = Date.now() - animationData.startTime;
754
+ if (elapsed >= animation.duration) {
755
+ animationData.active = false;
756
+ }
757
+ }
758
+ },
759
+ delete: ({ animation, app, animationData }) => {
760
+ // Animation cleanup logic
761
+ // Stop any ongoing animations
762
+ }
763
+ });
764
+ ```
765
+
766
+ ### Audio Plugin Creation
767
+
768
+ ```javascript
769
+ import { createAudioPlugin } from 'route-graphics';
770
+
771
+ const customAudioPlugin = createAudioPlugin({
772
+ type: "myCustomAudio",
773
+ add: ({ audio, app }) => {
774
+ // Audio creation logic
775
+ return {
776
+ audio,
777
+ startTime: Date.now(),
778
+ playing: true
779
+ };
780
+ },
781
+ update: ({ audio, app, audioData }) => {
782
+ // Audio update logic
783
+ if (audioData.playing && Date.now() - audioData.startTime >= audio.delay) {
784
+ // Start playing after delay
785
+ }
786
+ },
787
+ delete: ({ audio, app, audioData }) => {
788
+ // Audio cleanup logic
789
+ // Stop audio playback
790
+ }
791
+ });
792
+ ```
793
+
794
+ ## Parser System
795
+
796
+ The parser system transforms your JSON input into Abstract Syntax Trees (AST) that the rendering engine can process. Each element plugin includes its own parser function that converts JSON definitions into the internal AST format.
797
+
798
+ ### parseElements Function
799
+
800
+ ```javascript
801
+ // Main parsing function that processes all elements
802
+ const parsedElements = parseElements({
803
+ JSONObject: [
804
+ {
805
+ id: "myButton",
806
+ type: "sprite",
79
807
  x: 100,
80
808
  y: 100,
809
+ width: 64,
810
+ height: 64
81
811
  }
82
812
  ],
83
- animations: []
813
+ parserPlugins: [spritePlugin, textPlugin, ...]
84
814
  });
85
815
  ```
86
816
 
87
- ## Features
817
+ ### Parser Function Properties
818
+
819
+ **Parameters:**
820
+ - `state`: The raw JSON element definition from the input
821
+ - `parserPlugins`: Array of available parser plugins (useful for nested elements like containers)
822
+
823
+ **Returns:**
824
+ - AST (Abstract Syntax Tree) node with processed properties ready for rendering
825
+
826
+ ### Parser Function Example
827
+
828
+ ```javascript
829
+ const parseMyElement = ({ state, parserPlugins }) => {
830
+ // Validate required properties
831
+ if (!state.id || !state.type) {
832
+ throw new Error('Missing required properties');
833
+ }
834
+
835
+ // Apply defaults and type conversion
836
+ return {
837
+ id: state.id,
838
+ type: state.type,
839
+ x: Math.round(state.x ?? 0),
840
+ y: Math.round(state.y ?? 0),
841
+ width: Math.round(state.width ?? 100),
842
+ height: Math.round(state.height ?? 50),
843
+ // Custom property with default
844
+ customProperty: state.customProperty ?? "default",
845
+ // Example: Hex color to number conversion
846
+ color: state.color ? parseInt(state.color.replace('#', ''), 16) : 0x000000,
847
+ };
848
+ };
849
+ ```
850
+
851
+ ## Asset Management
852
+
853
+ Route Graphics uses a sophisticated asset management system with aliasing.
854
+
855
+ ### Asset Management
856
+
857
+ #### Loading Assets
858
+
859
+ Load assets using the `createAssetBufferManager`:
860
+
861
+ ```javascript
862
+ import { createAssetBufferManager } from 'route-graphics';
863
+
864
+ // Define assets with URL and type
865
+ const assets = {
866
+ "hero-sprite": {
867
+ url: "./assets/hero.png",
868
+ type: "image/png",
869
+ },
870
+ "background-image": {
871
+ url: "./assets/background.jpg",
872
+ type: "image/jpeg"
873
+ },
874
+ "bg-music": {
875
+ url: "./audio/background.mp3",
876
+ type: "audio/mpeg",
877
+ },
878
+ "click-sound": {
879
+ url: "./audio/click.wav",
880
+ type: "audio/wav"
881
+ }
882
+ };
883
+
884
+ // Load assets using asset buffer manager
885
+ const assetBufferManager = createAssetBufferManager();
886
+ await assetBufferManager.load(assets);
887
+ const assetBufferMap = assetBufferManager.getBufferMap();
888
+
889
+ // Load assets into the app
890
+ await app.loadAssets(assetBufferMap);
891
+ ```
892
+
893
+ #### Asset Aliases
894
+
895
+ Once loaded, assets are referenced by their alias keys:
896
+
897
+ ```yaml
898
+ id: hero
899
+ type: sprite
900
+ src: hero-sprite
901
+ ```
88
902
 
89
- - 2D graphics rendering
90
- - Sprite management
91
- - Text rendering with reveal effects
92
- - Container layouts
93
- - Transitions and animations
94
- - Interactive elements
95
- - Audio playback
903
+ #### Supported Asset Types
96
904
 
97
- ## Development
905
+ - **Images**: PNG, JPG, JPEG, WebP, GIF
906
+ - **Audio**: MP3, WAV, OGG
907
+ - **Fonts**: TTF, OTF, WOFF
908
+
909
+ ## Development & Testing
910
+
911
+ ### Running Tests
98
912
 
99
913
  ```bash
100
- # Install dependencies
101
- bun install
914
+ # Run all tests
915
+ bun run test
916
+ ```
917
+ ### Code Quality
102
918
 
103
- # Build
919
+ ```bash
920
+ # Build visual tests
104
921
  bun run vt:generate
105
922
 
106
- # Lint
107
- bun run lint
108
923
 
109
- # to test it
110
- bun run test
924
+ # Fix linting issues
925
+ bun run lint:fix
111
926
 
112
- # or
113
- bun run test:coverage
927
+ ```
114
928
 
929
+ ## Complete YAML Example
115
930
 
931
+ ```yaml
932
+ elements:
933
+ - id: background
934
+ type: sprite
935
+ x: 0
936
+ y: 0
937
+ width: 1920
938
+ height: 1080
939
+ src: file:bg-image
940
+ - id: title
941
+ type: text
942
+ x: 960
943
+ y: 100
944
+ content: Game Title
945
+ textStyle:
946
+ fill: "#ffffff"
947
+ fontFamily: Arial
948
+ fontSize: 64
949
+ align: center
950
+ - id: buttonContainer
951
+ type: container
952
+ x: 960
953
+ y: 400
954
+ width: 200
955
+ height: 300
956
+ direction: vertical
957
+ gap: 20
958
+ children:
959
+ - id: startBtn
960
+ type: sprite
961
+ x: 0
962
+ y: 0
963
+ width: 200
964
+ height: 50
965
+ src: file:btn-normal
966
+ hover:
967
+ imageSrc: file:btn-hover
968
+ soundSrc: file:hover-sound
969
+ click:
970
+ action: startGame
971
+ soundSrc: file:click-sound
972
+ animations:
973
+ - id: titleFadeIn
974
+ targetId: title
975
+ type: tween
976
+ properties:
977
+ alpha:
978
+ initialValue: 0
979
+ keyframes:
980
+ - duration: 2000
981
+ value: 1
982
+ easing: linear
983
+ audio:
984
+ - id: bgMusic
985
+ type: sound
986
+ src: file:background-music
987
+ volume: 600
988
+ loop: true
116
989
  ```
117
990
 
118
991
 
992
+ ## Schemas
993
+
994
+ All element types are defined with YAML schemas in the `src/schemas/` directory, providing:
995
+
996
+ - Type definitions and validation
997
+ - Property documentation
998
+ - Default values
999
+ - Required field specifications