@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.
Files changed (349) hide show
  1. package/.github/workflows/release.yaml +70 -0
  2. package/.jshintrc +4 -0
  3. package/.vscode/settings.json +22 -0
  4. package/CLAUDE.md +310 -0
  5. package/blackhole.jpg +0 -0
  6. package/demo.png +0 -0
  7. package/demos/CNAME +1 -0
  8. package/demos/animations.html +31 -0
  9. package/demos/basic.html +38 -0
  10. package/demos/baskara.html +31 -0
  11. package/demos/bezier.html +35 -0
  12. package/demos/beziersignature.html +29 -0
  13. package/demos/blackhole.html +28 -0
  14. package/demos/blob.html +35 -0
  15. package/demos/demos.css +289 -0
  16. package/demos/easing.html +28 -0
  17. package/demos/events.html +195 -0
  18. package/demos/fluent.html +647 -0
  19. package/demos/fractals.html +36 -0
  20. package/demos/genart.html +26 -0
  21. package/demos/gendream.html +26 -0
  22. package/demos/group.html +36 -0
  23. package/demos/home.html +587 -0
  24. package/demos/index.html +364 -0
  25. package/demos/isometric.html +34 -0
  26. package/demos/js/animations.js +452 -0
  27. package/demos/js/basic.js +204 -0
  28. package/demos/js/baskara.js +751 -0
  29. package/demos/js/bezier.js +692 -0
  30. package/demos/js/beziersignature.js +241 -0
  31. package/demos/js/blackhole/accretiondisk.obj.js +379 -0
  32. package/demos/js/blackhole/blackhole.obj.js +318 -0
  33. package/demos/js/blackhole/index.js +409 -0
  34. package/demos/js/blackhole/particle.js +56 -0
  35. package/demos/js/blackhole/starfield.obj.js +218 -0
  36. package/demos/js/blob.js +2263 -0
  37. package/demos/js/easing.js +477 -0
  38. package/demos/js/fluent.js +183 -0
  39. package/demos/js/fractals.js +931 -0
  40. package/demos/js/fractalworker.js +93 -0
  41. package/demos/js/genart.js +268 -0
  42. package/demos/js/gendream.js +209 -0
  43. package/demos/js/group.js +140 -0
  44. package/demos/js/info-toggle.js +25 -0
  45. package/demos/js/isometric.js +863 -0
  46. package/demos/js/kerr.js +1556 -0
  47. package/demos/js/lavalamp.js +590 -0
  48. package/demos/js/layout.js +354 -0
  49. package/demos/js/mondrian.js +285 -0
  50. package/demos/js/opacity.js +275 -0
  51. package/demos/js/painter.js +484 -0
  52. package/demos/js/particles-showcase.js +514 -0
  53. package/demos/js/particles.js +299 -0
  54. package/demos/js/patterns.js +397 -0
  55. package/demos/js/penrose/artifact.js +69 -0
  56. package/demos/js/penrose/blackhole.js +121 -0
  57. package/demos/js/penrose/constants.js +73 -0
  58. package/demos/js/penrose/game.js +943 -0
  59. package/demos/js/penrose/lore.js +278 -0
  60. package/demos/js/penrose/penrosescene.js +892 -0
  61. package/demos/js/penrose/ship.js +216 -0
  62. package/demos/js/penrose/sounds.js +211 -0
  63. package/demos/js/penrose/voidparticle.js +55 -0
  64. package/demos/js/penrose/voidscene.js +258 -0
  65. package/demos/js/penrose/voidship.js +144 -0
  66. package/demos/js/penrose/wormhole.js +46 -0
  67. package/demos/js/pipeline.js +555 -0
  68. package/demos/js/scene.js +304 -0
  69. package/demos/js/scenes.js +320 -0
  70. package/demos/js/schrodinger.js +410 -0
  71. package/demos/js/schwarzschild.js +1023 -0
  72. package/demos/js/shapes.js +628 -0
  73. package/demos/js/space/alien.js +171 -0
  74. package/demos/js/space/boom.js +98 -0
  75. package/demos/js/space/boss.js +353 -0
  76. package/demos/js/space/buff.js +73 -0
  77. package/demos/js/space/bullet.js +102 -0
  78. package/demos/js/space/constants.js +85 -0
  79. package/demos/js/space/game.js +1884 -0
  80. package/demos/js/space/hud.js +112 -0
  81. package/demos/js/space/laserbeam.js +179 -0
  82. package/demos/js/space/lightning.js +277 -0
  83. package/demos/js/space/minion.js +192 -0
  84. package/demos/js/space/missile.js +212 -0
  85. package/demos/js/space/player.js +430 -0
  86. package/demos/js/space/powerup.js +90 -0
  87. package/demos/js/space/starfield.js +58 -0
  88. package/demos/js/space/starpower.js +90 -0
  89. package/demos/js/spacetime.js +559 -0
  90. package/demos/js/svgtween.js +204 -0
  91. package/demos/js/tde/accretiondisk.js +418 -0
  92. package/demos/js/tde/blackhole.js +219 -0
  93. package/demos/js/tde/blackholescene.js +209 -0
  94. package/demos/js/tde/config.js +59 -0
  95. package/demos/js/tde/index.js +695 -0
  96. package/demos/js/tde/jets.js +290 -0
  97. package/demos/js/tde/lensedstarfield.js +147 -0
  98. package/demos/js/tde/tdestar.js +317 -0
  99. package/demos/js/tde/tidalstream.js +356 -0
  100. package/demos/js/tde_old/blackhole.obj.js +354 -0
  101. package/demos/js/tde_old/debris.obj.js +791 -0
  102. package/demos/js/tde_old/flare.obj.js +239 -0
  103. package/demos/js/tde_old/index.js +448 -0
  104. package/demos/js/tde_old/star.obj.js +812 -0
  105. package/demos/js/tiles.js +312 -0
  106. package/demos/js/tweendemo.js +79 -0
  107. package/demos/js/visibility.js +102 -0
  108. package/demos/kerr.html +28 -0
  109. package/demos/lavalamp.html +27 -0
  110. package/demos/layouts.html +37 -0
  111. package/demos/logo.svg +4 -0
  112. package/demos/loop.html +84 -0
  113. package/demos/mondrian.html +32 -0
  114. package/demos/og_image.png +0 -0
  115. package/demos/opacity.html +36 -0
  116. package/demos/painter.html +39 -0
  117. package/demos/particles-showcase.html +28 -0
  118. package/demos/particles.html +24 -0
  119. package/demos/patterns.html +33 -0
  120. package/demos/penrose-game.html +31 -0
  121. package/demos/pipeline.html +737 -0
  122. package/demos/scene.html +33 -0
  123. package/demos/scenes.html +96 -0
  124. package/demos/schrodinger.html +27 -0
  125. package/demos/schwarzschild.html +27 -0
  126. package/demos/shapes.html +16 -0
  127. package/demos/space.html +85 -0
  128. package/demos/spacetime.html +27 -0
  129. package/demos/svgtween.html +29 -0
  130. package/demos/tde.html +28 -0
  131. package/demos/tiles.html +28 -0
  132. package/demos/transforms.html +400 -0
  133. package/demos/tween.html +45 -0
  134. package/demos/visibility.html +33 -0
  135. package/disk_example.png +0 -0
  136. package/docs/README.md +222 -0
  137. package/docs/concepts/architecture-overview.md +204 -0
  138. package/docs/concepts/lifecycle.md +255 -0
  139. package/docs/concepts/rendering-pipeline.md +279 -0
  140. package/docs/concepts/tde-zorder.md +106 -0
  141. package/docs/concepts/two-layer-architecture.md +229 -0
  142. package/docs/getting-started/first-game.md +354 -0
  143. package/docs/getting-started/hello-world.md +269 -0
  144. package/docs/getting-started/installation.md +157 -0
  145. package/docs/modules/collision/README.md +453 -0
  146. package/docs/modules/fluent/README.md +1075 -0
  147. package/docs/modules/game/README.md +303 -0
  148. package/docs/modules/isometric-camera.md +210 -0
  149. package/docs/modules/isometric.md +275 -0
  150. package/docs/modules/painter/README.md +328 -0
  151. package/docs/modules/particle/README.md +559 -0
  152. package/docs/modules/shapes/README.md +221 -0
  153. package/docs/modules/shapes/base/euclidian.md +123 -0
  154. package/docs/modules/shapes/base/geometry2d.md +204 -0
  155. package/docs/modules/shapes/base/renderable.md +215 -0
  156. package/docs/modules/shapes/base/shape.md +262 -0
  157. package/docs/modules/shapes/base/transformable.md +243 -0
  158. package/docs/modules/shapes/hierarchy.md +218 -0
  159. package/docs/modules/state/README.md +577 -0
  160. package/docs/modules/util/README.md +99 -0
  161. package/docs/modules/util/camera3d.md +412 -0
  162. package/docs/modules/util/scene3d.md +395 -0
  163. package/index.html +17 -0
  164. package/jsdoc.json +50 -0
  165. package/package.json +55 -0
  166. package/readme.md +599 -0
  167. package/scripts/build-demo.js +69 -0
  168. package/scripts/bundle4llm.js +276 -0
  169. package/scripts/clearconsole.js +48 -0
  170. package/src/collision/collision-system.js +332 -0
  171. package/src/collision/collision.js +303 -0
  172. package/src/collision/index.js +10 -0
  173. package/src/fluent/fluent-game.js +430 -0
  174. package/src/fluent/fluent-go.js +1060 -0
  175. package/src/fluent/fluent-layer.js +152 -0
  176. package/src/fluent/fluent-scene.js +291 -0
  177. package/src/fluent/index.js +98 -0
  178. package/src/fluent/sketch.js +380 -0
  179. package/src/game/game.js +467 -0
  180. package/src/game/index.js +49 -0
  181. package/src/game/objects/go.js +220 -0
  182. package/src/game/objects/imagego.js +30 -0
  183. package/src/game/objects/index.js +54 -0
  184. package/src/game/objects/isometric-scene.js +260 -0
  185. package/src/game/objects/layoutscene.js +549 -0
  186. package/src/game/objects/scene.js +175 -0
  187. package/src/game/objects/scene3d.js +118 -0
  188. package/src/game/objects/text.js +221 -0
  189. package/src/game/objects/wrapper.js +232 -0
  190. package/src/game/pipeline.js +243 -0
  191. package/src/game/ui/button.js +396 -0
  192. package/src/game/ui/cursor.js +93 -0
  193. package/src/game/ui/fps.js +91 -0
  194. package/src/game/ui/index.js +5 -0
  195. package/src/game/ui/togglebutton.js +93 -0
  196. package/src/game/ui/tooltip.js +249 -0
  197. package/src/index.js +25 -0
  198. package/src/io/events.js +20 -0
  199. package/src/io/index.js +86 -0
  200. package/src/io/input.js +70 -0
  201. package/src/io/keys.js +152 -0
  202. package/src/io/mouse.js +61 -0
  203. package/src/io/touch.js +39 -0
  204. package/src/logger/debugtab.js +138 -0
  205. package/src/logger/index.js +3 -0
  206. package/src/logger/loggable.js +47 -0
  207. package/src/logger/logger.js +113 -0
  208. package/src/math/complex.js +37 -0
  209. package/src/math/constants.js +1 -0
  210. package/src/math/fractal.js +1271 -0
  211. package/src/math/gr.js +201 -0
  212. package/src/math/heat.js +202 -0
  213. package/src/math/index.js +12 -0
  214. package/src/math/noise.js +433 -0
  215. package/src/math/orbital.js +191 -0
  216. package/src/math/patterns.js +1339 -0
  217. package/src/math/penrose.js +259 -0
  218. package/src/math/quantum.js +115 -0
  219. package/src/math/random.js +195 -0
  220. package/src/math/tensor.js +1009 -0
  221. package/src/mixins/anchor.js +131 -0
  222. package/src/mixins/draggable.js +72 -0
  223. package/src/mixins/index.js +2 -0
  224. package/src/motion/bezier.js +132 -0
  225. package/src/motion/bounce.js +58 -0
  226. package/src/motion/easing.js +349 -0
  227. package/src/motion/float.js +130 -0
  228. package/src/motion/follow.js +125 -0
  229. package/src/motion/hop.js +52 -0
  230. package/src/motion/index.js +82 -0
  231. package/src/motion/motion.js +1124 -0
  232. package/src/motion/orbit.js +49 -0
  233. package/src/motion/oscillate.js +39 -0
  234. package/src/motion/parabolic.js +141 -0
  235. package/src/motion/patrol.js +147 -0
  236. package/src/motion/pendulum.js +48 -0
  237. package/src/motion/pulse.js +88 -0
  238. package/src/motion/shake.js +83 -0
  239. package/src/motion/spiral.js +144 -0
  240. package/src/motion/spring.js +150 -0
  241. package/src/motion/swing.js +47 -0
  242. package/src/motion/tween.js +92 -0
  243. package/src/motion/tweenetik.js +139 -0
  244. package/src/motion/waypoint.js +210 -0
  245. package/src/painter/index.js +8 -0
  246. package/src/painter/painter.colors.js +331 -0
  247. package/src/painter/painter.effects.js +230 -0
  248. package/src/painter/painter.img.js +229 -0
  249. package/src/painter/painter.js +295 -0
  250. package/src/painter/painter.lines.js +189 -0
  251. package/src/painter/painter.opacity.js +41 -0
  252. package/src/painter/painter.shapes.js +277 -0
  253. package/src/painter/painter.text.js +273 -0
  254. package/src/particle/emitter.js +124 -0
  255. package/src/particle/index.js +11 -0
  256. package/src/particle/particle-system.js +322 -0
  257. package/src/particle/particle.js +71 -0
  258. package/src/particle/updaters.js +170 -0
  259. package/src/shapes/arc.js +43 -0
  260. package/src/shapes/arrow.js +33 -0
  261. package/src/shapes/bezier.js +42 -0
  262. package/src/shapes/circle.js +62 -0
  263. package/src/shapes/clouds.js +56 -0
  264. package/src/shapes/cone.js +219 -0
  265. package/src/shapes/cross.js +70 -0
  266. package/src/shapes/cube.js +244 -0
  267. package/src/shapes/cylinder.js +254 -0
  268. package/src/shapes/diamond.js +48 -0
  269. package/src/shapes/euclidian.js +111 -0
  270. package/src/shapes/figure.js +115 -0
  271. package/src/shapes/geometry.js +220 -0
  272. package/src/shapes/group.js +375 -0
  273. package/src/shapes/heart.js +42 -0
  274. package/src/shapes/hexagon.js +26 -0
  275. package/src/shapes/image.js +192 -0
  276. package/src/shapes/index.js +111 -0
  277. package/src/shapes/line.js +29 -0
  278. package/src/shapes/pattern.js +90 -0
  279. package/src/shapes/pin.js +44 -0
  280. package/src/shapes/poly.js +31 -0
  281. package/src/shapes/prism.js +226 -0
  282. package/src/shapes/rect.js +35 -0
  283. package/src/shapes/renderable.js +333 -0
  284. package/src/shapes/ring.js +26 -0
  285. package/src/shapes/roundrect.js +95 -0
  286. package/src/shapes/shape.js +117 -0
  287. package/src/shapes/slice.js +26 -0
  288. package/src/shapes/sphere.js +314 -0
  289. package/src/shapes/sphere3d.js +537 -0
  290. package/src/shapes/square.js +15 -0
  291. package/src/shapes/star.js +99 -0
  292. package/src/shapes/svg.js +408 -0
  293. package/src/shapes/text.js +553 -0
  294. package/src/shapes/traceable.js +83 -0
  295. package/src/shapes/transform.js +357 -0
  296. package/src/shapes/transformable.js +172 -0
  297. package/src/shapes/triangle.js +26 -0
  298. package/src/sound/index.js +17 -0
  299. package/src/sound/sound.js +473 -0
  300. package/src/sound/synth.analyzer.js +149 -0
  301. package/src/sound/synth.effects.js +207 -0
  302. package/src/sound/synth.envelope.js +59 -0
  303. package/src/sound/synth.js +229 -0
  304. package/src/sound/synth.musical.js +160 -0
  305. package/src/sound/synth.noise.js +85 -0
  306. package/src/sound/synth.oscillators.js +293 -0
  307. package/src/state/index.js +10 -0
  308. package/src/state/state-machine.js +371 -0
  309. package/src/util/camera3d.js +438 -0
  310. package/src/util/index.js +6 -0
  311. package/src/util/isometric-camera.js +235 -0
  312. package/src/util/layout.js +317 -0
  313. package/src/util/position.js +147 -0
  314. package/src/util/tasks.js +47 -0
  315. package/src/util/zindex.js +287 -0
  316. package/src/webgl/index.js +9 -0
  317. package/src/webgl/shaders/sphere-shaders.js +994 -0
  318. package/src/webgl/webgl-renderer.js +388 -0
  319. package/tde.png +0 -0
  320. package/test/math/orbital.test.js +61 -0
  321. package/test/math/tensor.test.js +114 -0
  322. package/test/particle/emitter.test.js +204 -0
  323. package/test/particle/particle-system.test.js +310 -0
  324. package/test/particle/particle.test.js +116 -0
  325. package/test/particle/updaters.test.js +386 -0
  326. package/test/setup.js +120 -0
  327. package/test/shapes/euclidian.test.js +44 -0
  328. package/test/shapes/geometry.test.js +86 -0
  329. package/test/shapes/group.test.js +86 -0
  330. package/test/shapes/rectangle.test.js +64 -0
  331. package/test/shapes/transform.test.js +379 -0
  332. package/test/util/camera3d.test.js +428 -0
  333. package/test/util/scene3d.test.js +352 -0
  334. package/types/collision.d.ts +249 -0
  335. package/types/common.d.ts +155 -0
  336. package/types/game.d.ts +497 -0
  337. package/types/index.d.ts +309 -0
  338. package/types/io.d.ts +188 -0
  339. package/types/logger.d.ts +127 -0
  340. package/types/math.d.ts +268 -0
  341. package/types/mixins.d.ts +92 -0
  342. package/types/motion.d.ts +678 -0
  343. package/types/painter.d.ts +378 -0
  344. package/types/shapes.d.ts +864 -0
  345. package/types/sound.d.ts +672 -0
  346. package/types/state.d.ts +251 -0
  347. package/types/util.d.ts +253 -0
  348. package/vite.config.js +50 -0
  349. package/vitest.config.js +13 -0
