@guinetik/gcanvas 1.0.2 → 1.0.4

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 (217) hide show
  1. package/dist/gcanvas.es.js +25656 -0
  2. package/dist/gcanvas.es.min.js +1 -0
  3. package/dist/gcanvas.umd.js +1 -0
  4. package/dist/gcanvas.umd.min.js +1 -0
  5. package/package.json +23 -6
  6. package/src/game/objects/index.js +1 -0
  7. package/src/game/objects/spritesheet.js +260 -0
  8. package/src/game/ui/theme.js +6 -0
  9. package/src/io/keys.js +9 -1
  10. package/src/math/boolean.js +481 -0
  11. package/src/math/index.js +1 -0
  12. package/.github/workflows/release.yaml +0 -70
  13. package/.jshintrc +0 -4
  14. package/.vscode/settings.json +0 -22
  15. package/CLAUDE.md +0 -310
  16. package/blackhole.jpg +0 -0
  17. package/demo.png +0 -0
  18. package/demos/CNAME +0 -1
  19. package/demos/animations.html +0 -31
  20. package/demos/basic.html +0 -38
  21. package/demos/baskara.html +0 -31
  22. package/demos/bezier.html +0 -35
  23. package/demos/beziersignature.html +0 -29
  24. package/demos/blackhole.html +0 -28
  25. package/demos/blob.html +0 -35
  26. package/demos/coordinates.html +0 -698
  27. package/demos/cube3d.html +0 -23
  28. package/demos/demos.css +0 -303
  29. package/demos/dino.html +0 -42
  30. package/demos/easing.html +0 -28
  31. package/demos/events.html +0 -195
  32. package/demos/fluent.html +0 -647
  33. package/demos/fluid-simple.html +0 -22
  34. package/demos/fluid.html +0 -37
  35. package/demos/fractals.html +0 -36
  36. package/demos/gameobjects.html +0 -626
  37. package/demos/genart.html +0 -26
  38. package/demos/gendream.html +0 -26
  39. package/demos/group.html +0 -36
  40. package/demos/home.html +0 -587
  41. package/demos/index.html +0 -376
  42. package/demos/isometric.html +0 -34
  43. package/demos/js/animations.js +0 -452
  44. package/demos/js/basic.js +0 -204
  45. package/demos/js/baskara.js +0 -751
  46. package/demos/js/bezier.js +0 -692
  47. package/demos/js/beziersignature.js +0 -241
  48. package/demos/js/blackhole/accretiondisk.obj.js +0 -379
  49. package/demos/js/blackhole/blackhole.obj.js +0 -318
  50. package/demos/js/blackhole/index.js +0 -409
  51. package/demos/js/blackhole/particle.js +0 -56
  52. package/demos/js/blackhole/starfield.obj.js +0 -218
  53. package/demos/js/blob.js +0 -2276
  54. package/demos/js/coordinates.js +0 -840
  55. package/demos/js/cube3d.js +0 -789
  56. package/demos/js/dino.js +0 -1420
  57. package/demos/js/easing.js +0 -477
  58. package/demos/js/fluent.js +0 -183
  59. package/demos/js/fluid-simple.js +0 -253
  60. package/demos/js/fluid.js +0 -527
  61. package/demos/js/fractals.js +0 -931
  62. package/demos/js/fractalworker.js +0 -93
  63. package/demos/js/gameobjects.js +0 -176
  64. package/demos/js/genart.js +0 -268
  65. package/demos/js/gendream.js +0 -209
  66. package/demos/js/group.js +0 -140
  67. package/demos/js/info-toggle.js +0 -25
  68. package/demos/js/isometric.js +0 -863
  69. package/demos/js/kerr.js +0 -1556
  70. package/demos/js/lavalamp.js +0 -590
  71. package/demos/js/layout.js +0 -354
  72. package/demos/js/mondrian.js +0 -285
  73. package/demos/js/opacity.js +0 -275
  74. package/demos/js/painter.js +0 -484
  75. package/demos/js/particles-showcase.js +0 -514
  76. package/demos/js/particles.js +0 -299
  77. package/demos/js/patterns.js +0 -397
  78. package/demos/js/penrose/artifact.js +0 -69
  79. package/demos/js/penrose/blackhole.js +0 -121
  80. package/demos/js/penrose/constants.js +0 -73
  81. package/demos/js/penrose/game.js +0 -943
  82. package/demos/js/penrose/lore.js +0 -278
  83. package/demos/js/penrose/penrosescene.js +0 -892
  84. package/demos/js/penrose/ship.js +0 -216
  85. package/demos/js/penrose/sounds.js +0 -211
  86. package/demos/js/penrose/voidparticle.js +0 -55
  87. package/demos/js/penrose/voidscene.js +0 -258
  88. package/demos/js/penrose/voidship.js +0 -144
  89. package/demos/js/penrose/wormhole.js +0 -46
  90. package/demos/js/pipeline.js +0 -555
  91. package/demos/js/plane3d.js +0 -256
  92. package/demos/js/platformer.js +0 -1579
  93. package/demos/js/scene.js +0 -304
  94. package/demos/js/scenes.js +0 -320
  95. package/demos/js/schrodinger.js +0 -410
  96. package/demos/js/schwarzschild.js +0 -1023
  97. package/demos/js/shapes.js +0 -628
  98. package/demos/js/space/alien.js +0 -171
  99. package/demos/js/space/boom.js +0 -98
  100. package/demos/js/space/boss.js +0 -353
  101. package/demos/js/space/buff.js +0 -73
  102. package/demos/js/space/bullet.js +0 -102
  103. package/demos/js/space/constants.js +0 -85
  104. package/demos/js/space/game.js +0 -1884
  105. package/demos/js/space/hud.js +0 -112
  106. package/demos/js/space/laserbeam.js +0 -179
  107. package/demos/js/space/lightning.js +0 -277
  108. package/demos/js/space/minion.js +0 -192
  109. package/demos/js/space/missile.js +0 -212
  110. package/demos/js/space/player.js +0 -430
  111. package/demos/js/space/powerup.js +0 -90
  112. package/demos/js/space/starfield.js +0 -58
  113. package/demos/js/space/starpower.js +0 -90
  114. package/demos/js/spacetime.js +0 -559
  115. package/demos/js/sphere3d.js +0 -229
  116. package/demos/js/sprite.js +0 -473
  117. package/demos/js/svgtween.js +0 -204
  118. package/demos/js/tde/accretiondisk.js +0 -471
  119. package/demos/js/tde/blackhole.js +0 -219
  120. package/demos/js/tde/blackholescene.js +0 -209
  121. package/demos/js/tde/config.js +0 -59
  122. package/demos/js/tde/index.js +0 -820
  123. package/demos/js/tde/jets.js +0 -290
  124. package/demos/js/tde/lensedstarfield.js +0 -154
  125. package/demos/js/tde/tdestar.js +0 -297
  126. package/demos/js/tde/tidalstream.js +0 -372
  127. package/demos/js/tde_old/blackhole.obj.js +0 -354
  128. package/demos/js/tde_old/debris.obj.js +0 -791
  129. package/demos/js/tde_old/flare.obj.js +0 -239
  130. package/demos/js/tde_old/index.js +0 -448
  131. package/demos/js/tde_old/star.obj.js +0 -812
  132. package/demos/js/tiles.js +0 -312
  133. package/demos/js/tweendemo.js +0 -79
  134. package/demos/js/visibility.js +0 -102
  135. package/demos/kerr.html +0 -28
  136. package/demos/lavalamp.html +0 -27
  137. package/demos/layouts.html +0 -37
  138. package/demos/logo.svg +0 -4
  139. package/demos/loop.html +0 -84
  140. package/demos/mondrian.html +0 -32
  141. package/demos/og_image.png +0 -0
  142. package/demos/opacity.html +0 -36
  143. package/demos/painter.html +0 -39
  144. package/demos/particles-showcase.html +0 -28
  145. package/demos/particles.html +0 -24
  146. package/demos/patterns.html +0 -33
  147. package/demos/penrose-game.html +0 -31
  148. package/demos/pipeline.html +0 -737
  149. package/demos/plane3d.html +0 -24
  150. package/demos/platformer.html +0 -43
  151. package/demos/scene.html +0 -33
  152. package/demos/scenes.html +0 -96
  153. package/demos/schrodinger.html +0 -27
  154. package/demos/schwarzschild.html +0 -27
  155. package/demos/shapes.html +0 -16
  156. package/demos/space.html +0 -85
  157. package/demos/spacetime.html +0 -27
  158. package/demos/sphere3d.html +0 -24
  159. package/demos/sprite.html +0 -18
  160. package/demos/svgtween.html +0 -29
  161. package/demos/tde.html +0 -28
  162. package/demos/tiles.html +0 -28
  163. package/demos/transforms.html +0 -400
  164. package/demos/tween.html +0 -45
  165. package/demos/visibility.html +0 -33
  166. package/docs/README.md +0 -230
  167. package/docs/api/FluidSystem.md +0 -173
  168. package/docs/concepts/architecture-overview.md +0 -204
  169. package/docs/concepts/coordinate-system.md +0 -384
  170. package/docs/concepts/lifecycle.md +0 -255
  171. package/docs/concepts/rendering-pipeline.md +0 -279
  172. package/docs/concepts/shapes-vs-gameobjects.md +0 -187
  173. package/docs/concepts/tde-zorder.md +0 -106
  174. package/docs/concepts/two-layer-architecture.md +0 -229
  175. package/docs/fluid-dynamics.md +0 -99
  176. package/docs/getting-started/first-game.md +0 -354
  177. package/docs/getting-started/hello-world.md +0 -269
  178. package/docs/getting-started/installation.md +0 -175
  179. package/docs/modules/collision/README.md +0 -453
  180. package/docs/modules/fluent/README.md +0 -1075
  181. package/docs/modules/game/README.md +0 -303
  182. package/docs/modules/isometric-camera.md +0 -210
  183. package/docs/modules/isometric.md +0 -275
  184. package/docs/modules/painter/README.md +0 -328
  185. package/docs/modules/particle/README.md +0 -559
  186. package/docs/modules/shapes/README.md +0 -221
  187. package/docs/modules/shapes/base/euclidian.md +0 -123
  188. package/docs/modules/shapes/base/geometry2d.md +0 -204
  189. package/docs/modules/shapes/base/renderable.md +0 -215
  190. package/docs/modules/shapes/base/shape.md +0 -262
  191. package/docs/modules/shapes/base/transformable.md +0 -243
  192. package/docs/modules/shapes/hierarchy.md +0 -218
  193. package/docs/modules/state/README.md +0 -577
  194. package/docs/modules/util/README.md +0 -99
  195. package/docs/modules/util/camera3d.md +0 -412
  196. package/docs/modules/util/scene3d.md +0 -395
  197. package/index.html +0 -17
  198. package/jsdoc.json +0 -50
  199. package/scripts/build-demo.js +0 -69
  200. package/scripts/bundle4llm.js +0 -276
  201. package/scripts/clearconsole.js +0 -48
  202. package/test/math/orbital.test.js +0 -61
  203. package/test/math/tensor.test.js +0 -114
  204. package/test/particle/emitter.test.js +0 -204
  205. package/test/particle/particle-system.test.js +0 -310
  206. package/test/particle/particle.test.js +0 -116
  207. package/test/particle/updaters.test.js +0 -386
  208. package/test/setup.js +0 -120
  209. package/test/shapes/euclidian.test.js +0 -44
  210. package/test/shapes/geometry.test.js +0 -86
  211. package/test/shapes/group.test.js +0 -86
  212. package/test/shapes/rectangle.test.js +0 -64
  213. package/test/shapes/transform.test.js +0 -379
  214. package/test/util/camera3d.test.js +0 -428
  215. package/test/util/scene3d.test.js +0 -352
  216. package/vite.config.js +0 -50
  217. package/vitest.config.js +0 -13
