@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,204 @@
|
|
|
1
|
+
# Architecture Overview
|
|
2
|
+
|
|
3
|
+
> High-level system architecture, module relationships, and design philosophy.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
GCanvas is a modular 2D rendering and game framework built on top of the HTML5 Canvas API. It follows a layered architecture where each module has a clear responsibility and minimal coupling to other modules.
|
|
8
|
+
|
|
9
|
+
The library is designed around three core principles:
|
|
10
|
+
|
|
11
|
+
1. **Modularity** - Use only what you need
|
|
12
|
+
2. **Composability** - Combine simple parts to build complex systems
|
|
13
|
+
3. **Zero Dependencies** - Pure JavaScript, works everywhere
|
|
14
|
+
|
|
15
|
+
## Module Architecture
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
19
|
+
│ GCanvas │
|
|
20
|
+
│ (index.js) │
|
|
21
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
22
|
+
│ │
|
|
23
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
24
|
+
│ │ Core Modules │ │
|
|
25
|
+
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │
|
|
26
|
+
│ │ │ shapes/ │ │ game/ │ │ painter/ │ │ │
|
|
27
|
+
│ │ │ 40+ shapes │ │ Game loop │ │ Canvas API │ │ │
|
|
28
|
+
│ │ │ hierarchy │ │ Pipeline │ │ abstraction │ │ │
|
|
29
|
+
│ │ │ Group │ │ GameObject │ │ │ │ │
|
|
30
|
+
│ │ └─────────────┘ └─────────────┘ └─────────────────┘ │ │
|
|
31
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
32
|
+
│ │
|
|
33
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
34
|
+
│ │ Support Modules │ │
|
|
35
|
+
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
|
|
36
|
+
│ │ │ motion │ │ io │ │ math │ │ util │ │ mixins │ │ │
|
|
37
|
+
│ │ │ Tween │ │ Events │ │ Random │ │ Layout │ │Draggable│ │ │
|
|
38
|
+
│ │ │ Easing │ │ Mouse │ │ Noise │ │Position│ │ Anchor │ │ │
|
|
39
|
+
│ │ │ Motion │ │ Keys │ │Fractals│ │ZIndex │ │ │ │ │
|
|
40
|
+
│ │ │Tweenetik│ │ Touch │ │Patterns│ │ Tasks │ │ │ │ │
|
|
41
|
+
│ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │
|
|
42
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
43
|
+
│ │
|
|
44
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
45
|
+
│ │ Utility Modules │ │
|
|
46
|
+
│ │ ┌────────┐ │ │
|
|
47
|
+
│ │ │ logger │ │ │
|
|
48
|
+
│ │ │ Logger │ │ │
|
|
49
|
+
│ │ │Loggable│ │ │
|
|
50
|
+
│ │ │DebugTab│ │ │
|
|
51
|
+
│ │ └────────┘ │ │
|
|
52
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
53
|
+
│ │
|
|
54
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Module Responsibilities
|
|
58
|
+
|
|
59
|
+
### Core Modules
|
|
60
|
+
|
|
61
|
+
| Module | Responsibility | Key Classes |
|
|
62
|
+
|--------|---------------|-------------|
|
|
63
|
+
| **shapes** | Visual primitives and rendering | `Shape`, `Circle`, `Rectangle`, `Group`, `Transformable` |
|
|
64
|
+
| **game** | Game loop, lifecycle, object management | `Game`, `Pipeline`, `GameObject`, `Scene` |
|
|
65
|
+
| **painter** | Canvas context abstraction | `Painter`, `PainterShapes`, `PainterText` |
|
|
66
|
+
|
|
67
|
+
### Support Modules
|
|
68
|
+
|
|
69
|
+
| Module | Responsibility | Key Classes |
|
|
70
|
+
|--------|---------------|-------------|
|
|
71
|
+
| **motion** | Animation and tweening | `Motion`, `Tweenetik`, `Easing`, `Tween` |
|
|
72
|
+
| **io** | Input handling | `EventEmitter`, `Mouse`, `Keys`, `Touch`, `Input` |
|
|
73
|
+
| **math** | Mathematical utilities | `Random`, `Noise`, `Complex`, `Fractals`, `Patterns` |
|
|
74
|
+
| **util** | Layout and positioning | `Layout`, `Position`, `ZOrderedCollection` |
|
|
75
|
+
| **mixins** | Composable behaviors | `applyDraggable()`, `applyAnchor()` |
|
|
76
|
+
|
|
77
|
+
### Utility Modules
|
|
78
|
+
|
|
79
|
+
| Module | Responsibility | Key Classes |
|
|
80
|
+
|--------|---------------|-------------|
|
|
81
|
+
| **logger** | Debug and logging | `Logger`, `Loggable`, `DebugTab` |
|
|
82
|
+
|
|
83
|
+
## Data Flow
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
User Input Game Loop
|
|
87
|
+
│ │
|
|
88
|
+
▼ ▼
|
|
89
|
+
┌────────┐ events ┌────────┐
|
|
90
|
+
│ IO │ ──────────────────►│ Game │
|
|
91
|
+
└────────┘ └────────┘
|
|
92
|
+
│
|
|
93
|
+
┌──────────────┼──────────────┐
|
|
94
|
+
▼ ▼ ▼
|
|
95
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
96
|
+
│ Pipeline │ │ Tweenetik│ │ Painter │
|
|
97
|
+
│ update() │ │ update() │ │ clear() │
|
|
98
|
+
└──────────┘ └──────────┘ └──────────┘
|
|
99
|
+
│
|
|
100
|
+
▼
|
|
101
|
+
┌──────────┐
|
|
102
|
+
│GameObject│
|
|
103
|
+
│ update() │
|
|
104
|
+
│ render() │
|
|
105
|
+
└──────────┘
|
|
106
|
+
│
|
|
107
|
+
▼
|
|
108
|
+
┌──────────┐
|
|
109
|
+
│ Shape │
|
|
110
|
+
│ draw() │
|
|
111
|
+
└──────────┘
|
|
112
|
+
│
|
|
113
|
+
▼
|
|
114
|
+
┌──────────┐
|
|
115
|
+
│ Painter │
|
|
116
|
+
│ Canvas │
|
|
117
|
+
└──────────┘
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Design Patterns
|
|
121
|
+
|
|
122
|
+
### 1. Inheritance Chain (Shapes)
|
|
123
|
+
|
|
124
|
+
Shapes use a linear inheritance hierarchy where each class adds specific functionality:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Euclidian → Geometry2d → Traceable → Renderable → Transformable → Shape
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
See: [Rendering Pipeline](./rendering-pipeline.md)
|
|
131
|
+
|
|
132
|
+
### 2. Static Singleton (Painter)
|
|
133
|
+
|
|
134
|
+
`Painter` is a static utility class initialized once with the canvas context:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
Painter.init(ctx);
|
|
138
|
+
Painter.shapes.circle(100, 100, 50);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 3. Component Pattern (GameObject + Shape)
|
|
142
|
+
|
|
143
|
+
GameObjects compose shapes rather than inheriting from them:
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
class Player extends GameObject {
|
|
147
|
+
constructor(game) {
|
|
148
|
+
super(game);
|
|
149
|
+
this.shape = new Circle(40, { color: 'blue' });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 4. Mixin Pattern (Behaviors)
|
|
155
|
+
|
|
156
|
+
Optional behaviors are applied via mixin functions:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
applyDraggable(gameObject, gameObject.shape);
|
|
160
|
+
applyAnchor(gameObject, { anchor: 'top-right' });
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 5. Observer Pattern (Events)
|
|
164
|
+
|
|
165
|
+
The `EventEmitter` provides pub-sub event handling:
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
game.events.on('click', (e) => { ... });
|
|
169
|
+
game.events.emit('custom-event', data);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Entry Point
|
|
173
|
+
|
|
174
|
+
The main entry point (`src/index.js`) re-exports all modules:
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
export * from "./util";
|
|
178
|
+
export * from "./math";
|
|
179
|
+
export * from "./logger";
|
|
180
|
+
export * from "./painter";
|
|
181
|
+
export * from "./shapes";
|
|
182
|
+
export * from "./io";
|
|
183
|
+
export * from "./game";
|
|
184
|
+
export * from "./motion";
|
|
185
|
+
export * from "./mixins";
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
This allows importing any component from the main package:
|
|
189
|
+
|
|
190
|
+
```js
|
|
191
|
+
import { Game, Circle, Painter, Motion } from 'gcanvas';
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Related
|
|
195
|
+
|
|
196
|
+
- [Two-Layer Architecture](./two-layer-architecture.md) - Shape vs Game layer
|
|
197
|
+
- [Rendering Pipeline](./rendering-pipeline.md) - Shape inheritance chain
|
|
198
|
+
- [Game Lifecycle](./lifecycle.md) - Update/render cycle
|
|
199
|
+
|
|
200
|
+
## See Also
|
|
201
|
+
|
|
202
|
+
- [Shapes Module](../modules/shapes/README.md)
|
|
203
|
+
- [Game Module](../modules/game/README.md)
|
|
204
|
+
- [Painter Module](../modules/painter/README.md)
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Game Lifecycle
|
|
2
|
+
|
|
3
|
+
> Understanding the update/render cycle and frame timing.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Game class manages the core game loop using `requestAnimationFrame`. It provides a fixed-timestep update cycle with automatic delta time calculation, ensuring consistent gameplay regardless of frame rate.
|
|
8
|
+
|
|
9
|
+
## The Game Loop
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ Game Loop │
|
|
14
|
+
│ │
|
|
15
|
+
│ game.start() │
|
|
16
|
+
│ │ │
|
|
17
|
+
│ ▼ │
|
|
18
|
+
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
19
|
+
│ │ requestAnimationFrame │ │
|
|
20
|
+
│ │ │ │ │
|
|
21
|
+
│ │ ▼ │ │
|
|
22
|
+
│ │ ┌─────────────────────────────────────────────────┐ │ │
|
|
23
|
+
│ │ │ loop(timestamp) │ │ │
|
|
24
|
+
│ │ │ │ │ │
|
|
25
|
+
│ │ │ 1. Calculate elapsed time │ │ │
|
|
26
|
+
│ │ │ elapsed = timestamp - lastTime │ │ │
|
|
27
|
+
│ │ │ │ │ │
|
|
28
|
+
│ │ │ 2. Accumulate time │ │ │
|
|
29
|
+
│ │ │ accumulator += elapsed │ │ │
|
|
30
|
+
│ │ │ │ │ │
|
|
31
|
+
│ │ │ 3. While accumulator >= frameInterval: │ │ │
|
|
32
|
+
│ │ │ │ │ │ │
|
|
33
|
+
│ │ │ ├─► update(dt) │ │ │
|
|
34
|
+
│ │ │ │ │ │ │ │
|
|
35
|
+
│ │ │ │ ├─► Pipeline.update(dt) │ │ │
|
|
36
|
+
│ │ │ │ │ └─► GameObject.update(dt) │ │ │
|
|
37
|
+
│ │ │ │ │ │ │ │
|
|
38
|
+
│ │ │ │ └─► Tweenetik.updateAll(dt) │ │ │
|
|
39
|
+
│ │ │ │ │ │ │
|
|
40
|
+
│ │ │ └─► accumulator -= frameInterval │ │ │
|
|
41
|
+
│ │ │ │ │ │
|
|
42
|
+
│ │ │ 4. render() │ │ │
|
|
43
|
+
│ │ │ │ │ │ │
|
|
44
|
+
│ │ │ ├─► Painter.clear() │ │ │
|
|
45
|
+
│ │ │ │ │ │ │
|
|
46
|
+
│ │ │ └─► Pipeline.render() │ │ │
|
|
47
|
+
│ │ │ └─► GameObject.render() │ │ │
|
|
48
|
+
│ │ │ └─► Shape.draw() │ │ │
|
|
49
|
+
│ │ │ │ │ │
|
|
50
|
+
│ │ │ 5. requestAnimationFrame(loop) │ │ │
|
|
51
|
+
│ │ │ │ │ │
|
|
52
|
+
│ │ └─────────────────────────────────────────────────┘ │ │
|
|
53
|
+
│ │ │ │ │
|
|
54
|
+
│ │ └───────────────────────────────┼───┘
|
|
55
|
+
│ └─────────────────────────────────────────────────────────┘ │
|
|
56
|
+
│ │
|
|
57
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Fixed Timestep
|
|
61
|
+
|
|
62
|
+
GCanvas uses a **fixed timestep** pattern. This means:
|
|
63
|
+
|
|
64
|
+
- Updates happen at a consistent rate (default: 60 FPS)
|
|
65
|
+
- `dt` (delta time) is always the same value
|
|
66
|
+
- Game logic is frame-rate independent
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
// Default: 60 FPS = 16.67ms per frame
|
|
70
|
+
game.setFPS(60);
|
|
71
|
+
|
|
72
|
+
// dt in update() is always 1/60 = 0.01667 seconds
|
|
73
|
+
update(dt) {
|
|
74
|
+
// Move 200 pixels per second, regardless of actual frame rate
|
|
75
|
+
this.x += 200 * dt;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Lifecycle Methods
|
|
80
|
+
|
|
81
|
+
### Game Lifecycle
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
class MyGame extends Game {
|
|
85
|
+
constructor(canvas) {
|
|
86
|
+
super(canvas);
|
|
87
|
+
// 1. Constructor: Setup canvas, context, pipeline
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
init() {
|
|
91
|
+
super.init();
|
|
92
|
+
// 2. Init: Create scenes, objects, set up game state
|
|
93
|
+
// Called once before start()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
update(dt) {
|
|
97
|
+
super.update(dt);
|
|
98
|
+
// 3. Update: Game logic (called every frame)
|
|
99
|
+
// dt = time since last update in seconds
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
render() {
|
|
103
|
+
super.render();
|
|
104
|
+
// 4. Render: Drawing (called every frame after update)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const game = new MyGame(canvas);
|
|
109
|
+
game.start(); // Calls init() then starts the loop
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### GameObject Lifecycle
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
class Player extends GameObject {
|
|
116
|
+
constructor(game) {
|
|
117
|
+
super(game);
|
|
118
|
+
// 1. Constructor: Create shapes, set initial state
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
update(dt) {
|
|
122
|
+
// 2. Update: Movement, physics, game logic
|
|
123
|
+
// Called every frame while active
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
render() {
|
|
127
|
+
// 3. Render: Draw the object
|
|
128
|
+
// Called every frame while visible
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
destroy() {
|
|
132
|
+
super.destroy();
|
|
133
|
+
// 4. Destroy: Cleanup when removed
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Delta Time (dt)
|
|
139
|
+
|
|
140
|
+
The `dt` parameter represents time elapsed since the last update, in **seconds**.
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
update(dt) {
|
|
144
|
+
// dt ≈ 0.01667 at 60 FPS
|
|
145
|
+
// dt ≈ 0.03333 at 30 FPS
|
|
146
|
+
|
|
147
|
+
// Movement: pixels per second
|
|
148
|
+
this.x += this.speed * dt; // speed = 200 means 200 px/sec
|
|
149
|
+
|
|
150
|
+
// Rotation: radians per second
|
|
151
|
+
this.rotation += Math.PI * dt; // Half rotation per second
|
|
152
|
+
|
|
153
|
+
// Timers
|
|
154
|
+
this.timer += dt;
|
|
155
|
+
if (this.timer >= 2.0) { // 2 seconds
|
|
156
|
+
this.doSomething();
|
|
157
|
+
this.timer = 0;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Frame Rate Control
|
|
163
|
+
|
|
164
|
+
```js
|
|
165
|
+
// Set target FPS
|
|
166
|
+
game.setFPS(60); // Default
|
|
167
|
+
game.setFPS(30); // Lower for mobile/performance
|
|
168
|
+
|
|
169
|
+
// Current frame number
|
|
170
|
+
console.log(game.frame);
|
|
171
|
+
|
|
172
|
+
// Pause on blur (tab switch)
|
|
173
|
+
game.enablePauseOnBlur(true);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Pipeline Execution Order
|
|
177
|
+
|
|
178
|
+
The Pipeline manages multiple objects and ensures proper execution order:
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
Pipeline.update(dt)
|
|
182
|
+
├─► Filter active objects
|
|
183
|
+
├─► Sort by zIndex
|
|
184
|
+
├─► For each object:
|
|
185
|
+
│ └─► object.update(dt)
|
|
186
|
+
└─► Tweenetik.updateAll(dt)
|
|
187
|
+
|
|
188
|
+
Pipeline.render()
|
|
189
|
+
├─► Filter visible objects
|
|
190
|
+
├─► Sort by zIndex (low to high)
|
|
191
|
+
└─► For each object:
|
|
192
|
+
└─► object.render()
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Scenes and Hierarchy
|
|
196
|
+
|
|
197
|
+
Scenes create nested lifecycles:
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
// Scene contains GameObjects
|
|
201
|
+
const scene = new Scene(game);
|
|
202
|
+
scene.add(player);
|
|
203
|
+
scene.add(enemy);
|
|
204
|
+
game.pipeline.add(scene);
|
|
205
|
+
|
|
206
|
+
// Lifecycle flows through hierarchy:
|
|
207
|
+
// Pipeline.update()
|
|
208
|
+
// └─► Scene.update()
|
|
209
|
+
// ├─► player.update()
|
|
210
|
+
// └─► enemy.update()
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## State Management
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
class MyGame extends Game {
|
|
217
|
+
init() {
|
|
218
|
+
this.state = 'menu'; // menu, playing, paused, gameover
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
update(dt) {
|
|
222
|
+
switch (this.state) {
|
|
223
|
+
case 'menu':
|
|
224
|
+
this.menuScene.update(dt);
|
|
225
|
+
break;
|
|
226
|
+
case 'playing':
|
|
227
|
+
this.gameScene.update(dt);
|
|
228
|
+
break;
|
|
229
|
+
case 'paused':
|
|
230
|
+
// Don't update game objects
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Performance Tips
|
|
238
|
+
|
|
239
|
+
1. **Use `active` flag** - Set `gameObject.active = false` to skip updates
|
|
240
|
+
2. **Use `visible` flag** - Set `shape.visible = false` to skip rendering
|
|
241
|
+
3. **Pool objects** - Reuse objects instead of creating/destroying
|
|
242
|
+
4. **Batch similar operations** - Group shapes in containers
|
|
243
|
+
5. **Profile with DevTools** - Use browser performance tools
|
|
244
|
+
|
|
245
|
+
## Related
|
|
246
|
+
|
|
247
|
+
- [Architecture Overview](./architecture-overview.md) - Full system architecture
|
|
248
|
+
- [Two-Layer Architecture](./two-layer-architecture.md) - Shape vs Game layer
|
|
249
|
+
- [Rendering Pipeline](./rendering-pipeline.md) - Shape inheritance chain
|
|
250
|
+
|
|
251
|
+
## See Also
|
|
252
|
+
|
|
253
|
+
- [Game Module](../modules/game/README.md)
|
|
254
|
+
- [Pipeline](../modules/game/pipeline.md)
|
|
255
|
+
- [GameObject](../modules/game/gameobject.md)
|