@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
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCanvas Common Types
|
|
3
|
+
* Shared interfaces and types used across all modules.
|
|
4
|
+
* @module common
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ==========================================================================
|
|
8
|
+
// Basic Geometric Types
|
|
9
|
+
// ==========================================================================
|
|
10
|
+
|
|
11
|
+
/** 2D point/position */
|
|
12
|
+
export interface Point {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Bounding box representing position and dimensions */
|
|
18
|
+
export interface Bounds {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ==========================================================================
|
|
26
|
+
// Animation & Easing Types
|
|
27
|
+
// ==========================================================================
|
|
28
|
+
|
|
29
|
+
/** Easing function type - takes normalized time (0-1) and returns eased value */
|
|
30
|
+
export type EasingFunction = (t: number) => number;
|
|
31
|
+
|
|
32
|
+
/** Event callback type */
|
|
33
|
+
export type EventCallback<T = any> = (payload?: T) => void;
|
|
34
|
+
|
|
35
|
+
/** Callbacks for Motion animation methods */
|
|
36
|
+
export interface MotionCallbacks {
|
|
37
|
+
/** Called when animation starts */
|
|
38
|
+
onStart?: () => void;
|
|
39
|
+
/** Called when animation completes (non-looping only) */
|
|
40
|
+
onComplete?: () => void;
|
|
41
|
+
/** Called when animation loops, receives loop count */
|
|
42
|
+
onLoop?: (loopCount: number) => void;
|
|
43
|
+
/** Called each frame with current progress */
|
|
44
|
+
onUpdate?: (progress: number) => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Internal state tracking for Motion animations */
|
|
48
|
+
export interface MotionState {
|
|
49
|
+
/** Whether onStart has been called */
|
|
50
|
+
started: boolean;
|
|
51
|
+
/** Current loop count */
|
|
52
|
+
loopCount: number;
|
|
53
|
+
/** Whether animation has completed */
|
|
54
|
+
completed?: boolean;
|
|
55
|
+
/** Animation-specific state data */
|
|
56
|
+
[key: string]: any;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Result object returned by Motion animation methods */
|
|
60
|
+
export interface MotionResult {
|
|
61
|
+
/** Normalized time (0-1) */
|
|
62
|
+
t: number;
|
|
63
|
+
/** Alias for normalized time */
|
|
64
|
+
progress: number;
|
|
65
|
+
/** Whether animation is looping */
|
|
66
|
+
loop: boolean;
|
|
67
|
+
/** Whether animation has completed (non-looping only) */
|
|
68
|
+
completed: boolean;
|
|
69
|
+
/** Internal state for the next call */
|
|
70
|
+
state: MotionState | null;
|
|
71
|
+
/** Animation-specific values (x, y, value, etc.) */
|
|
72
|
+
[key: string]: any;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Result with position coordinates */
|
|
76
|
+
export interface MotionPositionResult extends MotionResult {
|
|
77
|
+
x: number;
|
|
78
|
+
y: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Result with a single value */
|
|
82
|
+
export interface MotionValueResult extends MotionResult {
|
|
83
|
+
value: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Result from spring animation */
|
|
87
|
+
export interface SpringResult extends MotionResult {
|
|
88
|
+
value: number;
|
|
89
|
+
velocity: number;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Result from waypoint animation */
|
|
93
|
+
export interface WaypointResult extends MotionPositionResult {
|
|
94
|
+
/** Whether currently moving between waypoints */
|
|
95
|
+
moving: boolean;
|
|
96
|
+
/** Current direction of movement */
|
|
97
|
+
direction: string;
|
|
98
|
+
/** Index of current waypoint */
|
|
99
|
+
waypointIndex: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ==========================================================================
|
|
103
|
+
// Layout Types
|
|
104
|
+
// ==========================================================================
|
|
105
|
+
|
|
106
|
+
/** Options for layout functions */
|
|
107
|
+
export interface LayoutOptions {
|
|
108
|
+
/** Horizontal spacing between items */
|
|
109
|
+
spacing?: number;
|
|
110
|
+
/** Starting X position */
|
|
111
|
+
x?: number;
|
|
112
|
+
/** Starting Y position */
|
|
113
|
+
y?: number;
|
|
114
|
+
/** Number of columns (for tile/grid layouts) */
|
|
115
|
+
columns?: number;
|
|
116
|
+
/** Number of rows (for grid layout) */
|
|
117
|
+
rows?: number;
|
|
118
|
+
/** Cell width (for grid layout) */
|
|
119
|
+
cellWidth?: number;
|
|
120
|
+
/** Cell height (for grid layout) */
|
|
121
|
+
cellHeight?: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Result returned by layout functions */
|
|
125
|
+
export interface LayoutResult {
|
|
126
|
+
/** Calculated positions for each object */
|
|
127
|
+
positions: Point[];
|
|
128
|
+
/** Total width of the layout */
|
|
129
|
+
width: number;
|
|
130
|
+
/** Total height of the layout */
|
|
131
|
+
height: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ==========================================================================
|
|
135
|
+
// Penrose Tiling Types
|
|
136
|
+
// ==========================================================================
|
|
137
|
+
|
|
138
|
+
/** RGBA color as 4-element array [R, G, B, A] with values 0-255 */
|
|
139
|
+
export type RGBAColor = [number, number, number, number];
|
|
140
|
+
|
|
141
|
+
/** Options for Penrose tiling generation */
|
|
142
|
+
export interface PenroseTilingOptions {
|
|
143
|
+
/** Number of subdivision iterations (default: 5) */
|
|
144
|
+
divisions?: number;
|
|
145
|
+
/** Zoom type: "in" or "out" (default: "in") */
|
|
146
|
+
zoomType?: 'in' | 'out';
|
|
147
|
+
/** Color for thin rhombi (default: red) */
|
|
148
|
+
color1?: RGBAColor;
|
|
149
|
+
/** Color for thick rhombi (default: blue) */
|
|
150
|
+
color2?: RGBAColor;
|
|
151
|
+
/** Color for outlines (default: black) */
|
|
152
|
+
color3?: RGBAColor;
|
|
153
|
+
/** Background color (default: white) */
|
|
154
|
+
backgroundColor?: RGBAColor;
|
|
155
|
+
}
|
package/types/game.d.ts
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCanvas Game Module
|
|
3
|
+
* Core game loop, pipeline, game objects, scenes, and UI components.
|
|
4
|
+
* @module game
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Bounds, Point, EventCallback } from './common';
|
|
8
|
+
import { Logger } from './logger';
|
|
9
|
+
import { Transformable, TransformableOptions, Shape } from './shapes';
|
|
10
|
+
import { EventEmitter } from './io';
|
|
11
|
+
|
|
12
|
+
// ==========================================================================
|
|
13
|
+
// Game Class
|
|
14
|
+
// ==========================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Core game class providing game loop, pipeline, and input management.
|
|
18
|
+
* Entry point for creating interactive canvas applications.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const canvas = document.getElementById('game');
|
|
22
|
+
* const game = new Game(canvas);
|
|
23
|
+
* game.init();
|
|
24
|
+
* game.start();
|
|
25
|
+
*/
|
|
26
|
+
export class Game {
|
|
27
|
+
/** The canvas element */
|
|
28
|
+
canvas: HTMLCanvasElement;
|
|
29
|
+
/** The 2D rendering context */
|
|
30
|
+
ctx: CanvasRenderingContext2D;
|
|
31
|
+
/** Event emitter for game events */
|
|
32
|
+
events: EventEmitter;
|
|
33
|
+
/** Pipeline for managing game objects */
|
|
34
|
+
pipeline: Pipeline;
|
|
35
|
+
/** Whether the game loop is running */
|
|
36
|
+
running: boolean;
|
|
37
|
+
/** Delta time since last frame (seconds) */
|
|
38
|
+
dt: number;
|
|
39
|
+
/** Target frames per second */
|
|
40
|
+
targetFPS: number;
|
|
41
|
+
/** Actual measured FPS */
|
|
42
|
+
actualFps: number;
|
|
43
|
+
/** Logger instance */
|
|
44
|
+
logger: Logger;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create a new Game instance.
|
|
48
|
+
* @param canvas - The canvas element to render to
|
|
49
|
+
*/
|
|
50
|
+
constructor(canvas: HTMLCanvasElement);
|
|
51
|
+
|
|
52
|
+
/** Canvas width */
|
|
53
|
+
get width(): number;
|
|
54
|
+
/** Canvas height */
|
|
55
|
+
get height(): number;
|
|
56
|
+
/** Background color (set only) */
|
|
57
|
+
set backgroundColor(color: string);
|
|
58
|
+
/** Custom cursor (get/set) */
|
|
59
|
+
get cursor(): Cursor;
|
|
60
|
+
set cursor(cursor: Cursor);
|
|
61
|
+
/** Whether bounds need recalculation */
|
|
62
|
+
get boundsDirty(): boolean;
|
|
63
|
+
set boundsDirty(dirty: boolean);
|
|
64
|
+
|
|
65
|
+
/** Initialize the game (called automatically by constructor) */
|
|
66
|
+
init(): void;
|
|
67
|
+
/** Start the game loop */
|
|
68
|
+
start(): void;
|
|
69
|
+
/** Stop the game loop */
|
|
70
|
+
stop(): void;
|
|
71
|
+
/** Restart the game (stop and start) */
|
|
72
|
+
restart(): void;
|
|
73
|
+
/** Clear the canvas */
|
|
74
|
+
clear(): void;
|
|
75
|
+
/** Update game state (called each frame) */
|
|
76
|
+
update(dt: number): void;
|
|
77
|
+
/** Render the game (called each frame) */
|
|
78
|
+
render(): void;
|
|
79
|
+
|
|
80
|
+
// Input initialization
|
|
81
|
+
/** Initialize mouse input */
|
|
82
|
+
initMouse(): void;
|
|
83
|
+
/** Initialize touch input */
|
|
84
|
+
initTouch(): void;
|
|
85
|
+
/** Initialize unified input (mouse + touch) */
|
|
86
|
+
initInput(): void;
|
|
87
|
+
/** Initialize keyboard input */
|
|
88
|
+
initKeyboard(): void;
|
|
89
|
+
/** Initialize all input systems */
|
|
90
|
+
initIO(): void;
|
|
91
|
+
/** Initialize motion/animation system */
|
|
92
|
+
initMotion(): void;
|
|
93
|
+
/** Initialize logging */
|
|
94
|
+
initLogging(): void;
|
|
95
|
+
|
|
96
|
+
/** Enable debug logging */
|
|
97
|
+
enableLogging(): void;
|
|
98
|
+
/** Disable debug logging */
|
|
99
|
+
disableLogging(): void;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Enable fluid canvas sizing (resizes with container).
|
|
103
|
+
* @param container - Container element (default: window)
|
|
104
|
+
*/
|
|
105
|
+
enableFluidSize(container?: HTMLElement | Window): void;
|
|
106
|
+
/** Disable fluid sizing */
|
|
107
|
+
disableFluidSize(): void;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Enable/disable pausing when window loses focus.
|
|
111
|
+
* @param enabled - Whether to pause on blur
|
|
112
|
+
*/
|
|
113
|
+
enablePauseOnBlur(enabled: boolean): void;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Set target frame rate.
|
|
117
|
+
* @param fps - Target FPS
|
|
118
|
+
*/
|
|
119
|
+
setFPS(fps: number): void;
|
|
120
|
+
|
|
121
|
+
/** Mark that bounds need recalculation */
|
|
122
|
+
markBoundsDirty(): void;
|
|
123
|
+
/** Reset to default cursor */
|
|
124
|
+
resetCursor(): void;
|
|
125
|
+
|
|
126
|
+
/** Override for custom resize handling */
|
|
127
|
+
onResize?(): void;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ==========================================================================
|
|
131
|
+
// Pipeline
|
|
132
|
+
// ==========================================================================
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Pipeline for managing GameObjects lifecycle.
|
|
136
|
+
* Handles update and render cycles for all registered objects.
|
|
137
|
+
*/
|
|
138
|
+
export class Pipeline {
|
|
139
|
+
/**
|
|
140
|
+
* Create a new Pipeline.
|
|
141
|
+
* @param game - The game instance
|
|
142
|
+
*/
|
|
143
|
+
constructor(game: Game);
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Add a game object to the pipeline.
|
|
147
|
+
* @param object - GameObject to add
|
|
148
|
+
*/
|
|
149
|
+
add(object: GameObject): void;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Remove a game object from the pipeline.
|
|
153
|
+
* @param object - GameObject to remove
|
|
154
|
+
*/
|
|
155
|
+
remove(object: GameObject): void;
|
|
156
|
+
|
|
157
|
+
/** Remove all objects from the pipeline */
|
|
158
|
+
clear(): void;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Update all objects.
|
|
162
|
+
* @param dt - Delta time
|
|
163
|
+
*/
|
|
164
|
+
update(dt: number): void;
|
|
165
|
+
|
|
166
|
+
/** Render all objects */
|
|
167
|
+
render(): void;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ==========================================================================
|
|
171
|
+
// GameObject
|
|
172
|
+
// ==========================================================================
|
|
173
|
+
|
|
174
|
+
/** Options for GameObject */
|
|
175
|
+
export interface GameObjectOptions extends TransformableOptions {
|
|
176
|
+
/** Whether object responds to input events */
|
|
177
|
+
interactive?: boolean;
|
|
178
|
+
/** Screen anchor position (e.g., "top-left", "center") */
|
|
179
|
+
anchor?: string | Point;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Base class for interactive game entities.
|
|
184
|
+
* Extends Transformable with events and hit testing.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* const player = new GameObject(game, {
|
|
188
|
+
* x: 100, y: 100,
|
|
189
|
+
* width: 50, height: 50,
|
|
190
|
+
* interactive: true
|
|
191
|
+
* });
|
|
192
|
+
* player.on('click', () => console.log('Player clicked!'));
|
|
193
|
+
*/
|
|
194
|
+
export class GameObject extends Transformable {
|
|
195
|
+
/** Reference to the game instance */
|
|
196
|
+
game: Game;
|
|
197
|
+
/** Event emitter for this object */
|
|
198
|
+
events: EventEmitter;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Create a new GameObject.
|
|
202
|
+
* @param game - The game instance
|
|
203
|
+
* @param options - Configuration options
|
|
204
|
+
*/
|
|
205
|
+
constructor(game: Game, options?: GameObjectOptions);
|
|
206
|
+
|
|
207
|
+
/** Whether object responds to input */
|
|
208
|
+
get interactive(): boolean;
|
|
209
|
+
set interactive(value: boolean);
|
|
210
|
+
/** Whether pointer is over this object */
|
|
211
|
+
get hovered(): boolean;
|
|
212
|
+
set hovered(value: boolean);
|
|
213
|
+
|
|
214
|
+
/** Update the object (override in subclasses) */
|
|
215
|
+
update(dt: number): void;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Subscribe to an event.
|
|
219
|
+
* @param event - Event name
|
|
220
|
+
* @param callback - Handler function
|
|
221
|
+
*/
|
|
222
|
+
on<T = any>(event: string, callback: EventCallback<T>): void;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Unsubscribe from an event.
|
|
226
|
+
* @param event - Event name
|
|
227
|
+
* @param callback - Handler function
|
|
228
|
+
*/
|
|
229
|
+
off<T = any>(event: string, callback: EventCallback<T>): void;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Emit an event.
|
|
233
|
+
* @param event - Event name
|
|
234
|
+
* @param args - Event arguments
|
|
235
|
+
*/
|
|
236
|
+
emit<T = any>(event: string, ...args: any[]): void;
|
|
237
|
+
|
|
238
|
+
/** @internal Test if point is inside object bounds */
|
|
239
|
+
_hitTest(x: number, y: number): boolean;
|
|
240
|
+
/** @internal Set hover state */
|
|
241
|
+
_setHovered(state: boolean): void;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ==========================================================================
|
|
245
|
+
// Scene
|
|
246
|
+
// ==========================================================================
|
|
247
|
+
|
|
248
|
+
/** Options for Scene */
|
|
249
|
+
export interface SceneOptions extends GameObjectOptions {
|
|
250
|
+
/** Sort children by zIndex before rendering */
|
|
251
|
+
sortByZIndex?: boolean;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Hierarchical container for GameObjects with z-ordering.
|
|
256
|
+
* Use scenes to group related objects and manage their lifecycle.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* const uiScene = new Scene(game, { x: 0, y: 0 });
|
|
260
|
+
* uiScene.add(new Button(game, { label: 'Start' }));
|
|
261
|
+
* game.pipeline.add(uiScene);
|
|
262
|
+
*/
|
|
263
|
+
export class Scene extends GameObject {
|
|
264
|
+
/**
|
|
265
|
+
* Create a new Scene.
|
|
266
|
+
* @param game - The game instance
|
|
267
|
+
* @param options - Configuration options
|
|
268
|
+
*/
|
|
269
|
+
constructor(game: Game, options?: SceneOptions);
|
|
270
|
+
|
|
271
|
+
/** Get all child objects */
|
|
272
|
+
get children(): GameObject[];
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Add a child object.
|
|
276
|
+
* @param object - GameObject to add
|
|
277
|
+
* @returns The added object
|
|
278
|
+
*/
|
|
279
|
+
add(object: GameObject): GameObject;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Remove a child object.
|
|
283
|
+
* @param object - GameObject to remove
|
|
284
|
+
* @returns Whether object was found and removed
|
|
285
|
+
*/
|
|
286
|
+
remove(object: GameObject): boolean;
|
|
287
|
+
|
|
288
|
+
/** Remove all children */
|
|
289
|
+
clear(): void;
|
|
290
|
+
|
|
291
|
+
/** Move object to front (highest z-order) */
|
|
292
|
+
bringToFront(object: GameObject): void;
|
|
293
|
+
|
|
294
|
+
/** Move object to back (lowest z-order) */
|
|
295
|
+
sendToBack(object: GameObject): void;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ==========================================================================
|
|
299
|
+
// Shape Wrappers
|
|
300
|
+
// ==========================================================================
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Wraps a Shape as a GameObject for use in the pipeline.
|
|
304
|
+
* Allows using pure shapes in the game object system.
|
|
305
|
+
*/
|
|
306
|
+
export class GameObjectShapeWrapper extends GameObject {
|
|
307
|
+
/** The wrapped shape */
|
|
308
|
+
shape: Shape;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Create a wrapper for a shape.
|
|
312
|
+
* @param game - The game instance
|
|
313
|
+
* @param shape - Shape to wrap
|
|
314
|
+
* @param options - Additional options
|
|
315
|
+
*/
|
|
316
|
+
constructor(game: Game, shape: Shape, options?: GameObjectOptions);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Factory for quickly creating GameObject wrappers for shapes.
|
|
321
|
+
*/
|
|
322
|
+
export class ShapeGOFactory {
|
|
323
|
+
/**
|
|
324
|
+
* Wrap a shape as a GameObject.
|
|
325
|
+
* @param game - The game instance
|
|
326
|
+
* @param shape - Shape to wrap
|
|
327
|
+
* @param options - Additional options
|
|
328
|
+
*/
|
|
329
|
+
static wrap(game: Game, shape: Shape, options?: GameObjectOptions): GameObjectShapeWrapper;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// ==========================================================================
|
|
333
|
+
// Text GameObject
|
|
334
|
+
// ==========================================================================
|
|
335
|
+
|
|
336
|
+
/** Options for Text GameObject */
|
|
337
|
+
export interface TextGameObjectOptions extends GameObjectOptions {
|
|
338
|
+
/** CSS font string */
|
|
339
|
+
font?: string;
|
|
340
|
+
/** Text alignment */
|
|
341
|
+
align?: CanvasTextAlign;
|
|
342
|
+
/** Text baseline */
|
|
343
|
+
baseline?: CanvasTextBaseline;
|
|
344
|
+
/** Text color */
|
|
345
|
+
color?: string;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Text rendering as a GameObject.
|
|
350
|
+
*/
|
|
351
|
+
export class Text extends GameObject {
|
|
352
|
+
/** The text content */
|
|
353
|
+
text: string;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Create a Text object.
|
|
357
|
+
* @param game - The game instance
|
|
358
|
+
* @param text - Text to display
|
|
359
|
+
* @param options - Text options
|
|
360
|
+
*/
|
|
361
|
+
constructor(game: Game, text: string, options?: TextGameObjectOptions);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ==========================================================================
|
|
365
|
+
// Image GameObject
|
|
366
|
+
// ==========================================================================
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Image rendering as a GameObject.
|
|
370
|
+
*/
|
|
371
|
+
export class ImageGo extends GameObject {
|
|
372
|
+
/**
|
|
373
|
+
* Create an Image object.
|
|
374
|
+
* @param game - The game instance
|
|
375
|
+
* @param src - Image source URL or HTMLImageElement
|
|
376
|
+
* @param options - GameObject options
|
|
377
|
+
*/
|
|
378
|
+
constructor(game: Game, src: string | HTMLImageElement, options?: GameObjectOptions);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ==========================================================================
|
|
382
|
+
// Layout Scenes
|
|
383
|
+
// ==========================================================================
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Base layout container with automatic child positioning.
|
|
387
|
+
*/
|
|
388
|
+
export class LayoutScene extends Scene {
|
|
389
|
+
constructor(game: Game, options?: SceneOptions);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Horizontal layout - children arranged left to right.
|
|
394
|
+
*/
|
|
395
|
+
export class HorizontalLayout extends LayoutScene {
|
|
396
|
+
constructor(game: Game, options?: SceneOptions);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Vertical layout - children arranged top to bottom.
|
|
401
|
+
*/
|
|
402
|
+
export class VerticalLayout extends LayoutScene {
|
|
403
|
+
constructor(game: Game, options?: SceneOptions);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Tile layout - children arranged in a grid.
|
|
408
|
+
*/
|
|
409
|
+
export class TileLayout extends LayoutScene {
|
|
410
|
+
constructor(game: Game, options?: SceneOptions);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Flexible grid layout with configurable rows and columns.
|
|
415
|
+
*/
|
|
416
|
+
export class GridLayout extends LayoutScene {
|
|
417
|
+
constructor(game: Game, options?: SceneOptions);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// ==========================================================================
|
|
421
|
+
// UI Components
|
|
422
|
+
// ==========================================================================
|
|
423
|
+
|
|
424
|
+
/** Options for Button */
|
|
425
|
+
export interface ButtonOptions extends GameObjectOptions {
|
|
426
|
+
/** Button text */
|
|
427
|
+
label?: string;
|
|
428
|
+
/** CSS font string */
|
|
429
|
+
font?: string;
|
|
430
|
+
/** Padding around text */
|
|
431
|
+
padding?: number;
|
|
432
|
+
/** Background color (normal state) */
|
|
433
|
+
backgroundColor?: string;
|
|
434
|
+
/** Background color (hover state) */
|
|
435
|
+
hoverColor?: string;
|
|
436
|
+
/** Background color (pressed state) */
|
|
437
|
+
pressedColor?: string;
|
|
438
|
+
/** Text color */
|
|
439
|
+
textColor?: string;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Interactive button component.
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* const btn = new Button(game, {
|
|
447
|
+
* x: 100, y: 100,
|
|
448
|
+
* label: 'Click Me',
|
|
449
|
+
* backgroundColor: '#3498db'
|
|
450
|
+
* });
|
|
451
|
+
* btn.on('click', () => console.log('Button clicked!'));
|
|
452
|
+
*/
|
|
453
|
+
export class Button extends GameObject {
|
|
454
|
+
/** Button label text */
|
|
455
|
+
label: string;
|
|
456
|
+
|
|
457
|
+
constructor(game: Game, options?: ButtonOptions);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Toggle button component (on/off state).
|
|
462
|
+
*/
|
|
463
|
+
export class ToggleButton extends Button {
|
|
464
|
+
/** Current toggle state */
|
|
465
|
+
toggled: boolean;
|
|
466
|
+
|
|
467
|
+
constructor(game: Game, options?: ButtonOptions);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** Options for Cursor */
|
|
471
|
+
export interface CursorOptions extends GameObjectOptions {
|
|
472
|
+
/** Cursor image */
|
|
473
|
+
image?: HTMLImageElement | string;
|
|
474
|
+
/** Hotspot offset from cursor position */
|
|
475
|
+
hotspot?: Point;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Custom cursor component.
|
|
480
|
+
* Hides the system cursor and renders a custom one.
|
|
481
|
+
*/
|
|
482
|
+
export class Cursor extends GameObject {
|
|
483
|
+
constructor(game: Game, options?: CursorOptions);
|
|
484
|
+
|
|
485
|
+
/** Activate this cursor (hide system cursor) */
|
|
486
|
+
activate(): void;
|
|
487
|
+
/** Destroy and restore system cursor */
|
|
488
|
+
destroy(): void;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* FPS counter display component.
|
|
493
|
+
* Shows real-time frame rate.
|
|
494
|
+
*/
|
|
495
|
+
export class FPSCounter extends GameObject {
|
|
496
|
+
constructor(game: Game, options?: GameObjectOptions);
|
|
497
|
+
}
|