@guinetik/gcanvas 1.0.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/.github/workflows/release.yaml +70 -0
- package/.jshintrc +4 -0
- package/.vscode/settings.json +22 -0
- package/CLAUDE.md +310 -0
- package/blackhole.jpg +0 -0
- package/demo.png +0 -0
- package/demos/CNAME +1 -0
- package/demos/animations.html +31 -0
- package/demos/basic.html +38 -0
- package/demos/baskara.html +31 -0
- package/demos/bezier.html +35 -0
- package/demos/beziersignature.html +29 -0
- package/demos/blackhole.html +28 -0
- package/demos/blob.html +35 -0
- package/demos/demos.css +289 -0
- package/demos/easing.html +28 -0
- package/demos/events.html +195 -0
- package/demos/fluent.html +647 -0
- package/demos/fractals.html +36 -0
- package/demos/genart.html +26 -0
- package/demos/gendream.html +26 -0
- package/demos/group.html +36 -0
- package/demos/home.html +587 -0
- package/demos/index.html +364 -0
- package/demos/isometric.html +34 -0
- package/demos/js/animations.js +452 -0
- package/demos/js/basic.js +204 -0
- package/demos/js/baskara.js +751 -0
- package/demos/js/bezier.js +692 -0
- package/demos/js/beziersignature.js +241 -0
- package/demos/js/blackhole/accretiondisk.obj.js +379 -0
- package/demos/js/blackhole/blackhole.obj.js +318 -0
- package/demos/js/blackhole/index.js +409 -0
- package/demos/js/blackhole/particle.js +56 -0
- package/demos/js/blackhole/starfield.obj.js +218 -0
- package/demos/js/blob.js +2263 -0
- package/demos/js/easing.js +477 -0
- package/demos/js/fluent.js +183 -0
- package/demos/js/fractals.js +931 -0
- package/demos/js/fractalworker.js +93 -0
- package/demos/js/genart.js +268 -0
- package/demos/js/gendream.js +209 -0
- package/demos/js/group.js +140 -0
- package/demos/js/info-toggle.js +25 -0
- package/demos/js/isometric.js +863 -0
- package/demos/js/kerr.js +1556 -0
- package/demos/js/lavalamp.js +590 -0
- package/demos/js/layout.js +354 -0
- package/demos/js/mondrian.js +285 -0
- package/demos/js/opacity.js +275 -0
- package/demos/js/painter.js +484 -0
- package/demos/js/particles-showcase.js +514 -0
- package/demos/js/particles.js +299 -0
- package/demos/js/patterns.js +397 -0
- package/demos/js/penrose/artifact.js +69 -0
- package/demos/js/penrose/blackhole.js +121 -0
- package/demos/js/penrose/constants.js +73 -0
- package/demos/js/penrose/game.js +943 -0
- package/demos/js/penrose/lore.js +278 -0
- package/demos/js/penrose/penrosescene.js +892 -0
- package/demos/js/penrose/ship.js +216 -0
- package/demos/js/penrose/sounds.js +211 -0
- package/demos/js/penrose/voidparticle.js +55 -0
- package/demos/js/penrose/voidscene.js +258 -0
- package/demos/js/penrose/voidship.js +144 -0
- package/demos/js/penrose/wormhole.js +46 -0
- package/demos/js/pipeline.js +555 -0
- package/demos/js/scene.js +304 -0
- package/demos/js/scenes.js +320 -0
- package/demos/js/schrodinger.js +410 -0
- package/demos/js/schwarzschild.js +1023 -0
- package/demos/js/shapes.js +628 -0
- package/demos/js/space/alien.js +171 -0
- package/demos/js/space/boom.js +98 -0
- package/demos/js/space/boss.js +353 -0
- package/demos/js/space/buff.js +73 -0
- package/demos/js/space/bullet.js +102 -0
- package/demos/js/space/constants.js +85 -0
- package/demos/js/space/game.js +1884 -0
- package/demos/js/space/hud.js +112 -0
- package/demos/js/space/laserbeam.js +179 -0
- package/demos/js/space/lightning.js +277 -0
- package/demos/js/space/minion.js +192 -0
- package/demos/js/space/missile.js +212 -0
- package/demos/js/space/player.js +430 -0
- package/demos/js/space/powerup.js +90 -0
- package/demos/js/space/starfield.js +58 -0
- package/demos/js/space/starpower.js +90 -0
- package/demos/js/spacetime.js +559 -0
- package/demos/js/svgtween.js +204 -0
- package/demos/js/tde/accretiondisk.js +418 -0
- package/demos/js/tde/blackhole.js +219 -0
- package/demos/js/tde/blackholescene.js +209 -0
- package/demos/js/tde/config.js +59 -0
- package/demos/js/tde/index.js +695 -0
- package/demos/js/tde/jets.js +290 -0
- package/demos/js/tde/lensedstarfield.js +147 -0
- package/demos/js/tde/tdestar.js +317 -0
- package/demos/js/tde/tidalstream.js +356 -0
- package/demos/js/tde_old/blackhole.obj.js +354 -0
- package/demos/js/tde_old/debris.obj.js +791 -0
- package/demos/js/tde_old/flare.obj.js +239 -0
- package/demos/js/tde_old/index.js +448 -0
- package/demos/js/tde_old/star.obj.js +812 -0
- package/demos/js/tiles.js +312 -0
- package/demos/js/tweendemo.js +79 -0
- package/demos/js/visibility.js +102 -0
- package/demos/kerr.html +28 -0
- package/demos/lavalamp.html +27 -0
- package/demos/layouts.html +37 -0
- package/demos/logo.svg +4 -0
- package/demos/loop.html +84 -0
- package/demos/mondrian.html +32 -0
- package/demos/og_image.png +0 -0
- package/demos/opacity.html +36 -0
- package/demos/painter.html +39 -0
- package/demos/particles-showcase.html +28 -0
- package/demos/particles.html +24 -0
- package/demos/patterns.html +33 -0
- package/demos/penrose-game.html +31 -0
- package/demos/pipeline.html +737 -0
- package/demos/scene.html +33 -0
- package/demos/scenes.html +96 -0
- package/demos/schrodinger.html +27 -0
- package/demos/schwarzschild.html +27 -0
- package/demos/shapes.html +16 -0
- package/demos/space.html +85 -0
- package/demos/spacetime.html +27 -0
- package/demos/svgtween.html +29 -0
- package/demos/tde.html +28 -0
- package/demos/tiles.html +28 -0
- package/demos/transforms.html +400 -0
- package/demos/tween.html +45 -0
- package/demos/visibility.html +33 -0
- package/disk_example.png +0 -0
- package/docs/README.md +222 -0
- package/docs/concepts/architecture-overview.md +204 -0
- package/docs/concepts/lifecycle.md +255 -0
- package/docs/concepts/rendering-pipeline.md +279 -0
- package/docs/concepts/tde-zorder.md +106 -0
- package/docs/concepts/two-layer-architecture.md +229 -0
- package/docs/getting-started/first-game.md +354 -0
- package/docs/getting-started/hello-world.md +269 -0
- package/docs/getting-started/installation.md +157 -0
- package/docs/modules/collision/README.md +453 -0
- package/docs/modules/fluent/README.md +1075 -0
- package/docs/modules/game/README.md +303 -0
- package/docs/modules/isometric-camera.md +210 -0
- package/docs/modules/isometric.md +275 -0
- package/docs/modules/painter/README.md +328 -0
- package/docs/modules/particle/README.md +559 -0
- package/docs/modules/shapes/README.md +221 -0
- package/docs/modules/shapes/base/euclidian.md +123 -0
- package/docs/modules/shapes/base/geometry2d.md +204 -0
- package/docs/modules/shapes/base/renderable.md +215 -0
- package/docs/modules/shapes/base/shape.md +262 -0
- package/docs/modules/shapes/base/transformable.md +243 -0
- package/docs/modules/shapes/hierarchy.md +218 -0
- package/docs/modules/state/README.md +577 -0
- package/docs/modules/util/README.md +99 -0
- package/docs/modules/util/camera3d.md +412 -0
- package/docs/modules/util/scene3d.md +395 -0
- package/index.html +17 -0
- package/jsdoc.json +50 -0
- package/package.json +55 -0
- package/readme.md +599 -0
- package/scripts/build-demo.js +69 -0
- package/scripts/bundle4llm.js +276 -0
- package/scripts/clearconsole.js +48 -0
- package/src/collision/collision-system.js +332 -0
- package/src/collision/collision.js +303 -0
- package/src/collision/index.js +10 -0
- package/src/fluent/fluent-game.js +430 -0
- package/src/fluent/fluent-go.js +1060 -0
- package/src/fluent/fluent-layer.js +152 -0
- package/src/fluent/fluent-scene.js +291 -0
- package/src/fluent/index.js +98 -0
- package/src/fluent/sketch.js +380 -0
- package/src/game/game.js +467 -0
- package/src/game/index.js +49 -0
- package/src/game/objects/go.js +220 -0
- package/src/game/objects/imagego.js +30 -0
- package/src/game/objects/index.js +54 -0
- package/src/game/objects/isometric-scene.js +260 -0
- package/src/game/objects/layoutscene.js +549 -0
- package/src/game/objects/scene.js +175 -0
- package/src/game/objects/scene3d.js +118 -0
- package/src/game/objects/text.js +221 -0
- package/src/game/objects/wrapper.js +232 -0
- package/src/game/pipeline.js +243 -0
- package/src/game/ui/button.js +396 -0
- package/src/game/ui/cursor.js +93 -0
- package/src/game/ui/fps.js +91 -0
- package/src/game/ui/index.js +5 -0
- package/src/game/ui/togglebutton.js +93 -0
- package/src/game/ui/tooltip.js +249 -0
- package/src/index.js +25 -0
- package/src/io/events.js +20 -0
- package/src/io/index.js +86 -0
- package/src/io/input.js +70 -0
- package/src/io/keys.js +152 -0
- package/src/io/mouse.js +61 -0
- package/src/io/touch.js +39 -0
- package/src/logger/debugtab.js +138 -0
- package/src/logger/index.js +3 -0
- package/src/logger/loggable.js +47 -0
- package/src/logger/logger.js +113 -0
- package/src/math/complex.js +37 -0
- package/src/math/constants.js +1 -0
- package/src/math/fractal.js +1271 -0
- package/src/math/gr.js +201 -0
- package/src/math/heat.js +202 -0
- package/src/math/index.js +12 -0
- package/src/math/noise.js +433 -0
- package/src/math/orbital.js +191 -0
- package/src/math/patterns.js +1339 -0
- package/src/math/penrose.js +259 -0
- package/src/math/quantum.js +115 -0
- package/src/math/random.js +195 -0
- package/src/math/tensor.js +1009 -0
- package/src/mixins/anchor.js +131 -0
- package/src/mixins/draggable.js +72 -0
- package/src/mixins/index.js +2 -0
- package/src/motion/bezier.js +132 -0
- package/src/motion/bounce.js +58 -0
- package/src/motion/easing.js +349 -0
- package/src/motion/float.js +130 -0
- package/src/motion/follow.js +125 -0
- package/src/motion/hop.js +52 -0
- package/src/motion/index.js +82 -0
- package/src/motion/motion.js +1124 -0
- package/src/motion/orbit.js +49 -0
- package/src/motion/oscillate.js +39 -0
- package/src/motion/parabolic.js +141 -0
- package/src/motion/patrol.js +147 -0
- package/src/motion/pendulum.js +48 -0
- package/src/motion/pulse.js +88 -0
- package/src/motion/shake.js +83 -0
- package/src/motion/spiral.js +144 -0
- package/src/motion/spring.js +150 -0
- package/src/motion/swing.js +47 -0
- package/src/motion/tween.js +92 -0
- package/src/motion/tweenetik.js +139 -0
- package/src/motion/waypoint.js +210 -0
- package/src/painter/index.js +8 -0
- package/src/painter/painter.colors.js +331 -0
- package/src/painter/painter.effects.js +230 -0
- package/src/painter/painter.img.js +229 -0
- package/src/painter/painter.js +295 -0
- package/src/painter/painter.lines.js +189 -0
- package/src/painter/painter.opacity.js +41 -0
- package/src/painter/painter.shapes.js +277 -0
- package/src/painter/painter.text.js +273 -0
- package/src/particle/emitter.js +124 -0
- package/src/particle/index.js +11 -0
- package/src/particle/particle-system.js +322 -0
- package/src/particle/particle.js +71 -0
- package/src/particle/updaters.js +170 -0
- package/src/shapes/arc.js +43 -0
- package/src/shapes/arrow.js +33 -0
- package/src/shapes/bezier.js +42 -0
- package/src/shapes/circle.js +62 -0
- package/src/shapes/clouds.js +56 -0
- package/src/shapes/cone.js +219 -0
- package/src/shapes/cross.js +70 -0
- package/src/shapes/cube.js +244 -0
- package/src/shapes/cylinder.js +254 -0
- package/src/shapes/diamond.js +48 -0
- package/src/shapes/euclidian.js +111 -0
- package/src/shapes/figure.js +115 -0
- package/src/shapes/geometry.js +220 -0
- package/src/shapes/group.js +375 -0
- package/src/shapes/heart.js +42 -0
- package/src/shapes/hexagon.js +26 -0
- package/src/shapes/image.js +192 -0
- package/src/shapes/index.js +111 -0
- package/src/shapes/line.js +29 -0
- package/src/shapes/pattern.js +90 -0
- package/src/shapes/pin.js +44 -0
- package/src/shapes/poly.js +31 -0
- package/src/shapes/prism.js +226 -0
- package/src/shapes/rect.js +35 -0
- package/src/shapes/renderable.js +333 -0
- package/src/shapes/ring.js +26 -0
- package/src/shapes/roundrect.js +95 -0
- package/src/shapes/shape.js +117 -0
- package/src/shapes/slice.js +26 -0
- package/src/shapes/sphere.js +314 -0
- package/src/shapes/sphere3d.js +537 -0
- package/src/shapes/square.js +15 -0
- package/src/shapes/star.js +99 -0
- package/src/shapes/svg.js +408 -0
- package/src/shapes/text.js +553 -0
- package/src/shapes/traceable.js +83 -0
- package/src/shapes/transform.js +357 -0
- package/src/shapes/transformable.js +172 -0
- package/src/shapes/triangle.js +26 -0
- package/src/sound/index.js +17 -0
- package/src/sound/sound.js +473 -0
- package/src/sound/synth.analyzer.js +149 -0
- package/src/sound/synth.effects.js +207 -0
- package/src/sound/synth.envelope.js +59 -0
- package/src/sound/synth.js +229 -0
- package/src/sound/synth.musical.js +160 -0
- package/src/sound/synth.noise.js +85 -0
- package/src/sound/synth.oscillators.js +293 -0
- package/src/state/index.js +10 -0
- package/src/state/state-machine.js +371 -0
- package/src/util/camera3d.js +438 -0
- package/src/util/index.js +6 -0
- package/src/util/isometric-camera.js +235 -0
- package/src/util/layout.js +317 -0
- package/src/util/position.js +147 -0
- package/src/util/tasks.js +47 -0
- package/src/util/zindex.js +287 -0
- package/src/webgl/index.js +9 -0
- package/src/webgl/shaders/sphere-shaders.js +994 -0
- package/src/webgl/webgl-renderer.js +388 -0
- package/tde.png +0 -0
- package/test/math/orbital.test.js +61 -0
- package/test/math/tensor.test.js +114 -0
- package/test/particle/emitter.test.js +204 -0
- package/test/particle/particle-system.test.js +310 -0
- package/test/particle/particle.test.js +116 -0
- package/test/particle/updaters.test.js +386 -0
- package/test/setup.js +120 -0
- package/test/shapes/euclidian.test.js +44 -0
- package/test/shapes/geometry.test.js +86 -0
- package/test/shapes/group.test.js +86 -0
- package/test/shapes/rectangle.test.js +64 -0
- package/test/shapes/transform.test.js +379 -0
- package/test/util/camera3d.test.js +428 -0
- package/test/util/scene3d.test.js +352 -0
- package/types/collision.d.ts +249 -0
- package/types/common.d.ts +155 -0
- package/types/game.d.ts +497 -0
- package/types/index.d.ts +309 -0
- package/types/io.d.ts +188 -0
- package/types/logger.d.ts +127 -0
- package/types/math.d.ts +268 -0
- package/types/mixins.d.ts +92 -0
- package/types/motion.d.ts +678 -0
- package/types/painter.d.ts +378 -0
- package/types/shapes.d.ts +864 -0
- package/types/sound.d.ts +672 -0
- package/types/state.d.ts +251 -0
- package/types/util.d.ts +253 -0
- package/vite.config.js +50 -0
- package/vitest.config.js +13 -0
package/types/state.d.ts
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCanvas State Machine Types
|
|
3
|
+
* State management utilities for game objects.
|
|
4
|
+
* @module state
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ==========================================================================
|
|
8
|
+
// State Machine Configuration
|
|
9
|
+
// ==========================================================================
|
|
10
|
+
|
|
11
|
+
/** State transition definition */
|
|
12
|
+
export interface StateTransition {
|
|
13
|
+
/** Target state to transition to */
|
|
14
|
+
target?: string;
|
|
15
|
+
/** Guard function - transition only if returns true */
|
|
16
|
+
guard?: (data?: any) => boolean;
|
|
17
|
+
/** Action to run before transition */
|
|
18
|
+
action?: (data?: any) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Event handlers for a state */
|
|
22
|
+
export interface StateEvents {
|
|
23
|
+
[triggerName: string]: string | StateTransition;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Individual state configuration */
|
|
27
|
+
export interface StateConfig {
|
|
28
|
+
/** Duration in seconds before auto-transitioning (optional) */
|
|
29
|
+
duration?: number;
|
|
30
|
+
/** Next state to transition to after duration (for timed states) */
|
|
31
|
+
next?: string;
|
|
32
|
+
/** Called when entering this state */
|
|
33
|
+
enter?: (data?: any) => void;
|
|
34
|
+
/** Called each frame while in this state */
|
|
35
|
+
update?: (dt: number) => void;
|
|
36
|
+
/** Called when leaving this state */
|
|
37
|
+
exit?: (data?: any) => void;
|
|
38
|
+
/** Called when a timed state completes without a 'next' state */
|
|
39
|
+
onComplete?: () => void;
|
|
40
|
+
/** Event-based transitions */
|
|
41
|
+
on?: StateEvents;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** State definitions object */
|
|
45
|
+
export interface States {
|
|
46
|
+
[stateName: string]: StateConfig;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** StateMachine constructor options */
|
|
50
|
+
export interface StateMachineOptions {
|
|
51
|
+
/** Initial state name */
|
|
52
|
+
initial?: string;
|
|
53
|
+
/** State definitions */
|
|
54
|
+
states?: States;
|
|
55
|
+
/** Context object passed to callbacks (usually `this`) */
|
|
56
|
+
context?: any;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Phase definition for sequence-based state machines */
|
|
60
|
+
export interface PhaseConfig {
|
|
61
|
+
/** Phase name */
|
|
62
|
+
name: string;
|
|
63
|
+
/** Phase duration in seconds */
|
|
64
|
+
duration: number;
|
|
65
|
+
/** Called when entering this phase */
|
|
66
|
+
enter?: () => void;
|
|
67
|
+
/** Called each frame during this phase */
|
|
68
|
+
update?: (dt: number) => void;
|
|
69
|
+
/** Called when leaving this phase */
|
|
70
|
+
exit?: () => void;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Options for StateMachine.fromSequence() */
|
|
74
|
+
export interface SequenceOptions {
|
|
75
|
+
/** Whether to loop back to first phase after last */
|
|
76
|
+
loop?: boolean;
|
|
77
|
+
/** Called when sequence completes (if not looping) */
|
|
78
|
+
onComplete?: () => void;
|
|
79
|
+
/** Context object passed to callbacks */
|
|
80
|
+
context?: any;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ==========================================================================
|
|
84
|
+
// StateMachine Class
|
|
85
|
+
// ==========================================================================
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Flexible state management for game objects.
|
|
89
|
+
* Manages states with enter/update/exit lifecycle callbacks.
|
|
90
|
+
* Supports timed transitions, sequential phases, and conditional triggers.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Basic usage
|
|
94
|
+
* const fsm = new StateMachine({
|
|
95
|
+
* initial: 'idle',
|
|
96
|
+
* states: {
|
|
97
|
+
* idle: {
|
|
98
|
+
* enter: () => console.log('Now idle'),
|
|
99
|
+
* update: (dt) => { // per-frame logic },
|
|
100
|
+
* exit: () => console.log('Leaving idle')
|
|
101
|
+
* },
|
|
102
|
+
* walking: {
|
|
103
|
+
* enter: () => player.startWalkAnimation(),
|
|
104
|
+
* update: (dt) => player.move(dt)
|
|
105
|
+
* }
|
|
106
|
+
* }
|
|
107
|
+
* });
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // Timed phase sequence
|
|
111
|
+
* const laser = new StateMachine({
|
|
112
|
+
* initial: 'warning',
|
|
113
|
+
* states: {
|
|
114
|
+
* warning: { duration: 0.3, next: 'charging' },
|
|
115
|
+
* charging: { duration: 0.2, next: 'active' },
|
|
116
|
+
* active: {
|
|
117
|
+
* duration: 0.4,
|
|
118
|
+
* next: 'fade',
|
|
119
|
+
* enter: () => { laser.canDamage = true; }
|
|
120
|
+
* },
|
|
121
|
+
* fade: {
|
|
122
|
+
* duration: 0.2,
|
|
123
|
+
* exit: () => { laser.destroy(); }
|
|
124
|
+
* }
|
|
125
|
+
* }
|
|
126
|
+
* });
|
|
127
|
+
*/
|
|
128
|
+
export class StateMachine {
|
|
129
|
+
/** State definitions */
|
|
130
|
+
states: States;
|
|
131
|
+
|
|
132
|
+
/** Current state name */
|
|
133
|
+
currentState: string | null;
|
|
134
|
+
|
|
135
|
+
/** Previous state name */
|
|
136
|
+
previousState: string | null;
|
|
137
|
+
|
|
138
|
+
/** Time spent in current state */
|
|
139
|
+
stateTime: number;
|
|
140
|
+
|
|
141
|
+
/** Context passed to state callbacks */
|
|
142
|
+
context: any;
|
|
143
|
+
|
|
144
|
+
/** Whether the state machine is paused */
|
|
145
|
+
paused: boolean;
|
|
146
|
+
|
|
147
|
+
/** Global state change callback */
|
|
148
|
+
onStateChange: ((newState: string, previousState: string | null, data?: any) => void) | null;
|
|
149
|
+
|
|
150
|
+
constructor(config?: StateMachineOptions);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get the current state name
|
|
154
|
+
*/
|
|
155
|
+
get state(): string | null;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get the current state configuration
|
|
159
|
+
*/
|
|
160
|
+
get currentStateConfig(): StateConfig | null;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Check if currently in a specific state
|
|
164
|
+
*/
|
|
165
|
+
is(stateName: string): boolean;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Check if currently in any of the given states
|
|
169
|
+
*/
|
|
170
|
+
isAny(...stateNames: string[]): boolean;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Add or update a state definition
|
|
174
|
+
* @returns this for chaining
|
|
175
|
+
*/
|
|
176
|
+
addState(name: string, config: StateConfig): this;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Remove a state definition
|
|
180
|
+
* @returns this for chaining
|
|
181
|
+
*/
|
|
182
|
+
removeState(name: string): this;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Transition to a new state
|
|
186
|
+
* @param newState - State to transition to
|
|
187
|
+
* @param data - Optional data passed to enter callback
|
|
188
|
+
* @returns True if transition occurred
|
|
189
|
+
*/
|
|
190
|
+
setState(newState: string, data?: any): boolean;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Attempt to transition based on a trigger/event
|
|
194
|
+
* @param trigger - Trigger name to check against state transitions
|
|
195
|
+
* @param data - Optional data passed to callbacks
|
|
196
|
+
* @returns True if a transition occurred
|
|
197
|
+
*/
|
|
198
|
+
trigger(trigger: string, data?: any): boolean;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Update the state machine (call each frame)
|
|
202
|
+
* @param dt - Delta time in seconds
|
|
203
|
+
*/
|
|
204
|
+
update(dt: number): void;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get normalized progress through current state (0-1)
|
|
208
|
+
* Only meaningful for states with a duration
|
|
209
|
+
*/
|
|
210
|
+
get progress(): number;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get remaining time in current state
|
|
214
|
+
* Only meaningful for states with a duration
|
|
215
|
+
*/
|
|
216
|
+
get remaining(): number;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Check if current state is a timed state
|
|
220
|
+
*/
|
|
221
|
+
get isTimed(): boolean;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Pause the state machine (stops update processing)
|
|
225
|
+
*/
|
|
226
|
+
pause(): void;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Resume the state machine
|
|
230
|
+
*/
|
|
231
|
+
resume(): void;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Reset to initial state or specific state
|
|
235
|
+
* @param state - State to reset to (defaults to first defined state)
|
|
236
|
+
*/
|
|
237
|
+
reset(state?: string): void;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Create a state machine from a simple phase sequence.
|
|
241
|
+
* Convenience method for common "phase 1 → phase 2 → phase 3" patterns.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* const lightning = StateMachine.fromSequence([
|
|
245
|
+
* { name: 'tracing', duration: 0.4, enter: () => startTrace() },
|
|
246
|
+
* { name: 'active', duration: 0.3, enter: () => enableDamage() },
|
|
247
|
+
* { name: 'fade', duration: 0.2, exit: () => destroy() }
|
|
248
|
+
* ]);
|
|
249
|
+
*/
|
|
250
|
+
static fromSequence(phases: PhaseConfig[], options?: SequenceOptions): StateMachine;
|
|
251
|
+
}
|
package/types/util.d.ts
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCanvas Util Module
|
|
3
|
+
* Utility classes and functions for layout, positioning, z-ordering, and task management.
|
|
4
|
+
* @module util
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Point, LayoutResult } from './common';
|
|
8
|
+
import { Transformable } from './shapes';
|
|
9
|
+
|
|
10
|
+
// ==========================================================================
|
|
11
|
+
// Z-Ordered Collection
|
|
12
|
+
// ==========================================================================
|
|
13
|
+
|
|
14
|
+
/** Options for ZOrderedCollection */
|
|
15
|
+
export interface ZOrderedCollectionOptions {
|
|
16
|
+
/** Sort children by zIndex when rendering */
|
|
17
|
+
sortByZIndex?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Z-ordered collection for managing child objects.
|
|
22
|
+
* Maintains rendering order based on zIndex property.
|
|
23
|
+
*/
|
|
24
|
+
export class ZOrderedCollection {
|
|
25
|
+
/** Array of child objects */
|
|
26
|
+
children: Transformable[];
|
|
27
|
+
|
|
28
|
+
constructor(options?: ZOrderedCollectionOptions);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Add an object to the collection.
|
|
32
|
+
* @param object - Object to add
|
|
33
|
+
*/
|
|
34
|
+
add(object: Transformable): void;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Remove an object from the collection.
|
|
38
|
+
* @param object - Object to remove
|
|
39
|
+
* @returns Whether object was found and removed
|
|
40
|
+
*/
|
|
41
|
+
remove(object: Transformable): boolean;
|
|
42
|
+
|
|
43
|
+
/** Remove all objects */
|
|
44
|
+
clear(): void;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get children sorted by zIndex.
|
|
48
|
+
* @returns Sorted array of children
|
|
49
|
+
*/
|
|
50
|
+
getSortedChildren(): Transformable[];
|
|
51
|
+
|
|
52
|
+
/** Move object to front (highest z-order) */
|
|
53
|
+
bringToFront(object: Transformable): void;
|
|
54
|
+
|
|
55
|
+
/** Move object to back (lowest z-order) */
|
|
56
|
+
sendToBack(object: Transformable): void;
|
|
57
|
+
|
|
58
|
+
/** Move object forward one z-level */
|
|
59
|
+
bringForward(object: Transformable): void;
|
|
60
|
+
|
|
61
|
+
/** Move object backward one z-level */
|
|
62
|
+
sendBackward(object: Transformable): void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ==========================================================================
|
|
66
|
+
// Position Constants
|
|
67
|
+
// ==========================================================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Position/anchor utilities with layout constants.
|
|
71
|
+
* Provides named constants for common anchor positions.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* const pos = Position.parse(Position.CENTER, canvasWidth, canvasHeight);
|
|
75
|
+
*/
|
|
76
|
+
export class Position {
|
|
77
|
+
static readonly TOP_LEFT: string;
|
|
78
|
+
static readonly TOP_CENTER: string;
|
|
79
|
+
static readonly TOP_RIGHT: string;
|
|
80
|
+
static readonly CENTER_LEFT: string;
|
|
81
|
+
static readonly CENTER: string;
|
|
82
|
+
static readonly CENTER_RIGHT: string;
|
|
83
|
+
static readonly BOTTOM_LEFT: string;
|
|
84
|
+
static readonly BOTTOM_CENTER: string;
|
|
85
|
+
static readonly BOTTOM_RIGHT: string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parse a position string into coordinates.
|
|
89
|
+
* @param position - Position string (e.g., "center", "top-left")
|
|
90
|
+
* @param containerWidth - Container width
|
|
91
|
+
* @param containerHeight - Container height
|
|
92
|
+
* @param objectWidth - Optional object width for centering
|
|
93
|
+
* @param objectHeight - Optional object height for centering
|
|
94
|
+
* @returns Calculated position
|
|
95
|
+
*/
|
|
96
|
+
static parse(
|
|
97
|
+
position: string,
|
|
98
|
+
containerWidth: number,
|
|
99
|
+
containerHeight: number,
|
|
100
|
+
objectWidth?: number,
|
|
101
|
+
objectHeight?: number
|
|
102
|
+
): Point;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ==========================================================================
|
|
106
|
+
// Task Manager
|
|
107
|
+
// ==========================================================================
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Task manager for scheduling delayed operations.
|
|
111
|
+
*/
|
|
112
|
+
export class TaskManager {
|
|
113
|
+
/**
|
|
114
|
+
* Add a task to be executed after a delay.
|
|
115
|
+
* @param task - Function to execute
|
|
116
|
+
* @param delay - Delay in seconds (default: 0)
|
|
117
|
+
*/
|
|
118
|
+
add(task: () => void, delay?: number): void;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Update all tasks.
|
|
122
|
+
* @param dt - Delta time in seconds
|
|
123
|
+
*/
|
|
124
|
+
update(dt: number): void;
|
|
125
|
+
|
|
126
|
+
/** Clear all pending tasks */
|
|
127
|
+
clear(): void;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ==========================================================================
|
|
131
|
+
// Layout Functions
|
|
132
|
+
// ==========================================================================
|
|
133
|
+
|
|
134
|
+
/** Item with dimensions for layout calculations */
|
|
135
|
+
export interface LayoutItem {
|
|
136
|
+
width?: number;
|
|
137
|
+
height?: number;
|
|
138
|
+
x?: number;
|
|
139
|
+
y?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Options for applyLayout */
|
|
143
|
+
export interface ApplyLayoutOptions {
|
|
144
|
+
/** X offset to apply to all positions */
|
|
145
|
+
offsetX?: number;
|
|
146
|
+
/** Y offset to apply to all positions */
|
|
147
|
+
offsetY?: number;
|
|
148
|
+
/** Transform function to apply to positions */
|
|
149
|
+
transform?: (pos: Point) => Point;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Options for horizontal/vertical layouts */
|
|
153
|
+
export interface LinearLayoutOptions {
|
|
154
|
+
/** Space between items (default: 10) */
|
|
155
|
+
spacing?: number;
|
|
156
|
+
/** Padding around entire layout (default: 0) */
|
|
157
|
+
padding?: number;
|
|
158
|
+
/** Alignment: "start", "center", or "end" (default: "start") */
|
|
159
|
+
align?: 'start' | 'center' | 'end';
|
|
160
|
+
/** Position items relative to their centers (default: true) */
|
|
161
|
+
centerItems?: boolean;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Options for tile layout */
|
|
165
|
+
export interface TileLayoutOptions {
|
|
166
|
+
/** Number of columns (default: 4) */
|
|
167
|
+
columns?: number;
|
|
168
|
+
/** Space between items (default: 10) */
|
|
169
|
+
spacing?: number;
|
|
170
|
+
/** Padding around entire layout (default: 0) */
|
|
171
|
+
padding?: number;
|
|
172
|
+
/** Position items relative to their centers (default: true) */
|
|
173
|
+
centerItems?: boolean;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Options for grid layout */
|
|
177
|
+
export interface GridLayoutOptions {
|
|
178
|
+
/** Number of columns */
|
|
179
|
+
columns?: number;
|
|
180
|
+
/** Number of rows */
|
|
181
|
+
rows?: number;
|
|
182
|
+
/** Fixed cell width */
|
|
183
|
+
cellWidth?: number;
|
|
184
|
+
/** Fixed cell height */
|
|
185
|
+
cellHeight?: number;
|
|
186
|
+
/** Space between cells (default: 10) */
|
|
187
|
+
spacing?: number;
|
|
188
|
+
/** Padding around entire layout (default: 0) */
|
|
189
|
+
padding?: number;
|
|
190
|
+
/** Position items relative to their centers (default: true) */
|
|
191
|
+
centerItems?: boolean;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Apply calculated positions to items.
|
|
196
|
+
* @param items - Array of objects to position (must have x, y properties)
|
|
197
|
+
* @param positions - Array of position objects from layout functions
|
|
198
|
+
* @param options - Options for applying positions
|
|
199
|
+
* @returns The items with updated positions
|
|
200
|
+
*/
|
|
201
|
+
export function applyLayout<T extends LayoutItem>(
|
|
202
|
+
items: T[],
|
|
203
|
+
positions: Point[],
|
|
204
|
+
options?: ApplyLayoutOptions
|
|
205
|
+
): T[];
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Create a horizontal layout (items arranged left to right).
|
|
209
|
+
* @param items - Array of objects with width and height
|
|
210
|
+
* @param options - Layout options
|
|
211
|
+
* @returns Layout result with positions and dimensions
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* const result = horizontalLayout(buttons, { spacing: 20 });
|
|
215
|
+
* applyLayout(buttons, result.positions);
|
|
216
|
+
*/
|
|
217
|
+
export function horizontalLayout(
|
|
218
|
+
items: LayoutItem[],
|
|
219
|
+
options?: LinearLayoutOptions
|
|
220
|
+
): LayoutResult;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Create a vertical layout (items arranged top to bottom).
|
|
224
|
+
* @param items - Array of objects with width and height
|
|
225
|
+
* @param options - Layout options
|
|
226
|
+
* @returns Layout result with positions and dimensions
|
|
227
|
+
*/
|
|
228
|
+
export function verticalLayout(
|
|
229
|
+
items: LayoutItem[],
|
|
230
|
+
options?: LinearLayoutOptions
|
|
231
|
+
): LayoutResult;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Create a tile layout (items in a grid with fixed columns).
|
|
235
|
+
* @param items - Array of objects with width and height
|
|
236
|
+
* @param options - Layout options
|
|
237
|
+
* @returns Layout result with positions and dimensions
|
|
238
|
+
*/
|
|
239
|
+
export function tileLayout(
|
|
240
|
+
items: LayoutItem[],
|
|
241
|
+
options?: TileLayoutOptions
|
|
242
|
+
): LayoutResult;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Create a flexible grid layout.
|
|
246
|
+
* @param items - Array of objects with width and height
|
|
247
|
+
* @param options - Layout options
|
|
248
|
+
* @returns Layout result with positions and dimensions
|
|
249
|
+
*/
|
|
250
|
+
export function gridLayout(
|
|
251
|
+
items: LayoutItem[],
|
|
252
|
+
options?: GridLayoutOptions
|
|
253
|
+
): LayoutResult;
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
const libEntry = path.resolve(__dirname, "src/index.js");
|
|
5
|
+
|
|
6
|
+
export default defineConfig(({ mode }) => {
|
|
7
|
+
const isDebug = mode === "debug";
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
server: {
|
|
11
|
+
port: 9195,
|
|
12
|
+
strictPort: true, // Don't try other ports if 9195 is in use
|
|
13
|
+
},
|
|
14
|
+
build: {
|
|
15
|
+
lib: {
|
|
16
|
+
entry: libEntry,
|
|
17
|
+
name: "GCanvas",
|
|
18
|
+
formats: isDebug ? ["umd"] : ["umd", "es"],
|
|
19
|
+
fileName: (format) => {
|
|
20
|
+
if (isDebug) return "gcanvas.debug.js";
|
|
21
|
+
return `gcanvas.${format}.js`;
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
minify: isDebug ? false : "terser",
|
|
25
|
+
terserOptions: {
|
|
26
|
+
compress: true,
|
|
27
|
+
mangle: true,
|
|
28
|
+
format: {
|
|
29
|
+
comments: false,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
outDir: "dist",
|
|
33
|
+
emptyOutDir: true,
|
|
34
|
+
rollupOptions: {
|
|
35
|
+
output: [
|
|
36
|
+
{
|
|
37
|
+
format: "umd",
|
|
38
|
+
entryFileNames: "gcanvas.umd.js",
|
|
39
|
+
name: "GCanvas",
|
|
40
|
+
globals: {},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
format: "es",
|
|
44
|
+
entryFileNames: "gcanvas.es.js",
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
});
|
package/vitest.config.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
environment: 'jsdom',
|
|
6
|
+
globals: true,
|
|
7
|
+
setupFiles: ['./test/setup.js'],
|
|
8
|
+
coverage: {
|
|
9
|
+
provider: 'v8',
|
|
10
|
+
reporter: ['text', 'json', 'html'],
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
});
|