@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,395 @@
1
+ # Scene3D
2
+
3
+ > A Scene that automatically projects children through Camera3D for pseudo-3D effects.
4
+
5
+ ## Overview
6
+
7
+ Scene3D bridges the GameObject/Scene system with Camera3D. It allows you to position GameObjects in 3D space (x, y, z) and automatically projects them through the camera for rendering.
8
+
9
+ **Key Features:**
10
+ - Extends the standard Scene class
11
+ - Projects children through Camera3D automatically
12
+ - Supports z-coordinate on any GameObject
13
+ - Depth sorting (back-to-front rendering)
14
+ - Perspective scaling based on depth
15
+
16
+ ## Quick Start
17
+
18
+ ```js
19
+ import { Game, Camera3D, Scene3D, GameObject, Rectangle } from 'gcanvas';
20
+
21
+ class BoxObject extends GameObject {
22
+ constructor(game) {
23
+ super(game);
24
+ this.z = 0; // Add z coordinate
25
+ this.shape = new Rectangle({
26
+ width: 60,
27
+ height: 60,
28
+ color: '#4a9eff',
29
+ stroke: '#fff',
30
+ });
31
+ }
32
+
33
+ draw() {
34
+ this.shape.draw();
35
+ }
36
+ }
37
+
38
+ class My3DDemo extends Game {
39
+ init() {
40
+ super.init();
41
+
42
+ // Create camera
43
+ this.camera = new Camera3D({
44
+ rotationX: 0.3,
45
+ perspective: 800,
46
+ });
47
+ this.camera.enableMouseControl(this.canvas);
48
+
49
+ // Create 3D scene (centered on screen)
50
+ this.scene3d = new Scene3D(this, {
51
+ x: this.width / 2,
52
+ y: this.height / 2,
53
+ camera: this.camera,
54
+ depthSort: true,
55
+ });
56
+
57
+ // Add objects with different z positions
58
+ const front = new BoxObject(this);
59
+ front.x = -80;
60
+ front.z = 100; // In front
61
+
62
+ const middle = new BoxObject(this);
63
+ middle.x = 0;
64
+ middle.z = 0; // Center
65
+
66
+ const back = new BoxObject(this);
67
+ back.x = 80;
68
+ back.z = -100; // Behind
69
+
70
+ this.scene3d.add(front);
71
+ this.scene3d.add(middle);
72
+ this.scene3d.add(back);
73
+
74
+ this.pipeline.add(this.scene3d);
75
+ }
76
+
77
+ update(dt) {
78
+ super.update(dt);
79
+ this.camera.update(dt);
80
+ }
81
+ }
82
+ ```
83
+
84
+ ## Constructor Options
85
+
86
+ ```js
87
+ const scene3d = new Scene3D(game, {
88
+ // Position (screen coordinates where scene is centered)
89
+ x: game.width / 2,
90
+ y: game.height / 2,
91
+
92
+ // Required: Camera for projection
93
+ camera: myCamera,
94
+
95
+ // Optional settings
96
+ depthSort: true, // Sort children by depth (back-to-front)
97
+ scaleByDepth: true, // Scale children based on perspective
98
+ });
99
+ ```
100
+
101
+ | Option | Type | Default | Description |
102
+ |--------|------|---------|-------------|
103
+ | `camera` | `Camera3D` | **required** | Camera for 3D projection |
104
+ | `depthSort` | `boolean` | `true` | Sort children back-to-front |
105
+ | `scaleByDepth` | `boolean` | `true` | Apply perspective scaling |
106
+ | `x`, `y` | `number` | `0` | Scene position (typically screen center) |
107
+
108
+ ---
109
+
110
+ ## Adding Objects
111
+
112
+ Scene3D works with any GameObject. Just add a `z` property:
113
+
114
+ ```js
115
+ // Standard GameObject
116
+ class MyObject extends GameObject {
117
+ constructor(game) {
118
+ super(game);
119
+ this.z = 0; // Initialize z coordinate
120
+ }
121
+ }
122
+
123
+ // Add to scene
124
+ const obj = new MyObject(this);
125
+ obj.x = 100; // Horizontal position
126
+ obj.y = 50; // Vertical position
127
+ obj.z = -200; // Depth (negative = behind, positive = in front)
128
+ scene3d.add(obj);
129
+ ```
130
+
131
+ If an object doesn't have a `z` property, it defaults to `0` (center plane).
132
+
133
+ ---
134
+
135
+ ## Depth Sorting
136
+
137
+ When `depthSort: true`, Scene3D renders objects from back to front, ensuring correct overlap:
138
+
139
+ ```js
140
+ // Objects overlap correctly
141
+ const scene3d = new Scene3D(this, {
142
+ camera: this.camera,
143
+ depthSort: true, // Enable depth sorting
144
+ });
145
+
146
+ // Back object won't obscure front object
147
+ backObj.z = -100; // Behind
148
+ frontObj.z = 100; // In front
149
+ ```
150
+
151
+ Disable for performance if objects don't overlap:
152
+
153
+ ```js
154
+ // All objects at same z - no need to sort
155
+ const scene3d = new Scene3D(this, {
156
+ camera: this.camera,
157
+ depthSort: false,
158
+ });
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Perspective Scaling
164
+
165
+ When `scaleByDepth: true`, objects scale based on their distance from the camera:
166
+
167
+ ```js
168
+ // Objects shrink as they move away
169
+ const scene3d = new Scene3D(this, {
170
+ camera: this.camera,
171
+ scaleByDepth: true, // Enable perspective scaling
172
+ });
173
+
174
+ nearObj.z = 200; // Appears larger
175
+ farObj.z = -300; // Appears smaller
176
+ ```
177
+
178
+ Disable for flat rendering (no size change with depth):
179
+
180
+ ```js
181
+ // All objects same size regardless of z
182
+ const scene3d = new Scene3D(this, {
183
+ camera: this.camera,
184
+ scaleByDepth: false,
185
+ });
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Common Patterns
191
+
192
+ ### Responsive Centering
193
+
194
+ Keep Scene3D centered when window resizes:
195
+
196
+ ```js
197
+ class MyDemo extends Game {
198
+ init() {
199
+ super.init();
200
+ this.enableFluidSize();
201
+
202
+ this.scene3d = new Scene3D(this, {
203
+ x: this.width / 2,
204
+ y: this.height / 2,
205
+ camera: this.camera,
206
+ });
207
+ }
208
+
209
+ update(dt) {
210
+ super.update(dt);
211
+
212
+ // Keep centered on resize
213
+ this.scene3d.x = this.width / 2;
214
+ this.scene3d.y = this.height / 2;
215
+ }
216
+ }
217
+ ```
218
+
219
+ ### Grid of Objects
220
+
221
+ Create a 3D grid layout:
222
+
223
+ ```js
224
+ const spacing = 80;
225
+ const gridSize = 5;
226
+
227
+ for (let x = 0; x < gridSize; x++) {
228
+ for (let z = 0; z < gridSize; z++) {
229
+ const obj = new GridCell(this);
230
+ obj.x = (x - gridSize / 2) * spacing;
231
+ obj.y = 0;
232
+ obj.z = (z - gridSize / 2) * spacing;
233
+ this.scene3d.add(obj);
234
+ }
235
+ }
236
+ ```
237
+
238
+ ### Orbiting Objects
239
+
240
+ Animate z-coordinates for 3D motion:
241
+
242
+ ```js
243
+ class OrbitingObject extends GameObject {
244
+ constructor(game, angle, radius) {
245
+ super(game);
246
+ this.angle = angle;
247
+ this.radius = radius;
248
+ this.z = 0;
249
+ }
250
+
251
+ update(dt) {
252
+ this.angle += dt;
253
+ this.x = Math.cos(this.angle) * this.radius;
254
+ this.z = Math.sin(this.angle) * this.radius;
255
+ }
256
+ }
257
+ ```
258
+
259
+ ### Multiple Layers
260
+
261
+ Use multiple Scene3D instances for layered effects:
262
+
263
+ ```js
264
+ // Background layer (far away, slow parallax)
265
+ this.bgScene = new Scene3D(this, {
266
+ x: cx, y: cy,
267
+ camera: this.camera,
268
+ });
269
+
270
+ // Main layer
271
+ this.mainScene = new Scene3D(this, {
272
+ x: cx, y: cy,
273
+ camera: this.camera,
274
+ });
275
+
276
+ // Foreground layer (close, fast parallax)
277
+ this.fgScene = new Scene3D(this, {
278
+ x: cx, y: cy,
279
+ camera: this.camera,
280
+ });
281
+
282
+ // Add to pipeline in order
283
+ this.pipeline.add(this.bgScene);
284
+ this.pipeline.add(this.mainScene);
285
+ this.pipeline.add(this.fgScene);
286
+ ```
287
+
288
+ ---
289
+
290
+ ## With ParticleSystem
291
+
292
+ Scene3D and ParticleSystem both use Camera3D independently. Add them to the same pipeline:
293
+
294
+ ```js
295
+ class EffectsDemo extends Game {
296
+ init() {
297
+ super.init();
298
+
299
+ this.camera = new Camera3D({ rotationX: 0.3 });
300
+ this.camera.enableMouseControl(this.canvas);
301
+
302
+ // 3D scene for objects
303
+ this.scene3d = new Scene3D(this, {
304
+ x: this.width / 2,
305
+ y: this.height / 2,
306
+ camera: this.camera,
307
+ });
308
+
309
+ // Particle system with same camera
310
+ this.particles = new ParticleSystem(this, {
311
+ camera: this.camera,
312
+ depthSort: true,
313
+ });
314
+
315
+ // Both in pipeline
316
+ this.pipeline.add(this.scene3d);
317
+ this.pipeline.add(this.particles);
318
+ }
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ ## How It Works
325
+
326
+ Scene3D overrides the Scene's `draw()` method to:
327
+
328
+ 1. **Build render list** - Collect visible children with their 3D positions
329
+ 2. **Project through camera** - Convert 3D (x, y, z) to 2D screen coordinates
330
+ 3. **Cull behind camera** - Skip objects behind the camera plane
331
+ 4. **Sort by depth** - Order back-to-front (if enabled)
332
+ 5. **Render with scaling** - Draw each child at projected position with perspective scale
333
+
334
+ ```
335
+ Child Object (x, y, z)
336
+ │
337
+ â–¼
338
+ Camera3D.project()
339
+ │
340
+ â–¼
341
+ Screen Position (x, y, scale)
342
+ │
343
+ â–¼
344
+ Painter.translateTo() + scale()
345
+ │
346
+ â–¼
347
+ child.draw()
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Differences from Scene
353
+
354
+ | Feature | Scene | Scene3D |
355
+ |---------|-------|---------|
356
+ | Coordinate system | 2D (x, y) | 3D (x, y, z) |
357
+ | Projection | None | Camera3D |
358
+ | Depth sorting | By zIndex | By projected z |
359
+ | Perspective scaling | No | Yes (optional) |
360
+ | Camera required | No | Yes |
361
+
362
+ ---
363
+
364
+ ## API Reference
365
+
366
+ ### Properties
367
+
368
+ | Property | Type | Description |
369
+ |----------|------|-------------|
370
+ | `camera` | `Camera3D` | Camera used for projection |
371
+ | `depthSort` | `boolean` | Whether to sort by depth |
372
+ | `scaleByDepth` | `boolean` | Whether to scale by perspective |
373
+ | `children` | `Array` | Child GameObjects (inherited) |
374
+
375
+ ### Methods
376
+
377
+ Inherits all methods from Scene:
378
+
379
+ | Method | Description |
380
+ |--------|-------------|
381
+ | `add(child)` | Add a GameObject |
382
+ | `remove(child)` | Remove a GameObject |
383
+ | `clear()` | Remove all children |
384
+
385
+ ---
386
+
387
+ ## Related
388
+
389
+ - [Camera3D](./camera3d.md) - Camera projection and controls
390
+ - [Game Module](../game/README.md) - Scene base class
391
+
392
+ ## See Also
393
+
394
+ - [Particle Module](../particle/README.md) - 3D particle effects
395
+ - [Shapes Module](../shapes/README.md) - Shape primitives
package/index.html ADDED
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <title>GCanvas Demos</title>
7
+ </head>
8
+
9
+ <body>
10
+ <div id="info">
11
+ <h1>🧪 GCanvas Demo Gallery</h1>
12
+ <p>Explore demos powered by the GCanvas engine:</p>
13
+ <a href="demos/index.html">Go to demos</a>
14
+ </div>
15
+ </body>
16
+
17
+ </html>
package/jsdoc.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "tags": {
3
+ "allowUnknownTags": ["category"]
4
+ },
5
+ "source": {
6
+ "include": ["./src"],
7
+ "includePattern": ".js$",
8
+ "excludePattern": "(node_modules/|docs)"
9
+ },
10
+ "plugins": [
11
+ "./node_modules/better-docs/category"
12
+ ],
13
+ "opts": {
14
+ "encoding": "utf8",
15
+ "destination": "docs-gen",
16
+ "readme": "readme.md",
17
+ "recurse": true,
18
+ "verbose": true,
19
+ "tutorials": "",
20
+ "template": "./node_modules/better-docs"
21
+ },
22
+ "templates": {
23
+ "cleverLinks": false,
24
+ "monospaceLinks": false,
25
+ "search": true,
26
+ "default": {
27
+ "staticFiles": {
28
+ "include": [""]
29
+ }
30
+ },
31
+ "better-docs": {
32
+ "name": "GCanvas",
33
+ "logo": "images/logo.png",
34
+ "title": "GCanvas",
35
+ "css": "style.css",
36
+ "trackingCode": "",
37
+ "hideGenerator": false,
38
+ "navLinks": [
39
+ {
40
+ "label": "Github",
41
+ "href": "https://github.com/guinetik/gcanvas"
42
+ },
43
+ {
44
+ "label": "Tech Demo",
45
+ "href": "https://gcanvas.guinetik.com"
46
+ }
47
+ ]
48
+ }
49
+ }
50
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@guinetik/gcanvas",
3
+ "version": "1.0.0",
4
+ "description": "Canvas Utilities and 2d Primitives",
5
+ "main": "index.js",
6
+ "types": "types/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "dev": "vite",
10
+ "build": "vite build && npm run minify",
11
+ "build:debug": "vite build --mode debug",
12
+ "build:llm": "npx bundle4llm --src=./src --out=./llm-docs --file=gcanvas-4-llm.js -v",
13
+ "build:demo": "node scripts/build-demo.js",
14
+ "clean:logs": "node scripts/clearconsole.js ./src",
15
+ "minify": "terser dist/gcanvas.umd.js -o dist/gcanvas.umd.min.js --compress --mangle && terser dist/gcanvas.es.js -o dist/gcanvas.es.min.js --compress --mangle",
16
+ "preview": "vite preview",
17
+ "docs": "jsdoc -c jsdoc.json --verbose",
18
+ "deploy:demo": "gh-pages --dist public --branch gh-pages",
19
+ "test": "vitest --no-watch",
20
+ "test:watch": "vitest watch",
21
+ "test:coverage": "vitest run --coverage"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/guinetik/gcanvas.git"
26
+ },
27
+ "keywords": [
28
+ "canvas",
29
+ "html5",
30
+ "no-dependencies"
31
+ ],
32
+ "author": "guinetik",
33
+ "license": "ISC",
34
+ "exports": {
35
+ ".": {
36
+ "import": "./dist/gcanvas.es.js",
37
+ "require": "./dist/gcanvas.umd.js"
38
+ }
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/guinetik/gcanvas/issues"
42
+ },
43
+ "homepage": "https://github.com/guinetik/gcanvas#readme",
44
+ "devDependencies": {
45
+ "@testing-library/jest-dom": "^6.6.3",
46
+ "gh-pages": "^6.3.0",
47
+ "jsdom": "^26.1.0",
48
+ "terser": "^5.39.0",
49
+ "vite": "^6.2.5",
50
+ "vitest": "^3.1.1"
51
+ },
52
+ "optionalDependencies": {
53
+ "@rollup/rollup-linux-x64-gnu": "^4.53.3"
54
+ }
55
+ }