@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,215 @@
1
+ # Renderable
2
+
3
+ > Visibility, opacity, shadows, and the render lifecycle.
4
+
5
+ **Module:** [shapes](../README.md) | **Extends:** `Traceable` | **Source:** `src/shapes/renderable.js`
6
+
7
+ ## Overview
8
+
9
+ Renderable introduces the core rendering lifecycle. It knows when to draw, how to draw, and when **not** to draw (invisible, opacity = 0).
10
+
11
+ This class adds:
12
+ - **Rendering lifecycle control** (`render()`)
13
+ - **Canvas state management** (save/restore)
14
+ - **Visual properties** (opacity, visibility)
15
+ - **Shadow styling** support
16
+
17
+ ## Constructor
18
+
19
+ ```js
20
+ new Renderable(options)
21
+ ```
22
+
23
+ ### Options
24
+
25
+ | Option | Type | Default | Description |
26
+ |--------|------|---------|-------------|
27
+ | `visible` | `boolean` | `true` | Whether to draw this object |
28
+ | `opacity` | `number` | `1` | Alpha transparency (0–1) |
29
+ | `active` | `boolean` | `true` | Whether to receive updates |
30
+ | `zIndex` | `number` | `0` | Stacking order |
31
+ | `blendMode` | `string` | `"source-over"` | Canvas composite operation |
32
+ | `shadowColor` | `string` | `undefined` | Shadow color |
33
+ | `shadowBlur` | `number` | `0` | Shadow blur radius |
34
+ | `shadowOffsetX` | `number` | `0` | Shadow X offset |
35
+ | `shadowOffsetY` | `number` | `0` | Shadow Y offset |
36
+
37
+ Plus all options from [Geometry2d](./geometry2d.md).
38
+
39
+ ## Properties
40
+
41
+ ### Inherited
42
+
43
+ From Euclidian: `x`, `y`, `width`, `height`, `debug`, `debugColor`
44
+
45
+ From Geometry2d: `minX`, `maxX`, `minY`, `maxY`, `crisp`, `boundsDirty`
46
+
47
+ ### Own Properties
48
+
49
+ | Property | Type | Description |
50
+ |----------|------|-------------|
51
+ | `visible` | `boolean` | Show/hide the object |
52
+ | `opacity` | `number` | Transparency (0 = invisible, 1 = opaque) |
53
+ | `active` | `boolean` | Whether to call `update()` |
54
+ | `zIndex` | `number` | Stacking order (higher = on top) |
55
+ | `shadowColor` | `string \| undefined` | CSS color for shadow |
56
+ | `shadowBlur` | `number` | Shadow blur radius in pixels |
57
+ | `shadowOffsetX` | `number` | Horizontal shadow offset |
58
+ | `shadowOffsetY` | `number` | Vertical shadow offset |
59
+ | `tick` | `number` | Total time object has been alive (readonly) |
60
+
61
+ ## Methods
62
+
63
+ ### render()
64
+
65
+ Main rendering lifecycle method. Handles canvas state, applies effects, and calls `draw()`.
66
+
67
+ ```js
68
+ shape.render();
69
+ ```
70
+
71
+ **Render flow:**
72
+
73
+ ```
74
+ render()
75
+ ├── Check visible && opacity > 0
76
+ ├── Painter.save()
77
+ ├── Set blend mode
78
+ ├── Push opacity
79
+ ├── Translate to (x, y)
80
+ ├── Apply shadows
81
+ ├── draw() ← subclass implements this
82
+ ├── Pop opacity
83
+ └── Painter.restore()
84
+ ```
85
+
86
+ ### draw()
87
+
88
+ Called by `render()` to do actual drawing. Override in subclasses.
89
+
90
+ ```js
91
+ class MyShape extends Renderable {
92
+ draw() {
93
+ // Custom drawing logic
94
+ Painter.shapes.fillCircle(0, 0, 50, 'red');
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### update(dt)
100
+
101
+ Called once per frame if the object is active.
102
+
103
+ ```js
104
+ shape.update(0.016); // dt in seconds
105
+
106
+ // Override in subclasses
107
+ update(dt) {
108
+ this.x += 100 * dt; // Move 100 pixels per second
109
+ super.update(dt);
110
+ }
111
+ ```
112
+
113
+ **Parameters:**
114
+ - `dt` (`number`): Time since last frame in seconds
115
+
116
+ ### applyShadow(ctx)
117
+
118
+ Applies shadow styles to the canvas context.
119
+
120
+ ```js
121
+ shape.applyShadow(Painter.ctx);
122
+ ```
123
+
124
+ ## Visibility Control
125
+
126
+ ```js
127
+ // Hide the shape (won't render)
128
+ shape.visible = false;
129
+
130
+ // Show the shape
131
+ shape.visible = true;
132
+
133
+ // Make semi-transparent
134
+ shape.opacity = 0.5;
135
+
136
+ // Fully transparent (same as invisible)
137
+ shape.opacity = 0;
138
+ ```
139
+
140
+ ## Shadow Effects
141
+
142
+ ```js
143
+ const shape = new Circle(50, {
144
+ x: 200,
145
+ y: 200,
146
+ color: '#4ecdc4',
147
+ shadowColor: 'rgba(0,0,0,0.5)',
148
+ shadowBlur: 15,
149
+ shadowOffsetX: 5,
150
+ shadowOffsetY: 5
151
+ });
152
+ ```
153
+
154
+ ## Z-Index Ordering
155
+
156
+ Objects are rendered in z-index order (low to high):
157
+
158
+ ```js
159
+ const background = new Rectangle({ zIndex: 0 });
160
+ const player = new Circle({ zIndex: 10 });
161
+ const ui = new Rectangle({ zIndex: 100 });
162
+
163
+ // Render order: background → player → ui
164
+ ```
165
+
166
+ ## Active vs Visible
167
+
168
+ | Property | Effect |
169
+ |----------|--------|
170
+ | `visible = false` | Skips `render()`, still calls `update()` |
171
+ | `active = false` | Skips `update()`, still calls `render()` |
172
+ | Both `false` | Object is completely dormant |
173
+
174
+ ```js
175
+ // Pause updates but keep drawing
176
+ shape.active = false;
177
+
178
+ // Pause everything
179
+ shape.active = false;
180
+ shape.visible = false;
181
+ ```
182
+
183
+ ## Blend Modes
184
+
185
+ GCanvas supports standard canvas composite operations:
186
+
187
+ ```js
188
+ shape.blendMode = 'multiply';
189
+ shape.blendMode = 'screen';
190
+ shape.blendMode = 'overlay';
191
+ // etc.
192
+ ```
193
+
194
+ Common values: `source-over` (default), `multiply`, `screen`, `overlay`, `darken`, `lighten`
195
+
196
+ ## Inheritance
197
+
198
+ ```
199
+ Geometry2d
200
+ └── Traceable
201
+ └── Renderable <── You are here
202
+ └── Transformable
203
+ └── Shape
204
+ ```
205
+
206
+ ## Related
207
+
208
+ - [Geometry2d](./geometry2d.md) - Parent class
209
+ - [Transformable](./transformable.md) - Adds rotation/scale
210
+ - [Shape Hierarchy](../hierarchy.md) - Full inheritance diagram
211
+
212
+ ## See Also
213
+
214
+ - [Shapes Module](../README.md)
215
+ - [Game Lifecycle](../../../concepts/lifecycle.md) - Update/render cycle
@@ -0,0 +1,262 @@
1
+ # Shape
2
+
3
+ > Fill color, stroke, and line styling for drawable primitives.
4
+
5
+ **Module:** [shapes](../README.md) | **Extends:** [Transformable](./transformable.md) | **Source:** `src/shapes/shape.js`
6
+
7
+ ## Overview
8
+
9
+ Shape is the base class for all drawable geometric primitives. It's the first class in the hierarchy to express **canvas styling intent**:
10
+
11
+ - Fill & stroke colors
12
+ - Line width & join styles
13
+ - Line cap styles
14
+
15
+ Shape does not define geometry — that's up to subclasses like Circle, Rectangle, etc.
16
+
17
+ ## Constructor
18
+
19
+ ```js
20
+ new Shape(options)
21
+ ```
22
+
23
+ ### Options
24
+
25
+ | Option | Type | Default | Description |
26
+ |--------|------|---------|-------------|
27
+ | `color` | `string \| null` | `null` | Fill color (CSS color) |
28
+ | `stroke` | `string \| null` | `null` | Stroke color (CSS color) |
29
+ | `lineWidth` | `number` | `1` | Stroke width in pixels |
30
+ | `lineJoin` | `string` | `"miter"` | Line join style |
31
+ | `lineCap` | `string` | `"butt"` | Line cap style |
32
+ | `miterLimit` | `number` | `10` | Maximum miter length |
33
+
34
+ Plus all options from [Transformable](./transformable.md).
35
+
36
+ ## Properties
37
+
38
+ ### Inherited
39
+
40
+ From Euclidian: `x`, `y`, `width`, `height`, `debug`, `debugColor`
41
+
42
+ From Geometry2d: `minX`, `maxX`, `minY`, `maxY`, `crisp`
43
+
44
+ From Renderable: `visible`, `opacity`, `active`, `zIndex`, `shadowColor`, `shadowBlur`, `shadowOffsetX`, `shadowOffsetY`
45
+
46
+ From Transformable: `rotation`, `scaleX`, `scaleY`
47
+
48
+ ### Own Properties
49
+
50
+ | Property | Type | Description |
51
+ |----------|------|-------------|
52
+ | `color` | `string \| null` | Fill color (CSS color string) |
53
+ | `stroke` | `string \| null` | Stroke color (CSS color string) |
54
+ | `lineWidth` | `number` | Width of stroke in pixels |
55
+ | `lineJoin` | `"miter" \| "round" \| "bevel"` | Line join style |
56
+ | `lineCap` | `"butt" \| "round" \| "square"` | Line cap style |
57
+ | `miterLimit` | `number` | Maximum miter length before bevel |
58
+
59
+ ## Fill and Stroke
60
+
61
+ ```js
62
+ // Fill only
63
+ const filled = new Circle(50, {
64
+ color: 'red'
65
+ });
66
+
67
+ // Stroke only
68
+ const outlined = new Circle(50, {
69
+ stroke: 'blue',
70
+ lineWidth: 2
71
+ });
72
+
73
+ // Both fill and stroke
74
+ const both = new Circle(50, {
75
+ color: 'red',
76
+ stroke: 'black',
77
+ lineWidth: 2
78
+ });
79
+ ```
80
+
81
+ ## Color Formats
82
+
83
+ Any valid CSS color string:
84
+
85
+ ```js
86
+ shape.color = 'red'; // Named color
87
+ shape.color = '#ff0000'; // Hex
88
+ shape.color = '#f00'; // Short hex
89
+ shape.color = 'rgb(255, 0, 0)'; // RGB
90
+ shape.color = 'rgba(255, 0, 0, 0.5)'; // RGBA
91
+ shape.color = 'hsl(0, 100%, 50%)'; // HSL
92
+ ```
93
+
94
+ ## Line Join Styles
95
+
96
+ Controls how lines meet at corners:
97
+
98
+ ```js
99
+ shape.lineJoin = 'miter'; // Sharp corners (default)
100
+ shape.lineJoin = 'round'; // Rounded corners
101
+ shape.lineJoin = 'bevel'; // Beveled corners
102
+ ```
103
+
104
+ ```
105
+ miter round bevel
106
+ ╱ ╱ ╱
107
+ ╱ ╱ ╱
108
+ ──┼── ──╲── ──┘──
109
+ ╲ ╲ ╲
110
+ ╲ ╲ ╲
111
+ ```
112
+
113
+ ## Line Cap Styles
114
+
115
+ Controls how line endpoints look:
116
+
117
+ ```js
118
+ shape.lineCap = 'butt'; // Flat end at endpoint (default)
119
+ shape.lineCap = 'round'; // Rounded end
120
+ shape.lineCap = 'square'; // Square end extending past endpoint
121
+ ```
122
+
123
+ ```
124
+ butt round square
125
+ │ │ │
126
+ ───┤ ───● ───┤
127
+ │ │ │
128
+ ```
129
+
130
+ ## Miter Limit
131
+
132
+ When `lineJoin` is `"miter"`, very sharp angles can create very long miter points. `miterLimit` caps this:
133
+
134
+ ```js
135
+ shape.lineJoin = 'miter';
136
+ shape.miterLimit = 10; // Default, reasonable for most cases
137
+ shape.miterLimit = 2; // Shorter miters, more beveling
138
+ ```
139
+
140
+ ## Subclassing
141
+
142
+ Shape is abstract. Subclasses implement `draw()`:
143
+
144
+ ```js
145
+ import { Shape, Painter } from 'gcanvas';
146
+
147
+ class CustomShape extends Shape {
148
+ constructor(options = {}) {
149
+ super(options);
150
+ // Custom initialization
151
+ }
152
+
153
+ draw() {
154
+ super.draw(); // Apply transforms
155
+
156
+ // Use this.color, this.stroke, this.lineWidth, etc.
157
+ if (this.color) {
158
+ Painter.colors.fill(this.color);
159
+ // Custom fill drawing
160
+ }
161
+
162
+ if (this.stroke) {
163
+ Painter.colors.stroke(this.stroke, this.lineWidth);
164
+ // Custom stroke drawing
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ ## Concrete Shape Classes
171
+
172
+ These classes extend Shape:
173
+
174
+ | Class | Description |
175
+ |-------|-------------|
176
+ | `Circle` | Circle with radius |
177
+ | `Rectangle` | Centered rectangle |
178
+ | `Triangle` | Three-sided polygon |
179
+ | `Star` | Star with n points |
180
+ | `Polygon` | N-sided polygon |
181
+ | `Line` | Line segment |
182
+ | `Arc` | Curved arc |
183
+ | `Heart` | Heart shape |
184
+ | `Diamond` | Diamond/rhombus |
185
+ | ... | And many more |
186
+
187
+ ## Example
188
+
189
+ ```js
190
+ import { Rectangle, Painter } from 'gcanvas';
191
+
192
+ const rect = new Rectangle({
193
+ x: 200,
194
+ y: 150,
195
+ width: 100,
196
+ height: 60,
197
+ color: '#4ecdc4',
198
+ stroke: '#2a9d8f',
199
+ lineWidth: 3,
200
+ lineJoin: 'round'
201
+ });
202
+
203
+ rect.draw();
204
+ ```
205
+
206
+ ## Complete Property Example
207
+
208
+ ```js
209
+ const shape = new Circle(50, {
210
+ // Position (Euclidian)
211
+ x: 400,
212
+ y: 300,
213
+
214
+ // Constraints (Geometry2d)
215
+ minX: 50,
216
+ maxX: 750,
217
+
218
+ // Visibility (Renderable)
219
+ visible: true,
220
+ opacity: 0.9,
221
+ shadowColor: 'rgba(0,0,0,0.3)',
222
+ shadowBlur: 10,
223
+ shadowOffsetX: 5,
224
+ shadowOffsetY: 5,
225
+
226
+ // Transforms (Transformable)
227
+ rotation: 0,
228
+ scaleX: 1,
229
+ scaleY: 1,
230
+
231
+ // Styling (Shape)
232
+ color: '#ff6b6b',
233
+ stroke: '#c92a2a',
234
+ lineWidth: 2,
235
+ lineJoin: 'round',
236
+ lineCap: 'round'
237
+ });
238
+ ```
239
+
240
+ ## Inheritance
241
+
242
+ ```
243
+ Transformable
244
+ └── Shape <── You are here
245
+ ├── Circle
246
+ ├── Rectangle
247
+ ├── Triangle
248
+ ├── Star
249
+ ├── Polygon
250
+ └── ... (40+ shapes)
251
+ ```
252
+
253
+ ## Related
254
+
255
+ - [Transformable](./transformable.md) - Parent class
256
+ - [Shape Hierarchy](../hierarchy.md) - Full inheritance diagram
257
+ - [Shapes Module](../README.md) - All available shapes
258
+
259
+ ## See Also
260
+
261
+ - [Rendering Pipeline](../../../concepts/rendering-pipeline.md)
262
+ - [Hello World](../../../getting-started/hello-world.md)
@@ -0,0 +1,243 @@
1
+ # Transformable
2
+
3
+ > Rotation and scaling with transformed bounding boxes.
4
+
5
+ **Module:** [shapes](../README.md) | **Extends:** [Renderable](./renderable.md) | **Source:** `src/shapes/transformable.js`
6
+
7
+ ## Overview
8
+
9
+ Transformable adds canvas transformation support:
10
+ - **Rotation** in degrees
11
+ - **Scaling** (horizontal and vertical)
12
+ - **Transformed bounds** calculation
13
+
14
+ This is the final base layer before custom shape styling is introduced.
15
+
16
+ ## Constructor
17
+
18
+ ```js
19
+ new Transformable(options)
20
+ ```
21
+
22
+ ### Options
23
+
24
+ | Option | Type | Default | Description |
25
+ |--------|------|---------|-------------|
26
+ | `rotation` | `number` | `0` | Rotation in degrees (clockwise) |
27
+ | `scaleX` | `number` | `1` | Horizontal scale factor |
28
+ | `scaleY` | `number` | `1` | Vertical scale factor |
29
+
30
+ Plus all options from [Renderable](./renderable.md).
31
+
32
+ ## Properties
33
+
34
+ ### Inherited
35
+
36
+ From Euclidian: `x`, `y`, `width`, `height`, `debug`, `debugColor`
37
+
38
+ From Geometry2d: `minX`, `maxX`, `minY`, `maxY`, `crisp`, `boundsDirty`
39
+
40
+ From Renderable: `visible`, `opacity`, `active`, `zIndex`, `shadowColor`, `shadowBlur`, `shadowOffsetX`, `shadowOffsetY`, `tick`
41
+
42
+ ### Own Properties
43
+
44
+ | Property | Type | Description |
45
+ |----------|------|-------------|
46
+ | `rotation` | `number` | Rotation angle in degrees |
47
+ | `scaleX` | `number` | Horizontal scale (1 = normal) |
48
+ | `scaleY` | `number` | Vertical scale (1 = normal) |
49
+
50
+ ## Methods
51
+
52
+ ### draw()
53
+
54
+ Applies transforms before subclass drawing. Always call `super.draw()` in subclasses.
55
+
56
+ ```js
57
+ class MyShape extends Transformable {
58
+ draw() {
59
+ super.draw(); // Apply transforms
60
+ // Custom drawing (in transformed space)
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### applyTransforms()
66
+
67
+ Applies rotation and scale to the canvas context. Called by `draw()`.
68
+
69
+ ```js
70
+ applyTransforms() {
71
+ Painter.rotate(this._rotation);
72
+ Painter.scale(this._scaleX, this._scaleY);
73
+ }
74
+ ```
75
+
76
+ Transform order: **rotate → scale**
77
+
78
+ ### calculateBounds()
79
+
80
+ Returns the bounding box after applying rotation and scale.
81
+
82
+ ```js
83
+ const bounds = shape.getBounds();
84
+ // Returns axis-aligned bounding box of the rotated/scaled shape
85
+ ```
86
+
87
+ ## Rotation
88
+
89
+ Rotation is specified in **degrees** (converted to radians internally):
90
+
91
+ ```js
92
+ const shape = new Rectangle({
93
+ width: 100,
94
+ height: 50,
95
+ rotation: 45 // 45 degrees clockwise
96
+ });
97
+
98
+ // Update rotation
99
+ shape.rotation = 90; // 90 degrees
100
+ shape.rotation = -30; // 30 degrees counter-clockwise
101
+ ```
102
+
103
+ ## Scaling
104
+
105
+ Scale factors multiply the shape's dimensions:
106
+
107
+ ```js
108
+ const shape = new Circle(50, {
109
+ scaleX: 2, // Twice as wide
110
+ scaleY: 0.5 // Half as tall
111
+ });
112
+
113
+ // Result: ellipse 200 wide, 50 tall
114
+ ```
115
+
116
+ Common patterns:
117
+
118
+ ```js
119
+ // Uniform scale
120
+ shape.scaleX = 2;
121
+ shape.scaleY = 2; // 2x size in both dimensions
122
+
123
+ // Flip horizontally
124
+ shape.scaleX = -1;
125
+
126
+ // Flip vertically
127
+ shape.scaleY = -1;
128
+ ```
129
+
130
+ ## Transform Order
131
+
132
+ Transforms are applied in this order:
133
+
134
+ 1. **Translate** to (x, y) — from Renderable
135
+ 2. **Rotate** by rotation angle
136
+ 3. **Scale** by scaleX, scaleY
137
+
138
+ ```js
139
+ // Canvas transform stack:
140
+ ctx.translate(x, y); // Move to position
141
+ ctx.rotate(rotation); // Rotate around position
142
+ ctx.scale(scaleX, scaleY); // Scale from position
143
+ ```
144
+
145
+ ## Transformed Bounds
146
+
147
+ `getBounds()` returns the axis-aligned bounding box that contains the rotated/scaled shape:
148
+
149
+ ```js
150
+ const rect = new Rectangle({
151
+ x: 100,
152
+ y: 100,
153
+ width: 100,
154
+ height: 50,
155
+ rotation: 45
156
+ });
157
+
158
+ const bounds = rect.getBounds();
159
+ // Returns AABB that contains the rotated rectangle
160
+ // bounds.width and bounds.height will be larger than original
161
+ ```
162
+
163
+ ```
164
+ Original: Rotated 45°:
165
+ ┌──────────┐ ◇
166
+ │ │ ╱ ╲
167
+ │ ● │ ╱ ╲
168
+ │ │ ◇ ● ◇
169
+ └──────────┘ ╲ ╱
170
+ ╲ ╱
171
+
172
+ ┌───────┐
173
+ │ AABB │
174
+ └───────┘
175
+ ```
176
+
177
+ ## Example: Spinning Shape
178
+
179
+ ```js
180
+ import { Rectangle, Painter } from 'gcanvas';
181
+
182
+ const canvas = document.getElementById('canvas');
183
+ Painter.init(canvas.getContext('2d'));
184
+
185
+ const rect = new Rectangle({
186
+ x: 400,
187
+ y: 300,
188
+ width: 100,
189
+ height: 60,
190
+ color: '#4ecdc4'
191
+ });
192
+
193
+ function animate() {
194
+ Painter.clear();
195
+
196
+ // Rotate 1 degree per frame
197
+ rect.rotation += 1;
198
+
199
+ rect.draw();
200
+ requestAnimationFrame(animate);
201
+ }
202
+
203
+ animate();
204
+ ```
205
+
206
+ ## Example: Pulsing Scale
207
+
208
+ ```js
209
+ let time = 0;
210
+
211
+ function animate() {
212
+ Painter.clear();
213
+ time += 0.05;
214
+
215
+ // Pulse between 0.8x and 1.2x
216
+ const scale = 1 + Math.sin(time) * 0.2;
217
+ shape.scaleX = scale;
218
+ shape.scaleY = scale;
219
+
220
+ shape.draw();
221
+ requestAnimationFrame(animate);
222
+ }
223
+ ```
224
+
225
+ ## Inheritance
226
+
227
+ ```
228
+ Renderable
229
+ └── Transformable <── You are here
230
+ └── Shape
231
+ └── Circle, Rectangle, Star, ...
232
+ ```
233
+
234
+ ## Related
235
+
236
+ - [Renderable](./renderable.md) - Parent class
237
+ - [Shape](./shape.md) - Adds fill/stroke styling
238
+ - [Shape Hierarchy](../hierarchy.md) - Full inheritance diagram
239
+
240
+ ## See Also
241
+
242
+ - [Shapes Module](../README.md)
243
+ - [Rendering Pipeline](../../../concepts/rendering-pipeline.md)