@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,157 @@
1
+ # Installation
2
+
3
+ > How to set up GCanvas in your project.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js 18+ (for development)
8
+ - Modern browser with ES6 support
9
+
10
+ ## Option 1: Clone Repository
11
+
12
+ The recommended way to get started:
13
+
14
+ ```bash
15
+ git clone https://github.com/guinetik/gcanvas.git
16
+ cd gcanvas
17
+ npm install
18
+ ```
19
+
20
+ ### Run Development Server
21
+
22
+ ```bash
23
+ npm run dev
24
+ ```
25
+
26
+ This starts Vite's dev server with hot reload. Open `http://localhost:5173` to see the demos.
27
+
28
+ ### Build the Library
29
+
30
+ ```bash
31
+ npm run build
32
+ ```
33
+
34
+ Outputs to `dist/`:
35
+ - `gcanvas.es.js` - ES Module
36
+ - `gcanvas.es.min.js` - ES Module (minified)
37
+ - `gcanvas.umd.js` - UMD bundle
38
+ - `gcanvas.umd.min.js` - UMD bundle (minified)
39
+
40
+ ## Option 2: NPM (Coming Soon)
41
+
42
+ ```bash
43
+ npm install gcanvas
44
+ ```
45
+
46
+ Then import in your project:
47
+
48
+ ```js
49
+ import { Game, Circle, Rectangle } from 'gcanvas';
50
+ ```
51
+
52
+ ## Option 3: Direct Script Include
53
+
54
+ ### ES Module
55
+
56
+ ```html
57
+ <script type="module">
58
+ import { Circle, Painter } from './dist/gcanvas.es.min.js';
59
+
60
+ const canvas = document.getElementById('canvas');
61
+ Painter.init(canvas.getContext('2d'));
62
+
63
+ const circle = new Circle(50, { x: 100, y: 100, color: 'red' });
64
+ circle.draw();
65
+ </script>
66
+ ```
67
+
68
+ ### UMD Bundle
69
+
70
+ ```html
71
+ <script src="./dist/gcanvas.umd.min.js"></script>
72
+ <script>
73
+ const { Circle, Painter } = GCanvas;
74
+
75
+ const canvas = document.getElementById('canvas');
76
+ Painter.init(canvas.getContext('2d'));
77
+
78
+ const circle = new GCanvas.Circle(50, { x: 100, y: 100, color: 'red' });
79
+ circle.draw();
80
+ </script>
81
+ ```
82
+
83
+ ## Project Structure
84
+
85
+ ```
86
+ gcanvas/
87
+ ├── src/ # Source code
88
+ │ ├── shapes/ # Shape classes
89
+ │ ├── game/ # Game loop, objects
90
+ │ ├── painter/ # Canvas abstraction
91
+ │ ├── motion/ # Animation
92
+ │ ├── io/ # Input handling
93
+ │ └── index.js # Main entry point
94
+ ├── demos/ # Demo applications
95
+ ├── dist/ # Built library
96
+ └── docs/ # Documentation
97
+ ```
98
+
99
+ ## NPM Scripts
100
+
101
+ | Script | Description |
102
+ |--------|-------------|
103
+ | `npm run dev` | Start development server |
104
+ | `npm run build` | Build library |
105
+ | `npm run build:demo` | Build demos for deployment |
106
+ | `npm run docs` | Generate JSDoc documentation |
107
+ | `npm run test` | Run tests |
108
+
109
+ ## TypeScript Support
110
+
111
+ TypeScript definitions are coming soon. For now, the library is written in JavaScript with JSDoc annotations.
112
+
113
+ ## Browser Support
114
+
115
+ GCanvas works in all modern browsers:
116
+
117
+ - Chrome 60+
118
+ - Firefox 55+
119
+ - Safari 11+
120
+ - Edge 79+
121
+
122
+ ## Next Steps
123
+
124
+ - [Hello World](./hello-world.md) - Draw your first shape
125
+ - [First Game](./first-game.md) - Create an interactive game
126
+ - [Architecture Overview](../concepts/architecture-overview.md) - Understand the design
127
+
128
+ ## Troubleshooting
129
+
130
+ ### Canvas not found
131
+
132
+ Make sure your canvas element has an ID and the script runs after DOM is ready:
133
+
134
+ ```html
135
+ <canvas id="game"></canvas>
136
+ <script type="module">
137
+ // Script runs after DOM is parsed when using type="module"
138
+ const canvas = document.getElementById('game');
139
+ </script>
140
+ ```
141
+
142
+ ### Module not found
143
+
144
+ When using ES modules, ensure paths are correct:
145
+
146
+ ```js
147
+ // Relative path from your script
148
+ import { Circle } from './dist/gcanvas.es.min.js';
149
+
150
+ // Or absolute path
151
+ import { Circle } from '/dist/gcanvas.es.min.js';
152
+ ```
153
+
154
+ ## Related
155
+
156
+ - [Hello World](./hello-world.md)
157
+ - [Architecture Overview](../concepts/architecture-overview.md)
@@ -0,0 +1,453 @@
1
+ # Collision Module
2
+
3
+ > 2D collision detection utilities and group-based collision management.
4
+
5
+ ## Overview
6
+
7
+ The collision module provides both low-level collision detection algorithms and a high-level system for managing collision groups in games. It supports various collision shapes including rectangles, circles, lines, and multi-segment paths.
8
+
9
+ ## Quick Start
10
+
11
+ ```js
12
+ import { Collision, CollisionSystem } from 'gcanvas';
13
+
14
+ // Low-level: Direct collision checks
15
+ const playerBounds = player.getBounds();
16
+ const enemyBounds = enemy.getBounds();
17
+
18
+ if (Collision.rectRect(playerBounds, enemyBounds)) {
19
+ console.log('Hit!');
20
+ }
21
+
22
+ // High-level: Group-based collision management
23
+ const collisions = new CollisionSystem()
24
+ .createGroup('players')
25
+ .createGroup('enemies')
26
+ .createGroup('bullets')
27
+ .onCollision('bullets', 'enemies', (bullet, enemy) => {
28
+ bullet.destroy();
29
+ enemy.takeDamage(10);
30
+ });
31
+
32
+ // In game loop
33
+ collisions.update();
34
+ ```
35
+
36
+ ## Core Classes
37
+
38
+ | Class | Description |
39
+ |-------|-------------|
40
+ | **Collision** | Static utility methods for collision detection |
41
+ | **CollisionSystem** | Group-based collision management with callbacks |
42
+
43
+ ---
44
+
45
+ ## Collision Class
46
+
47
+ Static utility class with various collision detection algorithms. All methods work with bounds objects: `{ x, y, width, height }` for rectangles, `{ x, y, radius }` for circles.
48
+
49
+ ### Rectangle vs Rectangle (AABB)
50
+
51
+ The most common collision check - axis-aligned bounding boxes.
52
+
53
+ ```js
54
+ const a = { x: 100, y: 100, width: 50, height: 50 };
55
+ const b = { x: 120, y: 120, width: 50, height: 50 };
56
+
57
+ if (Collision.rectRect(a, b)) {
58
+ console.log('Rectangles overlap!');
59
+ }
60
+
61
+ // Alias
62
+ Collision.intersects(a, b);
63
+ ```
64
+
65
+ ### Circle vs Circle
66
+
67
+ For circular hitboxes - more accurate for round objects.
68
+
69
+ ```js
70
+ const circleA = { x: 100, y: 100, radius: 30 };
71
+ const circleB = { x: 150, y: 100, radius: 25 };
72
+
73
+ if (Collision.circleCircle(circleA, circleB)) {
74
+ console.log('Circles overlap!');
75
+ }
76
+ ```
77
+
78
+ ### Circle vs Rectangle
79
+
80
+ Mixed shape collision - finds closest point on rectangle to circle center.
81
+
82
+ ```js
83
+ const circle = { x: 100, y: 100, radius: 30 };
84
+ const rect = { x: 120, y: 80, width: 60, height: 40 };
85
+
86
+ if (Collision.circleRect(circle, rect)) {
87
+ console.log('Circle and rectangle overlap!');
88
+ }
89
+ ```
90
+
91
+ ### Point Collision
92
+
93
+ Check if a point (like mouse cursor) is inside a shape.
94
+
95
+ ```js
96
+ // Point in rectangle
97
+ if (Collision.pointRect(mouseX, mouseY, button.getBounds())) {
98
+ button.highlight();
99
+ }
100
+
101
+ // Point in circle
102
+ if (Collision.pointCircle(mouseX, mouseY, planet)) {
103
+ showTooltip('Planet selected');
104
+ }
105
+ ```
106
+
107
+ ### Line vs Rectangle
108
+
109
+ For laser beams, lightning bolts, and raycast-style collision.
110
+
111
+ ```js
112
+ // Basic line collision
113
+ if (Collision.lineRect(x1, y1, x2, y2, target.getBounds())) {
114
+ console.log('Line hits target!');
115
+ }
116
+
117
+ // With thickness (for thick beams)
118
+ if (Collision.lineRect(x1, y1, x2, y2, target.getBounds(), 10)) {
119
+ console.log('Thick beam hits target!');
120
+ }
121
+ ```
122
+
123
+ ### Line vs Line
124
+
125
+ Check if two line segments intersect.
126
+
127
+ ```js
128
+ if (Collision.lineLine(x1, y1, x2, y2, x3, y3, x4, y4)) {
129
+ console.log('Lines cross!');
130
+ }
131
+ ```
132
+
133
+ ### Multi-Segment Collision
134
+
135
+ For complex shapes like branching lightning or paths.
136
+
137
+ ```js
138
+ const lightningSegments = [
139
+ { x1: 400, y1: 0, x2: 380, y2: 50 },
140
+ { x1: 380, y1: 50, x2: 420, y2: 100 },
141
+ { x1: 420, y1: 100, x2: 390, y2: 150 }
142
+ ];
143
+
144
+ if (Collision.segmentsRect(lightningSegments, player.getBounds(), 8)) {
145
+ player.takeDamage();
146
+ }
147
+ ```
148
+
149
+ ### Collision Response
150
+
151
+ Get information needed to respond to collisions.
152
+
153
+ ```js
154
+ // Get overlap depth
155
+ const overlap = Collision.getOverlap(playerBounds, wallBounds);
156
+ if (overlap) {
157
+ console.log(`Overlap: ${overlap.x}px x ${overlap.y}px`);
158
+ }
159
+
160
+ // Get minimum translation vector (for pushing objects apart)
161
+ const mtv = Collision.getMTV(playerBounds, wallBounds);
162
+ if (mtv) {
163
+ player.x += mtv.x;
164
+ player.y += mtv.y;
165
+ }
166
+ ```
167
+
168
+ ### Sweep Test (Continuous Collision)
169
+
170
+ Prevents fast-moving objects from tunneling through thin walls.
171
+
172
+ ```js
173
+ const bullet = { x: 100, y: 100, width: 10, height: 10 };
174
+ const wall = { x: 200, y: 50, width: 20, height: 200 };
175
+ const velocityX = 500;
176
+ const velocityY = 0;
177
+
178
+ const hit = Collision.sweep(bullet, velocityX, velocityY, wall);
179
+ if (hit) {
180
+ console.log(`Hit at time: ${hit.time}`);
181
+ console.log(`Normal: ${hit.normalX}, ${hit.normalY}`);
182
+
183
+ // Move to collision point
184
+ bullet.x += velocityX * hit.time;
185
+ bullet.y += velocityY * hit.time;
186
+ }
187
+ ```
188
+
189
+ ### Method Reference
190
+
191
+ | Method | Signature | Description |
192
+ |--------|-----------|-------------|
193
+ | `rectRect` | `(a, b)` | AABB collision |
194
+ | `intersects` | `(a, b)` | Alias for rectRect |
195
+ | `circleCircle` | `(a, b)` | Circle collision |
196
+ | `circleRect` | `(circle, rect)` | Mixed shape collision |
197
+ | `pointRect` | `(px, py, rect)` | Point in rectangle |
198
+ | `pointCircle` | `(px, py, circle)` | Point in circle |
199
+ | `lineRect` | `(x1, y1, x2, y2, rect, thickness?)` | Line segment vs rectangle |
200
+ | `lineLine` | `(x1, y1, x2, y2, x3, y3, x4, y4)` | Line vs line |
201
+ | `segmentsRect` | `(segments, rect, thickness?)` | Multi-segment vs rectangle |
202
+ | `getOverlap` | `(a, b)` | Get overlap depth |
203
+ | `getMTV` | `(a, b)` | Get minimum translation vector |
204
+ | `sweep` | `(rect, vx, vy, target)` | Continuous collision detection |
205
+
206
+ ---
207
+
208
+ ## CollisionSystem Class
209
+
210
+ High-level system for managing collision groups and callbacks. Ideal for games with multiple entity types.
211
+
212
+ ### Creating Groups
213
+
214
+ ```js
215
+ const collisions = new CollisionSystem();
216
+
217
+ // Create groups for different entity types
218
+ collisions.createGroup('players');
219
+ collisions.createGroup('enemies');
220
+ collisions.createGroup('bullets');
221
+ collisions.createGroup('pickups');
222
+ collisions.createGroup('walls');
223
+ ```
224
+
225
+ ### Adding Objects to Groups
226
+
227
+ Objects must have either a `getBounds()` method or a `bounds` property.
228
+
229
+ ```js
230
+ // Add single object
231
+ collisions.add('players', player);
232
+ collisions.add('enemies', alien);
233
+
234
+ // Add multiple objects
235
+ aliens.forEach(alien => collisions.add('enemies', alien));
236
+ ```
237
+
238
+ ### Registering Collision Callbacks
239
+
240
+ ```js
241
+ // When bullets hit enemies
242
+ collisions.onCollision('bullets', 'enemies', (bullet, enemy) => {
243
+ bullet.destroy();
244
+ enemy.takeDamage(10);
245
+ spawnExplosion(enemy.x, enemy.y);
246
+ });
247
+
248
+ // When player touches pickups
249
+ collisions.onCollision('players', 'pickups', (player, pickup) => {
250
+ pickup.collect();
251
+ player.score += pickup.value;
252
+ });
253
+
254
+ // When player hits walls (for collision response)
255
+ collisions.onCollision('players', 'walls', (player, wall) => {
256
+ const mtv = Collision.getMTV(player.getBounds(), wall.getBounds());
257
+ if (mtv) {
258
+ player.x += mtv.x;
259
+ player.y += mtv.y;
260
+ }
261
+ });
262
+ ```
263
+
264
+ ### Update Loop
265
+
266
+ Call `update()` each frame to check all registered collision pairs.
267
+
268
+ ```js
269
+ class MyGame extends Game {
270
+ update(dt) {
271
+ super.update(dt);
272
+
273
+ // Check all collisions
274
+ this.collisions.update();
275
+ }
276
+ }
277
+ ```
278
+
279
+ ### Manual Collision Checks
280
+
281
+ For cases where you need more control than callbacks.
282
+
283
+ ```js
284
+ // Check specific pair, get all collisions
285
+ const hits = collisions.check('bullets', 'enemies');
286
+ for (const [bullet, enemy] of hits) {
287
+ // Handle collision
288
+ }
289
+
290
+ // Check one object against a group
291
+ const enemy = collisions.checkAgainstGroup(bullet, 'enemies');
292
+ if (enemy) {
293
+ // First enemy hit
294
+ }
295
+
296
+ // Get all objects hit
297
+ const allEnemies = collisions.checkAllAgainstGroup(bullet, 'enemies');
298
+ ```
299
+
300
+ ### Removing Objects
301
+
302
+ ```js
303
+ // Remove from specific group
304
+ collisions.remove('enemies', deadEnemy);
305
+
306
+ // Remove from all groups
307
+ collisions.removeFromAll(destroyedObject);
308
+
309
+ // Clear entire group
310
+ collisions.clearGroup('bullets');
311
+
312
+ // Clear everything
313
+ collisions.clearAll();
314
+ ```
315
+
316
+ ### Active Object Filtering
317
+
318
+ CollisionSystem automatically skips inactive objects. It checks for:
319
+ - `obj.active === false`
320
+ - `obj.destroyed === true`
321
+ - `obj.alive === false`
322
+
323
+ ```js
324
+ // These objects are automatically skipped
325
+ enemy.active = false; // Skipped
326
+ bullet.destroyed = true; // Skipped
327
+ player.alive = false; // Skipped
328
+ ```
329
+
330
+ ### Method Reference
331
+
332
+ | Method | Returns | Description |
333
+ |--------|---------|-------------|
334
+ | `createGroup(name)` | `this` | Create a collision group |
335
+ | `add(group, obj)` | `this` | Add object to group |
336
+ | `remove(group, obj)` | `boolean` | Remove object from group |
337
+ | `removeFromAll(obj)` | `void` | Remove from all groups |
338
+ | `clearGroup(name)` | `void` | Clear all objects in group |
339
+ | `clearAll()` | `void` | Clear all groups |
340
+ | `getGroup(name)` | `Array` | Get all objects in group |
341
+ | `onCollision(a, b, callback)` | `this` | Register collision callback |
342
+ | `offCollision(a, b)` | `void` | Remove collision callback |
343
+ | `update()` | `void` | Check all collision pairs |
344
+ | `check(a, b)` | `Array<[obj, obj]>` | Get all colliding pairs |
345
+ | `checkAgainstGroup(obj, group)` | `Object\|null` | First collision in group |
346
+ | `checkAllAgainstGroup(obj, group)` | `Array` | All collisions in group |
347
+
348
+ ---
349
+
350
+ ## Complete Example
351
+
352
+ A Space Invaders-style collision setup:
353
+
354
+ ```js
355
+ import { Game, CollisionSystem, Collision } from 'gcanvas';
356
+
357
+ class SpaceGame extends Game {
358
+ init() {
359
+ super.init();
360
+
361
+ // Set up collision system
362
+ this.collisions = new CollisionSystem()
363
+ .createGroup('player')
364
+ .createGroup('aliens')
365
+ .createGroup('playerBullets')
366
+ .createGroup('alienBullets')
367
+ .createGroup('shields');
368
+
369
+ // Player bullets hit aliens
370
+ this.collisions.onCollision('playerBullets', 'aliens', (bullet, alien) => {
371
+ bullet.destroy();
372
+ alien.hit();
373
+ this.score += 100;
374
+ });
375
+
376
+ // Alien bullets hit player
377
+ this.collisions.onCollision('alienBullets', 'player', (bullet, player) => {
378
+ bullet.destroy();
379
+ this.handlePlayerHit();
380
+ });
381
+
382
+ // Any bullet hits shields
383
+ this.collisions.onCollision('playerBullets', 'shields', (bullet, shield) => {
384
+ bullet.destroy();
385
+ shield.damage();
386
+ });
387
+
388
+ this.collisions.onCollision('alienBullets', 'shields', (bullet, shield) => {
389
+ bullet.destroy();
390
+ shield.damage();
391
+ });
392
+
393
+ // Register initial objects
394
+ this.collisions.add('player', this.player);
395
+ this.aliens.forEach(a => this.collisions.add('aliens', a));
396
+ this.shields.forEach(s => this.collisions.add('shields', s));
397
+ }
398
+
399
+ spawnBullet(bullet, group) {
400
+ this.bullets.push(bullet);
401
+ this.collisions.add(group, bullet);
402
+ }
403
+
404
+ update(dt) {
405
+ super.update(dt);
406
+
407
+ // One line handles all collision logic!
408
+ this.collisions.update();
409
+ }
410
+ }
411
+ ```
412
+
413
+ ---
414
+
415
+ ## Architecture
416
+
417
+ ```
418
+ ┌─────────────────────────────────────────────────────────────┐
419
+ │ CollisionSystem │
420
+ │ ┌─────────────────────────────────────────────────────┐ │
421
+ │ │ Groups │ │
422
+ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
423
+ │ │ │ players │ │ enemies │ │ bullets │ ... │ │
424
+ │ │ │ Set() │ │ Set() │ │ Set() │ │ │
425
+ │ │ └─────────┘ └─────────┘ └─────────┘ │ │
426
+ │ └─────────────────────────────────────────────────────┘ │
427
+ │ │ │
428
+ │ ▼ │
429
+ │ ┌─────────────────────────────────────────────────────┐ │
430
+ │ │ Collision Pairs │ │
431
+ │ │ bullets vs enemies → callback │ │
432
+ │ │ bullets vs player → callback │ │
433
+ │ └─────────────────────────────────────────────────────┘ │
434
+ │ │ │
435
+ │ ▼ │
436
+ │ ┌─────────────────────────────────────────────────────┐ │
437
+ │ │ Collision (Static Utils) │ │
438
+ │ │ rectRect() | circleCircle() | lineRect() | ... │ │
439
+ │ └─────────────────────────────────────────────────────┘ │
440
+ └─────────────────────────────────────────────────────────────┘
441
+ ```
442
+
443
+ ---
444
+
445
+ ## Related
446
+
447
+ - [Game Module](../game/README.md) - Game loop and GameObjects
448
+ - [State Module](../state/README.md) - State machines for entity lifecycle
449
+
450
+ ## See Also
451
+
452
+ - [Motion Module](../motion/README.md) - Animation and movement
453
+ - [Shapes Module](../shapes/README.md) - Drawing primitives with bounds