@@ -0,0 +1,279 @@
1
+ # Rendering Pipeline
2
+
3
+ > The shape inheritance chain from Euclidian to concrete shapes.
4
+
5
+ ## Overview
6
+
7
+ Every visual element in GCanvas inherits from a chain of base classes. Each layer adds specific functionality, building from simple spatial properties to full rendering capabilities.
8
+
9
+ ## The Inheritance Chain
10
+
11
+ ```
12
+ ┌─────────────────────────────────────────────────────────────────┐
13
+ │ │
14
+ │ Euclidian │
15
+ │ ├── x, y (position) │
16
+ │ ├── width, height (dimensions) │
17
+ │ └── debug rendering support │
18
+ │ │ │
19
+ │ ▼ │
20
+ │ Geometry2d │
21
+ │ ├── getBounds() - bounding box calculation │
22
+ │ ├── minX, maxX, minY, maxY - constraints │
23
+ │ ├── crisp - pixel-perfect alignment │
24
+ │ └── dirty flag tracking │
25
+ │ │ │
26
+ │ ▼ │
27
+ │ Traceable │
28
+ │ ├── drawDebug() - debug visualization │
29
+ │ └── logging capabilities │
30
+ │ │ │
31
+ │ ▼ │
32
+ │ Renderable │
33
+ │ ├── visible - show/hide │
34
+ │ ├── opacity - transparency (0-1) │
35
+ │ ├── shadowColor, shadowBlur, shadowOffset │
36
+ │ ├── blendMode - canvas composite operation │
37
+ │ ├── zIndex - stacking order │
38
+ │ └── render() - main render lifecycle │
39
+ │ │ │
40
+ │ ▼ │
41
+ │ Transformable │
42
+ │ ├── rotation - angle in radians │
43
+ │ ├── scaleX, scaleY - scaling factors │
44
+ │ ├── applyTransforms() - canvas transform │
45
+ │ └── getTransformedBounds() - rotated bounds │
46
+ │ │ │
47
+ │ ▼ │
48
+ │ Shape │
49
+ │ ├── color - fill color │
50
+ │ ├── stroke - stroke color │
51
+ │ ├── lineWidth, lineJoin, lineCap │
52
+ │ └── draw() - abstract (override in subclasses) │
53
+ │ │ │
54
+ │ ▼ │
55
+ │ ┌─────────┬─────────┬─────────┬─────────┬─────────┐ │
56
+ │ │ Circle │Rectangle│ Star │ Cube │ ... │ │
57
+ │ │ draw() │ draw() │ draw() │ draw() │ │ │
58
+ │ └─────────┴─────────┴─────────┴─────────┴─────────┘ │
59
+ │ │
60
+ └─────────────────────────────────────────────────────────────────┘
61
+ ```
62
+
63
+ ## Layer Details
64
+
65
+ ### 1. Euclidian
66
+
67
+ **Source:** `src/shapes/euclidian.js`
68
+
69
+ The foundation class providing basic spatial properties.
70
+
71
+ ```js
72
+ class Euclidian {
73
+ x = 0; // Center X position
74
+ y = 0; // Center Y position
75
+ width = 0; // Width
76
+ height = 0; // Height
77
+ }
78
+ ```
79
+
80
+ **Key Concept:** Position is center-based, not top-left. A shape at `(100, 100)` has its center at that point.
81
+
82
+ ### 2. Geometry2d
83
+
84
+ **Source:** `src/shapes/geometry.js`
85
+
86
+ Adds bounding box calculations and positional constraints.
87
+
88
+ ```js
89
+ // Get the bounding box
90
+ const bounds = shape.getBounds();
91
+ // { x, y, width, height }
92
+
93
+ // Constrain position
94
+ shape.minX = 0;
95
+ shape.maxX = 800;
96
+ shape.applyConstraints();
97
+ ```
98
+
99
+ ### 3. Traceable
100
+
101
+ **Source:** `src/shapes/traceable.js`
102
+
103
+ Adds debug visualization capabilities.
104
+
105
+ ```js
106
+ shape.drawDebug(ctx); // Draw bounding box and center point
107
+ ```
108
+
109
+ ### 4. Renderable
110
+
111
+ **Source:** `src/shapes/renderable.js`
112
+
113
+ Adds visual properties and the main `render()` lifecycle.
114
+
115
+ ```js
116
+ shape.visible = true;
117
+ shape.opacity = 0.8;
118
+ shape.shadowColor = 'rgba(0,0,0,0.5)';
119
+ shape.shadowBlur = 10;
120
+ shape.shadowOffsetX = 5;
121
+ shape.shadowOffsetY = 5;
122
+ ```
123
+
124
+ **The `render()` method:**
125
+
126
+ ```js
127
+ render() {
128
+ if (!this.visible || this.opacity <= 0) return;
129
+
130
+ Painter.save();
131
+ Painter.effects.setBlendMode(this.blendMode);
132
+ Painter.opacity.pushOpacity(this.opacity);
133
+ Painter.translateTo(this.x, this.y);
134
+
135
+ // Apply shadows
136
+ if (this.shadowColor) {
137
+ ctx.shadowColor = this.shadowColor;
138
+ ctx.shadowBlur = this.shadowBlur;
139
+ ctx.shadowOffsetX = this.shadowOffsetX;
140
+ ctx.shadowOffsetY = this.shadowOffsetY;
141
+ }
142
+
143
+ this.draw(); // Call subclass implementation
144
+
145
+ Painter.opacity.popOpacity();
146
+ Painter.restore();
147
+ }
148
+ ```
149
+
150
+ ### 5. Transformable
151
+
152
+ **Source:** `src/shapes/transformable.js`
153
+
154
+ Adds rotation and scaling.
155
+
156
+ ```js
157
+ shape.rotation = Math.PI / 4; // 45 degrees
158
+ shape.scaleX = 2.0;
159
+ shape.scaleY = 0.5;
160
+ ```
161
+
162
+ **Transform application:**
163
+
164
+ ```js
165
+ applyTransforms() {
166
+ if (this.rotation !== 0) {
167
+ Painter.rotate(this.rotation);
168
+ }
169
+ if (this.scaleX !== 1 || this.scaleY !== 1) {
170
+ Painter.scale(this.scaleX, this.scaleY);
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### 6. Shape
176
+
177
+ **Source:** `src/shapes/shape.js`
178
+
179
+ Adds canvas styling (fill and stroke).
180
+
181
+ ```js
182
+ const circle = new Circle(50, {
183
+ color: 'red', // Fill color
184
+ stroke: 'black', // Stroke color
185
+ lineWidth: 2, // Stroke width
186
+ lineJoin: 'round', // Line join style
187
+ lineCap: 'round' // Line cap style
188
+ });
189
+ ```
190
+
191
+ ## The Render Flow
192
+
193
+ When `shape.render()` is called (or `shape.draw()` directly):
194
+
195
+ ```
196
+ 1. render() called
197
+
198
+ ├─► Check visible && opacity > 0
199
+
200
+ ├─► Painter.save() ─── Save canvas state
201
+
202
+ ├─► Set blend mode
203
+
204
+ ├─► Push opacity
205
+
206
+ ├─► Translate to (x, y) ─── Move to shape center
207
+
208
+ ├─► Apply shadows
209
+
210
+ ├─► draw() called ─── Subclass implementation
211
+ │ │
212
+ │ ├─► applyTransforms() ─── Rotation & scale
213
+ │ │
214
+ │ └─► Painter.shapes.* ─── Actual drawing
215
+
216
+ ├─► Pop opacity
217
+
218
+ └─► Painter.restore() ─── Restore canvas state
219
+ ```
220
+
221
+ ## Coordinate System
222
+
223
+ GCanvas uses a **center-based** coordinate system:
224
+
225
+ ```
226
+ ┌────────────────────────────────────┐
227
+ │ Canvas │
228
+ │ │
229
+ │ (0,0) top-left │
230
+ │ ┌──────────────────┐ │
231
+ │ │ │ │
232
+ │ │ (x, y) │ │
233
+ │ │ ●──────────┼─width │
234
+ │ │ │ │ │
235
+ │ │ │ │ │
236
+ │ └───────┼──────────┘ │
237
+ │ height │
238
+ │ │
239
+ └────────────────────────────────────┘
240
+ ```
241
+
242
+ The `(x, y)` point is the **center** of the shape, not the top-left corner.
243
+
244
+ ## Creating Custom Shapes
245
+
246
+ Extend `Shape` and implement `draw()`:
247
+
248
+ ```js
249
+ import { Shape, Painter } from 'gcanvas';
250
+
251
+ class CustomShape extends Shape {
252
+ constructor(options = {}) {
253
+ super(options);
254
+ this.customProp = options.customProp ?? 'default';
255
+ }
256
+
257
+ draw() {
258
+ super.draw(); // Apply transforms
259
+
260
+ // Draw using Painter
261
+ Painter.shapes.fillCircle(0, 0, this.width / 2, this.color);
262
+ Painter.shapes.strokeCircle(0, 0, this.width / 2, this.stroke, this.lineWidth);
263
+ }
264
+ }
265
+ ```
266
+
267
+ ## Related
268
+
269
+ - [Architecture Overview](./architecture-overview.md) - Full system architecture
270
+ - [Two-Layer Architecture](./two-layer-architecture.md) - Shape vs Game layer
271
+ - [Shape Hierarchy](../modules/shapes/hierarchy.md) - Detailed class documentation
272
+
273
+ ## See Also
274
+
275
+ - [Euclidian](../modules/shapes/base/euclidian.md)
276
+ - [Geometry2d](../modules/shapes/base/geometry2d.md)
277
+ - [Renderable](../modules/shapes/base/renderable.md)
278
+ - [Transformable](../modules/shapes/base/transformable.md)
279
+ - [Shape](../modules/shapes/base/shape.md)
@@ -0,0 +1,106 @@
1
+ # TDE Demo Z-Order Rendering System
2
+
3
+ This document describes the z-ordering (depth sorting) system used in the Tidal Disruption Event (TDE) demo.
4
+
5
+ ## Overview
6
+
7
+ The TDE demo uses a 3D scene with multiple objects that need to be rendered in the correct order based on their depth relative to the camera. The system uses a combination of:
8
+
9
+ 1. **Static z-index buckets** for objects that always render in a fixed order
10
+ 2. **Dynamic z-index updates** for objects whose render order depends on camera position
11
+
12
+ ## Z-Index Buckets
13
+
14
+ Objects are assigned to z-index buckets. Lower z-index values render first (behind), higher values render later (in front).
15
+
16
+ **Only the Star has a dynamic z-index** that changes based on its position relative to the camera. The TidalStream particles always render on top for a cleaner visual effect.
17
+
18
+ | Object | Z-Index | Description |
19
+ |--------|---------|-------------|
20
+ | Star (back) | 10 | Star when behind black hole |
21
+ | BlackHole | 15 | Dark shadow - at the back |
22
+ | AccretionDisk | 20 | Disk renders over the black hole |
23
+ | Star (front) | 25 | Star when in front of black hole |
24
+ | TidalStream | 30 | Particles - always on top |
25
+ | RelativisticJets | 40 | Jets - always on top |
26
+
27
+ ### Layering by Camera View
28
+
29
+ **When star is IN FRONT of black hole:**
30
+ - Stream (30) > Star (25) > Disk (20) > BlackHole (15)
31
+
32
+ **When star is BEHIND black hole:**
33
+ - Stream (30) > Disk (20) > BlackHole (15) > Star (10)
34
+
35
+ The accretion disk particles curve around the black hole visually, and the stream always stays on top.
36
+
37
+ ## Rendering Rules
38
+
39
+ ### Rule 1: TidalStream Always Behind Star
40
+ The tidal stream particles (z-index 10) always render behind the star (z-index 25-35). This ensures the star is always visible and the stream appears to emanate from behind/around it.
41
+
42
+ ### Rule 2: Star in Front of Black Hole (When Closer)
43
+ When the star is closer to the camera than the black hole, the star's z-index is set to 35 (starFront), which is higher than the black hole's z-index of 30. This causes the star to render after (on top of) the black hole.
44
+
45
+ ### Rule 3: Black Hole in Front of Star (When Star is Behind)
46
+ When the star is farther from the camera than the black hole, the star's z-index is set to 25 (starBack), which is lower than the black hole's z-index of 30. This causes the black hole to render after (on top of) the star.
47
+
48
+ ## Dynamic Z-Order Algorithm
49
+
50
+ The `BlackHoleScene.updateStarZOrder()` method handles dynamic z-ordering:
51
+
52
+ ```javascript
53
+ updateStarZOrder() {
54
+ const camera = this.game.camera;
55
+
56
+ // Project star position to get depth after camera rotation
57
+ const projStar = camera.project(star.x, star.y, star.z);
58
+
59
+ // Black hole is always at origin
60
+ const projBH = camera.project(0, 0, 0);
61
+
62
+ // Lower projected z = closer to camera
63
+ const starInFront = projStar.z < projBH.z;
64
+
65
+ // Update z-index based on depth comparison
66
+ star.zIndex = starInFront ? Z.starFront : Z.starBack;
67
+ }
68
+ ```
69
+
70
+ ### Critical: Update Order
71
+
72
+ The z-order update **must be called AFTER** the star position is updated each frame. This is done in `TDEDemo.update()` at the end, after all state-based position updates:
73
+
74
+ ```javascript
75
+ // In TDEDemo.update(), at the end:
76
+ if (this.scene) {
77
+ this.scene.updateStarZOrder();
78
+ }
79
+ ```
80
+
81
+ If called before the position update, it uses stale position data and causes incorrect ordering.
82
+
83
+ ## Camera3D Projection
84
+
85
+ The `Camera3D.project()` method returns:
86
+ - `x, y`: Screen position
87
+ - `z`: Depth after rotation (lower = closer to camera)
88
+ - `scale`: Perspective scale factor
89
+
90
+ The depth (`z`) value is used for z-order comparisons. Objects with lower depth values are closer to the camera and should render on top.
91
+
92
+ ## Scene3D Sorting
93
+
94
+ `Scene3D` sorts children before rendering:
95
+
96
+ 1. **Primary sort**: By `zIndex` (lower renders first)
97
+ 2. **Secondary sort**: By projected `z` depth (back-to-front, as tie-breaker)
98
+
99
+ This ensures objects with different z-indices render in the correct order, while objects with the same z-index are sorted by actual depth.
100
+
101
+ ## Implementation Files
102
+
103
+ - `demos/js/tde/blackholescene.js` - Main scene with z-ordering logic
104
+ - `src/game/objects/scene3d.js` - Base Scene3D with depth sorting
105
+ - `src/util/camera3d.js` - Camera projection utilities
106
+
@@ -0,0 +1,229 @@
1
+ # Two-Layer Architecture
2
+
3
+ > Understanding when to use the Shape Layer vs the Game Layer.
4
+
5
+ ## Overview
6
+
7
+ GCanvas provides two complementary approaches to building canvas applications:
8
+
9
+ 1. **Shape Layer** - For declarative, static graphics
10
+ 2. **Game Layer** - For interactive, dynamic applications
11
+
12
+ You can use either layer independently or combine them for complex applications.
13
+
14
+ ## Shape Layer
15
+
16
+ The Shape Layer is for drawing graphics without a game loop. Shapes are self-contained objects that know how to render themselves.
17
+
18
+ ### When to Use
19
+
20
+ - Static visualizations
21
+ - Data charts and graphs
22
+ - Decorative graphics
23
+ - Simple animations (manual redraw)
24
+ - Learning canvas fundamentals
25
+
26
+ ### Key Classes
27
+
28
+ - `Shape` and subclasses (`Circle`, `Rectangle`, `Star`, etc.)
29
+ - `Group` for composing shapes
30
+ - `Painter` for direct canvas control
31
+
32
+ ### Example
33
+
34
+ ```js
35
+ import { Circle, Rectangle, Group, Painter } from 'gcanvas';
36
+
37
+ // Initialize Painter with canvas context
38
+ const canvas = document.getElementById('canvas');
39
+ Painter.init(canvas.getContext('2d'));
40
+
41
+ // Create shapes
42
+ const circle = new Circle(50, { x: 100, y: 100, color: 'red' });
43
+ const rect = new Rectangle(80, 40, { x: 200, y: 100, color: 'blue' });
44
+
45
+ // Draw immediately
46
+ Painter.clear();
47
+ circle.draw();
48
+ rect.draw();
49
+ ```
50
+
51
+ ### Characteristics
52
+
53
+ | Aspect | Shape Layer |
54
+ |--------|-------------|
55
+ | Loop | None (manual redraw) |
56
+ | State | Shapes hold their own state |
57
+ | Input | Manual event handling |
58
+ | Animation | Call draw() on each frame manually |
59
+ | Complexity | Simple, direct |
60
+
61
+ ## Game Layer
62
+
63
+ The Game Layer provides a complete game loop with automatic updates, rendering, and input handling.
64
+
65
+ ### When to Use
66
+
67
+ - Games and simulations
68
+ - Interactive applications
69
+ - Real-time animations
70
+ - Complex state management
71
+ - Multi-object coordination
72
+
73
+ ### Key Classes
74
+
75
+ - `Game` - Main loop and canvas management
76
+ - `Pipeline` - Object lifecycle management
77
+ - `GameObject` - Interactive entities
78
+ - `Scene` - Hierarchical organization
79
+
80
+ ### Example
81
+
82
+ ```js
83
+ import { Game, Scene, GameObject, Circle } from 'gcanvas';
84
+
85
+ class Player extends GameObject {
86
+ constructor(game) {
87
+ super(game);
88
+ this.shape = new Circle(40, { color: 'blue' });
89
+ this.enableInteractivity(this.shape);
90
+ }
91
+
92
+ update(dt) {
93
+ // Called every frame
94
+ if (this.game.input.isKeyDown('ArrowRight')) {
95
+ this.shape.x += 200 * dt;
96
+ }
97
+ }
98
+
99
+ render() {
100
+ // Called every frame after update
101
+ this.shape.draw();
102
+ }
103
+
104
+ onPointerDown(e) {
105
+ // Automatic input handling
106
+ console.log('Clicked!');
107
+ }
108
+ }
109
+
110
+ class MyGame extends Game {
111
+ init() {
112
+ this.enableFluidSize();
113
+ const scene = new Scene(this);
114
+ scene.add(new Player(this));
115
+ this.pipeline.add(scene);
116
+ }
117
+ }
118
+
119
+ const game = new MyGame(document.getElementById('canvas'));
120
+ game.start();
121
+ ```
122
+
123
+ ### Characteristics
124
+
125
+ | Aspect | Game Layer |
126
+ |--------|-------------|
127
+ | Loop | Automatic (requestAnimationFrame) |
128
+ | State | Managed by Pipeline |
129
+ | Input | Automatic dispatching to objects |
130
+ | Animation | Built-in with dt (delta time) |
131
+ | Complexity | Full-featured |
132
+
133
+ ## Comparison
134
+
135
+ ```
136
+ ┌─────────────────────────────────────────────────────────────┐
137
+ │ Shape Layer │
138
+ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
139
+ │ │ Circle │ │Rectangle│ │ Star │ ... more shapes │
140
+ │ └────┬────┘ └────┬────┘ └────┬────┘ │
141
+ │ │ │ │ │
142
+ │ └────────────┼────────────┘ │
143
+ │ ▼ │
144
+ │ ┌──────────┐ │
145
+ │ │ Group │ (optional composition) │
146
+ │ └────┬─────┘ │
147
+ │ │ │
148
+ │ ▼ │
149
+ │ ┌──────────┐ │
150
+ │ │ draw() │ (manual call) │
151
+ │ └──────────┘ │
152
+ └─────────────────────────────────────────────────────────────┘
153
+
154
+ ┌─────────────────────────────────────────────────────────────┐
155
+ │ Game Layer │
156
+ │ ┌─────────────────────────────────────────────────────┐ │
157
+ │ │ Game │ │
158
+ │ │ ┌─────────────────────────────────────────────┐ │ │
159
+ │ │ │ Pipeline │ │ │
160
+ │ │ │ ┌─────────────────────────────────────┐ │ │ │
161
+ │ │ │ │ Scene │ │ │ │
162
+ │ │ │ │ ┌───────────┐ ┌───────────┐ │ │ │ │
163
+ │ │ │ │ │GameObject │ │GameObject │ ... │ │ │ │
164
+ │ │ │ │ │ + Shape │ │ + Shape │ │ │ │ │
165
+ │ │ │ │ └───────────┘ └───────────┘ │ │ │ │
166
+ │ │ │ └─────────────────────────────────────┘ │ │ │
167
+ │ │ └─────────────────────────────────────────────┘ │ │
168
+ │ └─────────────────────────────────────────────────────┘ │
169
+ │ │ │
170
+ │ ▼ │
171
+ │ ┌────────────┐ │
172
+ │ │ Game Loop │ (automatic) │
173
+ │ │ update(dt) │ │
174
+ │ │ render() │ │
175
+ │ └────────────┘ │
176
+ └─────────────────────────────────────────────────────────────┘
177
+ ```
178
+
179
+ ## Mixing Layers
180
+
181
+ You can use shapes without GameObjects, or combine both approaches:
182
+
183
+ ```js
184
+ class HybridGame extends Game {
185
+ init() {
186
+ // Game layer for interactive elements
187
+ const scene = new Scene(this);
188
+ scene.add(new Player(this));
189
+ this.pipeline.add(scene);
190
+
191
+ // Shape layer for static background
192
+ this.background = new Group();
193
+ this.background.add(new Rectangle(this.width, this.height, { color: '#222' }));
194
+ }
195
+
196
+ render() {
197
+ // Draw static shapes first
198
+ this.background.draw();
199
+
200
+ // Then let pipeline draw interactive objects
201
+ super.render();
202
+ }
203
+ }
204
+ ```
205
+
206
+ ## Decision Guide
207
+
208
+ | If you need... | Use |
209
+ |---------------|-----|
210
+ | Static graphics | Shape Layer |
211
+ | Simple animations | Shape Layer + manual loop |
212
+ | Keyboard/mouse input | Game Layer |
213
+ | Multiple interactive objects | Game Layer |
214
+ | Collision detection | Game Layer |
215
+ | Scene organization | Game Layer |
216
+ | Quick prototype | Shape Layer |
217
+ | Full game | Game Layer |
218
+
219
+ ## Related
220
+
221
+ - [Architecture Overview](./architecture-overview.md) - Full system architecture
222
+ - [Rendering Pipeline](./rendering-pipeline.md) - Shape inheritance chain
223
+ - [Game Lifecycle](./lifecycle.md) - Update/render cycle
224
+
225
+ ## See Also
226
+
227
+ - [Shapes Module](../modules/shapes/README.md)
228
+ - [Game Module](../modules/game/README.md)
229
+ - [Getting Started: Hello World](../getting-started/hello-world.md)