@@ -1,275 +0,0 @@
1
- # IsometricScene
2
-
3
- > A Scene subclass for rendering isometric tile-based games and visualizations.
4
-
5
- ## Overview
6
-
7
- `IsometricScene` extends `Scene` to provide automatic isometric projection for child GameObjects. It uses the standard "diamond" isometric projection where grid coordinates (x, y) are transformed to 2D screen positions, with optional z-axis support for height above the ground plane.
8
-
9
- ## Quick Start
10
-
11
- ```javascript
12
- import { Game, IsometricScene, GameObject } from "@guinetik/gcanvas";
13
-
14
- class MyGame extends Game {
15
- init() {
16
- super.init();
17
-
18
- // Create an isometric scene centered on canvas
19
- const isoScene = new IsometricScene(this, {
20
- x: this.width / 2,
21
- y: this.height / 2,
22
- tileWidth: 64,
23
- tileHeight: 32,
24
- gridSize: 10,
25
- depthSort: true,
26
- });
27
-
28
- // Add objects using grid coordinates
29
- const player = new Player(this);
30
- player.x = 0; // Grid X
31
- player.y = 0; // Grid Y
32
- player.z = 0; // Height above ground
33
- isoScene.add(player);
34
-
35
- this.pipeline.add(isoScene);
36
- }
37
- }
38
- ```
39
-
40
- ## Constructor Options
41
-
42
- | Option | Type | Default | Description |
43
- |--------|------|---------|-------------|
44
- | `tileWidth` | number | 64 | Width of a tile in pixels |
45
- | `tileHeight` | number | tileWidth / 2 | Height of a tile in pixels |
46
- | `gridSize` | number | 10 | Size of the grid (used for scale calculations) |
47
- | `depthSort` | boolean | true | Sort children by depth (back-to-front) |
48
- | `scaleByDepth` | boolean | false | Scale children by perspective distance |
49
- | `elevationScale` | number | 1 | Multiplier for z-axis visual offset |
50
- | `camera` | IsometricCamera | null | Optional camera for animated view rotation |
51
-
52
- ## Coordinate System
53
-
54
- IsometricScene uses a diamond-shaped isometric projection:
55
-
56
- ```
57
- Y-
58
- \
59
- \
60
- \
61
- X- ------+------ X+
62
- /
63
- /
64
- /
65
- Y+
66
- ```
67
-
68
- - **Grid coordinates (x, y)**: Position on the isometric grid
69
- - **Z coordinate**: Height above the ground plane
70
- - **Screen coordinates**: Calculated automatically via projection
71
-
72
- ### Projection Formula
73
-
74
- ```javascript
75
- // Grid to screen conversion
76
- screenX = (x - y) * (tileWidth / 2)
77
- screenY = (x + y) * (tileHeight / 2) - z * elevationScale
78
- ```
79
-
80
- ## API Reference
81
-
82
- ### toIsometric(x, y, z?)
83
-
84
- Converts grid coordinates to screen coordinates.
85
-
86
- ```javascript
87
- const screen = isoScene.toIsometric(5, 3, 0);
88
- // { x: 64, y: 128, depth: 8 }
89
- ```
90
-
91
- **Parameters:**
92
- - `x` (number): Grid X coordinate
93
- - `y` (number): Grid Y coordinate
94
- - `z` (number, optional): Height above ground (default: 0)
95
-
96
- **Returns:** `{ x: number, y: number, depth: number }`
97
-
98
- ### fromIsometric(screenX, screenY)
99
-
100
- Converts screen coordinates back to grid coordinates (inverse transform).
101
-
102
- ```javascript
103
- const grid = isoScene.fromIsometric(64, 128);
104
- // { x: 5, y: 3 }
105
- ```
106
-
107
- **Parameters:**
108
- - `screenX` (number): Screen X relative to scene center
109
- - `screenY` (number): Screen Y relative to scene center
110
-
111
- **Returns:** `{ x: number, y: number }`
112
-
113
- ### getTileAt(screenX, screenY)
114
-
115
- Gets the tile coordinates at a screen position (floored to integers).
116
-
117
- ```javascript
118
- const tile = isoScene.getTileAt(mouseX - scene.x, mouseY - scene.y);
119
- // { x: 5, y: 3 }
120
- ```
121
-
122
- **Parameters:**
123
- - `screenX` (number): Screen X relative to scene center
124
- - `screenY` (number): Screen Y relative to scene center
125
-
126
- **Returns:** `{ x: number, y: number }`
127
-
128
- ### getDepthScale(y)
129
-
130
- Calculates scale factor for perspective effect based on Y position.
131
-
132
- ```javascript
133
- const scale = isoScene.getDepthScale(5);
134
- // 1.0 (range: 0.7 to 1.3)
135
- ```
136
-
137
- **Parameters:**
138
- - `y` (number): Grid Y position
139
-
140
- **Returns:** `number` (scale factor)
141
-
142
- ## Depth Sorting
143
-
144
- When `depthSort` is enabled (default), children are rendered in back-to-front order based on:
145
-
146
- 1. **zIndex** (primary): Higher zIndex renders on top
147
- 2. **Isometric depth** (secondary): Calculated as `x + y - z * 0.01`
148
-
149
- Objects further back (lower x + y values) render first, allowing closer objects to overlap them correctly.
150
-
151
- ```javascript
152
- // Force an object to render behind/in front
153
- myObject.zIndex = -1; // Render behind others
154
- myObject.zIndex = 10; // Render on top
155
- ```
156
-
157
- ## Working with Children
158
-
159
- ### Grid-Based GameObjects
160
-
161
- Children added to IsometricScene use grid coordinates:
162
-
163
- ```javascript
164
- class Tile extends GameObject {
165
- constructor(game, gridX, gridY) {
166
- super(game);
167
- this.x = gridX; // Grid coordinate, not pixels
168
- this.y = gridY;
169
- this.z = 0; // Ground level
170
- }
171
-
172
- render() {
173
- // Render at local origin - scene handles projection
174
- Painter.shapes.fillRect(-16, -8, 32, 16, "#8B4513");
175
- }
176
- }
177
- ```
178
-
179
- ### Manual Projection
180
-
181
- For complex rendering (shadows, effects), access the scene's projection:
182
-
183
- ```javascript
184
- class Ball extends GameObject {
185
- render() {
186
- // Get projected position for manual drawing
187
- const pos = this.parent.toIsometric(this.x, this.y, 0);
188
- const elevation = this.z * 0.7;
189
-
190
- // Draw shadow at ground level
191
- Painter.shapes.fillCircle(pos.x, pos.y, 10, "rgba(0,0,0,0.3)");
192
-
193
- // Draw ball at elevated position
194
- Painter.shapes.fillCircle(pos.x, pos.y - elevation, 10, "blue");
195
- }
196
- }
197
- ```
198
-
199
- ## Example: Tile Map
200
-
201
- ```javascript
202
- class TileMap extends GameObject {
203
- constructor(game, isoScene) {
204
- super(game);
205
- this.isoScene = isoScene;
206
- this.tiles = [
207
- [1, 1, 1, 1, 1],
208
- [1, 0, 0, 0, 1],
209
- [1, 0, 2, 0, 1],
210
- [1, 0, 0, 0, 1],
211
- [1, 1, 1, 1, 1],
212
- ];
213
- this.colors = {
214
- 0: "#90EE90", // Grass
215
- 1: "#8B4513", // Wall
216
- 2: "#4169E1", // Water
217
- };
218
- this.zIndex = -1;
219
- }
220
-
221
- render() {
222
- const size = this.tiles.length;
223
- const halfW = this.isoScene.tileWidth / 2;
224
- const halfH = this.isoScene.tileHeight / 2;
225
-
226
- for (let y = 0; y < size; y++) {
227
- for (let x = 0; x < size; x++) {
228
- const tileType = this.tiles[y][x];
229
- const pos = this.isoScene.toIsometric(x - size/2, y - size/2);
230
-
231
- // Draw diamond tile
232
- Painter.useCtx((ctx) => {
233
- ctx.beginPath();
234
- ctx.moveTo(pos.x, pos.y - halfH);
235
- ctx.lineTo(pos.x + halfW, pos.y);
236
- ctx.lineTo(pos.x, pos.y + halfH);
237
- ctx.lineTo(pos.x - halfW, pos.y);
238
- ctx.closePath();
239
- ctx.fillStyle = this.colors[tileType];
240
- ctx.fill();
241
- ctx.strokeStyle = "#000";
242
- ctx.lineWidth = 1;
243
- ctx.stroke();
244
- });
245
- }
246
- }
247
- }
248
- }
249
- ```
250
-
251
- ## Example: Mouse Picking
252
-
253
- ```javascript
254
- class PickableGrid extends IsometricScene {
255
- constructor(game, options) {
256
- super(game, { ...options, interactive: true });
257
- this.hoveredTile = null;
258
- }
259
-
260
- onMouseMove(e) {
261
- // Convert screen position to scene-local coordinates
262
- const localX = e.clientX - this.x;
263
- const localY = e.clientY - this.y;
264
-
265
- // Get tile at mouse position
266
- this.hoveredTile = this.getTileAt(localX, localY);
267
- }
268
- }
269
- ```
270
-
271
- ## See Also
272
-
273
- - [Scene](./scene.md) - Base container class
274
- - [Scene3D](./scene3d.md) - Camera-based 3D projection
275
- - [Rendering Pipeline](../concepts/rendering-pipeline.md) - How rendering works
@@ -1,328 +0,0 @@
1
- # Painter Module
2
-
3
- > Low-level canvas drawing abstraction.
4
-
5
- ## Overview
6
-
7
- Painter is a static utility class that wraps the Canvas 2D API. It provides centralized drawing operations and state management, used internally by all shapes.
8
-
9
- ## Quick Start
10
-
11
- ```js
12
- import { Painter } from '@guinetik/gcanvas';
13
-
14
- // Initialize with canvas context
15
- const canvas = document.getElementById('canvas');
16
- Painter.init(canvas.getContext('2d'));
17
-
18
- // Draw shapes directly
19
- Painter.shapes.fillCircle(200, 150, 50, 'red');
20
- Painter.shapes.strokeRect(300, 100, 100, 80, 'blue', 2);
21
-
22
- // Draw text
23
- Painter.text.fill('Hello World', 400, 200, {
24
- font: '24px monospace',
25
- color: 'white'
26
- });
27
- ```
28
-
29
- ## Architecture
30
-
31
- Painter is composed of specialized sub-modules:
32
-
33
- ```
34
- ┌─────────────────────────────────────────────────────────────┐
35
- │ Painter │
36
- ├─────────────────────────────────────────────────────────────┤
37
- │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
38
- │ │ shapes │ │ text │ │ lines │ │
39
- │ │ fillCircle │ │ fill │ │ line │ │
40
- │ │ strokeRect │ │ stroke │ │ polyline │ │
41
- │ │ arc │ │ measure │ │ bezier │ │
42
- │ └─────────────┘ └─────────────┘ └─────────────┘ │
43
- │ │
44
- │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
45
- │ │ colors │ │ opacity │ │ effects │ │
46
- │ │ fill │ │ push │ │ setBlendMode│ │
47
- │ │ stroke │ │ pop │ │ shadow │ │
48
- │ │ gradient │ │ current │ │ filter │ │
49
- │ └─────────────┘ └─────────────┘ └─────────────┘ │
50
- │ │
51
- │ ┌─────────────┐ │
52
- │ │ img │ │
53
- │ │ draw │ │
54
- │ │ crop │ │
55
- │ │ pattern │ │
56
- │ └─────────────┘ │
57
- └─────────────────────────────────────────────────────────────┘
58
- ```
59
-
60
- ## Core API
61
-
62
- ### Initialization
63
-
64
- ```js
65
- Painter.init(ctx); // Set the canvas context
66
- const ctx = Painter.ctx; // Get the context
67
- ```
68
-
69
- ### Canvas State
70
-
71
- ```js
72
- Painter.save(); // Save canvas state
73
- Painter.restore(); // Restore canvas state
74
- Painter.clear(); // Clear entire canvas
75
- Painter.clear(x, y, w, h); // Clear rectangle
76
- ```
77
-
78
- ### Transforms
79
-
80
- ```js
81
- Painter.translateTo(x, y); // Move origin
82
- Painter.rotate(radians); // Rotate context
83
- Painter.scale(sx, sy); // Scale context
84
- ```
85
-
86
- ## Sub-Modules
87
-
88
- ### Painter.shapes
89
-
90
- Drawing geometric shapes.
91
-
92
- ```js
93
- // Circles
94
- Painter.shapes.fillCircle(x, y, radius, color);
95
- Painter.shapes.strokeCircle(x, y, radius, color, lineWidth);
96
-
97
- // Rectangles
98
- Painter.shapes.fillRect(x, y, width, height, color);
99
- Painter.shapes.strokeRect(x, y, width, height, color, lineWidth);
100
-
101
- // Rounded rectangles
102
- Painter.shapes.fillRoundedRect(x, y, w, h, radius, color);
103
- Painter.shapes.strokeRoundedRect(x, y, w, h, radius, color, lineWidth);
104
-
105
- // Arcs
106
- Painter.shapes.arc(x, y, radius, startAngle, endAngle, color);
107
- ```
108
-
109
- ### Painter.text
110
-
111
- Text rendering and measurement.
112
-
113
- ```js
114
- // Fill text
115
- Painter.text.fill(text, x, y, {
116
- font: '16px Arial',
117
- color: 'white',
118
- align: 'center', // left, center, right
119
- baseline: 'middle' // top, middle, bottom
120
- });
121
-
122
- // Stroke text
123
- Painter.text.stroke(text, x, y, {
124
- font: '24px Arial',
125
- color: 'black',
126
- lineWidth: 2
127
- });
128
-
129
- // Measure text
130
- const metrics = Painter.text.measure(text, font);
131
- console.log(metrics.width);
132
- ```
133
-
134
- ### Painter.lines
135
-
136
- Line and path drawing.
137
-
138
- ```js
139
- // Simple line
140
- Painter.lines.line(x1, y1, x2, y2, color, lineWidth);
141
-
142
- // Polyline
143
- Painter.lines.polyline([
144
- { x: 0, y: 0 },
145
- { x: 100, y: 50 },
146
- { x: 200, y: 25 }
147
- ], color, lineWidth);
148
-
149
- // Bezier curve
150
- Painter.lines.bezier(
151
- x1, y1, // Start
152
- cp1x, cp1y, // Control point 1
153
- cp2x, cp2y, // Control point 2
154
- x2, y2, // End
155
- color, lineWidth
156
- );
157
- ```
158
-
159
- ### Painter.colors
160
-
161
- Fill and stroke color management.
162
-
163
- ```js
164
- // Set fill style
165
- Painter.colors.fill(color);
166
-
167
- // Set stroke style
168
- Painter.colors.stroke(color, lineWidth);
169
-
170
- // Create gradient
171
- const gradient = Painter.colors.linearGradient(x1, y1, x2, y2, stops);
172
- // stops: [{ offset: 0, color: 'red' }, { offset: 1, color: 'blue' }]
173
-
174
- const radial = Painter.colors.radialGradient(x, y, r1, r2, stops);
175
- ```
176
-
177
- ### Painter.opacity
178
-
179
- Opacity stack management.
180
-
181
- ```js
182
- // Push new opacity (multiplies with current)
183
- Painter.opacity.pushOpacity(0.5);
184
-
185
- // Drawing here is 50% transparent
186
-
187
- // Pop to restore previous
188
- Painter.opacity.popOpacity();
189
-
190
- // Get current effective opacity
191
- const current = Painter.opacity.currentOpacity;
192
- ```
193
-
194
- ### Painter.effects
195
-
196
- Visual effects.
197
-
198
- ```js
199
- // Blend modes
200
- Painter.effects.setBlendMode('multiply');
201
- Painter.effects.setBlendMode('screen');
202
- Painter.effects.setBlendMode('source-over'); // default
203
-
204
- // Shadow
205
- Painter.effects.shadow(color, blur, offsetX, offsetY);
206
- Painter.effects.clearShadow();
207
- ```
208
-
209
- ### Painter.img
210
-
211
- Image drawing.
212
-
213
- ```js
214
- // Draw image
215
- Painter.img.draw(image, x, y);
216
- Painter.img.draw(image, x, y, width, height);
217
-
218
- // Draw cropped
219
- Painter.img.drawCropped(
220
- image,
221
- sx, sy, sw, sh, // Source rectangle
222
- dx, dy, dw, dh // Destination rectangle
223
- );
224
-
225
- // Create pattern
226
- const pattern = Painter.img.createPattern(image, 'repeat');
227
- ```
228
-
229
- ## Usage Patterns
230
-
231
- ### Direct Drawing (No Shapes)
232
-
233
- ```js
234
- Painter.init(ctx);
235
-
236
- function draw() {
237
- Painter.clear();
238
-
239
- // Draw background
240
- Painter.shapes.fillRect(0, 0, 800, 600, '#1a1a2e');
241
-
242
- // Draw shapes
243
- Painter.shapes.fillCircle(400, 300, 50, 'red');
244
-
245
- // Draw text
246
- Painter.text.fill('Score: 100', 10, 30, {
247
- font: '20px Arial',
248
- color: 'white'
249
- });
250
- }
251
- ```
252
-
253
- ### With State Management
254
-
255
- ```js
256
- Painter.save();
257
- Painter.translateTo(400, 300);
258
- Painter.rotate(Math.PI / 4);
259
- Painter.shapes.fillRect(-50, -25, 100, 50, 'blue');
260
- Painter.restore();
261
- ```
262
-
263
- ### Opacity Stacking
264
-
265
- ```js
266
- Painter.opacity.pushOpacity(0.8);
267
- // 80% opacity
268
- Painter.shapes.fillCircle(100, 100, 50, 'red');
269
-
270
- Painter.opacity.pushOpacity(0.5);
271
- // 40% opacity (0.8 * 0.5)
272
- Painter.shapes.fillCircle(150, 100, 50, 'blue');
273
- Painter.opacity.popOpacity();
274
-
275
- // Back to 80%
276
- Painter.shapes.fillCircle(200, 100, 50, 'green');
277
- Painter.opacity.popOpacity();
278
- ```
279
-
280
- ## When to Use Painter Directly
281
-
282
- Most of the time, use Shape classes. Use Painter directly when:
283
-
284
- - Drawing one-off graphics
285
- - Custom shape implementations
286
- - Performance-critical drawing
287
- - Procedural graphics
288
- - Effects not supported by shapes
289
-
290
- ## Example: Custom Shape
291
-
292
- ```js
293
- class Diamond extends Shape {
294
- draw() {
295
- super.draw(); // Apply transforms
296
-
297
- const hw = this.width / 2;
298
- const hh = this.height / 2;
299
-
300
- Painter.ctx.beginPath();
301
- Painter.ctx.moveTo(0, -hh);
302
- Painter.ctx.lineTo(hw, 0);
303
- Painter.ctx.lineTo(0, hh);
304
- Painter.ctx.lineTo(-hw, 0);
305
- Painter.ctx.closePath();
306
-
307
- if (this.color) {
308
- Painter.colors.fill(this.color);
309
- Painter.ctx.fill();
310
- }
311
-
312
- if (this.stroke) {
313
- Painter.colors.stroke(this.stroke, this.lineWidth);
314
- Painter.ctx.stroke();
315
- }
316
- }
317
- }
318
- ```
319
-
320
- ## Related
321
-
322
- - [Shapes Module](../shapes/README.md) - High-level shape classes
323
- - [Rendering Pipeline](../../concepts/rendering-pipeline.md) - How shapes use Painter
324
-
325
- ## See Also
326
-
327
- - [Hello World](../../getting-started/hello-world.md)
328
- - [Architecture Overview](../../concepts/architecture-overview.md)