@guinetik/gcanvas 1.0.0 → 1.0.1

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 (68) hide show
  1. package/demos/fluid-simple.html +22 -0
  2. package/demos/fluid.html +37 -0
  3. package/demos/index.html +2 -0
  4. package/demos/js/blob.js +18 -5
  5. package/demos/js/fluid-simple.js +253 -0
  6. package/demos/js/fluid.js +527 -0
  7. package/demos/js/tde/accretiondisk.js +64 -11
  8. package/demos/js/tde/blackholescene.js +2 -2
  9. package/demos/js/tde/config.js +2 -2
  10. package/demos/js/tde/index.js +152 -27
  11. package/demos/js/tde/lensedstarfield.js +32 -25
  12. package/demos/js/tde/tdestar.js +78 -98
  13. package/demos/js/tde/tidalstream.js +23 -7
  14. package/docs/README.md +230 -222
  15. package/docs/api/FluidSystem.md +173 -0
  16. package/docs/concepts/architecture-overview.md +204 -204
  17. package/docs/concepts/rendering-pipeline.md +279 -279
  18. package/docs/concepts/two-layer-architecture.md +229 -229
  19. package/docs/fluid-dynamics.md +97 -0
  20. package/docs/getting-started/first-game.md +354 -354
  21. package/docs/getting-started/installation.md +175 -157
  22. package/docs/modules/collision/README.md +2 -2
  23. package/docs/modules/fluent/README.md +6 -6
  24. package/docs/modules/game/README.md +303 -303
  25. package/docs/modules/isometric-camera.md +2 -2
  26. package/docs/modules/isometric.md +1 -1
  27. package/docs/modules/painter/README.md +328 -328
  28. package/docs/modules/particle/README.md +3 -3
  29. package/docs/modules/shapes/README.md +221 -221
  30. package/docs/modules/shapes/base/euclidian.md +123 -123
  31. package/docs/modules/shapes/base/shape.md +262 -262
  32. package/docs/modules/shapes/base/transformable.md +243 -243
  33. package/docs/modules/state/README.md +2 -2
  34. package/docs/modules/util/README.md +1 -1
  35. package/docs/modules/util/camera3d.md +3 -3
  36. package/docs/modules/util/scene3d.md +1 -1
  37. package/package.json +3 -1
  38. package/readme.md +19 -5
  39. package/src/collision/collision.js +75 -0
  40. package/src/game/index.js +2 -1
  41. package/src/game/pipeline.js +3 -3
  42. package/src/game/systems/FluidSystem.js +835 -0
  43. package/src/game/systems/index.js +11 -0
  44. package/src/game/ui/button.js +39 -18
  45. package/src/game/ui/cursor.js +14 -0
  46. package/src/game/ui/fps.js +12 -4
  47. package/src/game/ui/index.js +2 -0
  48. package/src/game/ui/stepper.js +549 -0
  49. package/src/game/ui/theme.js +121 -0
  50. package/src/game/ui/togglebutton.js +9 -3
  51. package/src/game/ui/tooltip.js +11 -4
  52. package/src/math/fluid.js +507 -0
  53. package/src/math/index.js +2 -0
  54. package/src/mixins/anchor.js +17 -7
  55. package/src/motion/tweenetik.js +16 -0
  56. package/src/shapes/index.js +1 -0
  57. package/src/util/camera3d.js +218 -12
  58. package/types/fluent.d.ts +361 -0
  59. package/types/game.d.ts +303 -0
  60. package/types/index.d.ts +144 -5
  61. package/types/math.d.ts +361 -0
  62. package/types/motion.d.ts +271 -0
  63. package/types/particle.d.ts +373 -0
  64. package/types/shapes.d.ts +107 -9
  65. package/types/util.d.ts +353 -0
  66. package/types/webgl.d.ts +109 -0
  67. package/disk_example.png +0 -0
  68. package/tde.png +0 -0
@@ -0,0 +1,373 @@
1
+ /// <reference lib="es2015" />
2
+
3
+ /**
4
+ * GCanvas Particle System Module
5
+ * High-performance particle system with optional Camera3D support.
6
+ * @module particle
7
+ */
8
+
9
+ import { GameObject, GameObjectOptions, Game } from './game';
10
+
11
+ // ==========================================================================
12
+ // Particle Class
13
+ // ==========================================================================
14
+
15
+ /** RGBA color object */
16
+ export interface ParticleColor {
17
+ r: number;
18
+ g: number;
19
+ b: number;
20
+ a: number;
21
+ }
22
+
23
+ /** Particle shape type */
24
+ export type ParticleShape = 'circle' | 'square' | 'triangle';
25
+
26
+ /**
27
+ * Lightweight data class for particle systems.
28
+ * Uses object pooling via reset() to minimize garbage collection.
29
+ *
30
+ * @example
31
+ * const p = new Particle();
32
+ * p.x = 100;
33
+ * p.y = 200;
34
+ * p.vx = 5;
35
+ * p.lifetime = 2;
36
+ */
37
+ export class Particle {
38
+ /** X position */
39
+ x: number;
40
+ /** Y position */
41
+ y: number;
42
+ /** Z position (for 3D systems) */
43
+ z: number;
44
+
45
+ /** X velocity */
46
+ vx: number;
47
+ /** Y velocity */
48
+ vy: number;
49
+ /** Z velocity */
50
+ vz: number;
51
+
52
+ /** Particle size */
53
+ size: number;
54
+ /** Particle color */
55
+ color: ParticleColor;
56
+ /** Particle shape */
57
+ shape: ParticleShape;
58
+
59
+ /** Current age in seconds */
60
+ age: number;
61
+ /** Maximum lifetime in seconds */
62
+ lifetime: number;
63
+ /** Whether particle is alive */
64
+ alive: boolean;
65
+
66
+ /** Custom data for domain-specific behaviors */
67
+ custom: Record<string, any>;
68
+
69
+ /** Progress through lifetime (0 = born, 1 = about to die) */
70
+ readonly progress: number;
71
+
72
+ constructor();
73
+
74
+ /** Reset all properties for object pooling */
75
+ reset(): void;
76
+ }
77
+
78
+ // ==========================================================================
79
+ // ParticleEmitter Class
80
+ // ==========================================================================
81
+
82
+ /** Options for ParticleEmitter */
83
+ export interface ParticleEmitterOptions {
84
+ /** Emission rate (particles per second) */
85
+ rate?: number;
86
+ /** Position X */
87
+ x?: number;
88
+ /** Position Y */
89
+ y?: number;
90
+ /** Position Z */
91
+ z?: number;
92
+ /** Position spread (randomness) */
93
+ spread?: { x?: number; y?: number; z?: number };
94
+ /** Initial velocity */
95
+ velocity?: { x?: number; y?: number; z?: number };
96
+ /** Velocity spread (randomness) */
97
+ velocitySpread?: { x?: number; y?: number; z?: number };
98
+ /** Particle size range [min, max] */
99
+ size?: [number, number];
100
+ /** Particle lifetime range [min, max] */
101
+ lifetime?: [number, number];
102
+ /** Particle color */
103
+ color?: ParticleColor | ((particle: Particle) => ParticleColor);
104
+ /** Particle shape */
105
+ shape?: ParticleShape;
106
+ /** Custom initializer function */
107
+ init?: (particle: Particle, emitter: ParticleEmitter) => void;
108
+ }
109
+
110
+ /**
111
+ * Emitter that spawns particles with configurable properties.
112
+ *
113
+ * @example
114
+ * const emitter = new ParticleEmitter({
115
+ * rate: 50,
116
+ * x: 400, y: 300,
117
+ * velocity: { x: 0, y: -100 },
118
+ * velocitySpread: { x: 50, y: 20 },
119
+ * lifetime: [1, 3],
120
+ * size: [2, 8],
121
+ * });
122
+ */
123
+ export class ParticleEmitter {
124
+ /** Whether emitter is active */
125
+ active: boolean;
126
+ /** Emission rate (particles per second) */
127
+ rate: number;
128
+ /** Emitter position X */
129
+ x: number;
130
+ /** Emitter position Y */
131
+ y: number;
132
+ /** Emitter position Z */
133
+ z: number;
134
+
135
+ constructor(options?: ParticleEmitterOptions);
136
+
137
+ /**
138
+ * Update emitter and return number of particles to spawn.
139
+ * @param dt - Delta time in seconds
140
+ * @returns Number of particles to spawn this frame
141
+ */
142
+ update(dt: number): number;
143
+
144
+ /**
145
+ * Initialize a particle with this emitter's settings.
146
+ * @param particle - Particle to initialize
147
+ */
148
+ emit(particle: Particle): void;
149
+
150
+ /** Start emitting */
151
+ start(): void;
152
+
153
+ /** Stop emitting */
154
+ stop(): void;
155
+
156
+ /** Burst spawn a specific number of particles */
157
+ burst(count: number): void;
158
+ }
159
+
160
+ // ==========================================================================
161
+ // ParticleSystem Class
162
+ // ==========================================================================
163
+
164
+ /** Options for ParticleSystem */
165
+ export interface ParticleSystemOptions extends GameObjectOptions {
166
+ /** Maximum active particles (default: 5000) */
167
+ maxParticles?: number;
168
+ /** Optional Camera3D for 3D projection */
169
+ camera?: any; // Camera3D
170
+ /** Enable depth sorting (requires camera) */
171
+ depthSort?: boolean;
172
+ /** Canvas blend mode (default: 'source-over') */
173
+ blendMode?: GlobalCompositeOperation;
174
+ /** Array of updater functions */
175
+ updaters?: ParticleUpdater[];
176
+ /** Position particles in world space */
177
+ worldSpace?: boolean;
178
+ }
179
+
180
+ /** Particle updater function signature */
181
+ export type ParticleUpdater = (particle: Particle, dt: number, system: ParticleSystem) => void;
182
+
183
+ /**
184
+ * High-performance particle management GameObject.
185
+ *
186
+ * @example
187
+ * const particles = new ParticleSystem(this, {
188
+ * camera: this.camera,
189
+ * depthSort: true,
190
+ * maxParticles: 3000,
191
+ * blendMode: 'screen',
192
+ * updaters: [Updaters.velocity, Updaters.lifetime, Updaters.gravity(150)],
193
+ * });
194
+ * particles.addEmitter('fountain', new ParticleEmitter({ rate: 50 }));
195
+ * this.pipeline.add(particles);
196
+ */
197
+ export class ParticleSystem extends GameObject {
198
+ /** Active particles */
199
+ particles: Particle[];
200
+ /** Object pool for recycled particles */
201
+ pool: Particle[];
202
+ /** Maximum particles allowed */
203
+ maxParticles: number;
204
+ /** Named emitters */
205
+ emitters: Map<string, ParticleEmitter>;
206
+ /** Optional Camera3D for 3D projection */
207
+ camera: any | null;
208
+ /** Whether to depth sort particles */
209
+ depthSort: boolean;
210
+ /** Updater functions */
211
+ updaters: ParticleUpdater[];
212
+ /** Canvas blend mode (set via options, not an accessor) */
213
+ readonly _blendMode: GlobalCompositeOperation;
214
+ /** Position in world space */
215
+ worldSpace: boolean;
216
+
217
+ /** Current particle count */
218
+ readonly particleCount: number;
219
+ /** Pool size (recycled particles ready for reuse) */
220
+ readonly poolSize: number;
221
+
222
+ constructor(game: Game, options?: ParticleSystemOptions);
223
+
224
+ /**
225
+ * Add an emitter to the system.
226
+ * @param name - Emitter identifier
227
+ * @param emitter - Emitter instance
228
+ */
229
+ addEmitter(name: string, emitter: ParticleEmitter): ParticleSystem;
230
+
231
+ /**
232
+ * Remove an emitter from the system.
233
+ * @param name - Emitter identifier
234
+ */
235
+ removeEmitter(name: string): ParticleSystem;
236
+
237
+ /**
238
+ * Get an emitter by name.
239
+ * @param name - Emitter identifier
240
+ */
241
+ getEmitter(name: string): ParticleEmitter | undefined;
242
+
243
+ /**
244
+ * Acquire a particle from pool or create new.
245
+ */
246
+ acquire(): Particle;
247
+
248
+ /**
249
+ * Release a particle back to pool.
250
+ * @param particle - Particle to release
251
+ */
252
+ release(particle: Particle): void;
253
+
254
+ /**
255
+ * Emit particles using an emitter.
256
+ * @param count - Number of particles to emit
257
+ * @param emitter - Emitter to use
258
+ */
259
+ emitParticles(count: number, emitter: ParticleEmitter): void;
260
+
261
+ /**
262
+ * Burst spawn particles.
263
+ * @param count - Number of particles
264
+ * @param emitterOrName - Emitter instance or name
265
+ */
266
+ burst(count: number, emitterOrName: ParticleEmitter | string): void;
267
+
268
+ /** Clear all particles and return them to pool */
269
+ clear(): void;
270
+
271
+ /**
272
+ * Draw a single particle (override for custom rendering).
273
+ * @param ctx - Canvas context
274
+ * @param p - Particle to draw
275
+ * @param x - Screen X position
276
+ * @param y - Screen Y position
277
+ * @param scale - Size scale factor
278
+ */
279
+ drawParticle(ctx: CanvasRenderingContext2D, p: Particle, x: number, y: number, scale: number): void;
280
+ }
281
+
282
+ // ==========================================================================
283
+ // Updaters
284
+ // ==========================================================================
285
+
286
+ /**
287
+ * Collection of composable particle updater functions.
288
+ *
289
+ * @example
290
+ * const system = new ParticleSystem(game, {
291
+ * updaters: [
292
+ * Updaters.velocity,
293
+ * Updaters.lifetime,
294
+ * Updaters.gravity(200),
295
+ * Updaters.fadeOut,
296
+ * Updaters.shrink,
297
+ * ]
298
+ * });
299
+ */
300
+ export namespace Updaters {
301
+ /** Apply velocity to position */
302
+ const velocity: ParticleUpdater;
303
+
304
+ /** Update age and kill expired particles */
305
+ const lifetime: ParticleUpdater;
306
+
307
+ /** Fade out alpha over lifetime */
308
+ const fadeOut: ParticleUpdater;
309
+
310
+ /** Shrink size over lifetime */
311
+ const shrink: ParticleUpdater;
312
+
313
+ /** Grow size over lifetime */
314
+ const grow: ParticleUpdater;
315
+
316
+ /**
317
+ * Apply gravity acceleration.
318
+ * @param strength - Gravity strength (pixels per second squared)
319
+ * @param axis - Axis to apply gravity ('y' by default)
320
+ */
321
+ function gravity(strength: number, axis?: 'x' | 'y' | 'z'): ParticleUpdater;
322
+
323
+ /**
324
+ * Apply friction/drag.
325
+ * @param factor - Friction factor (0-1, lower = more friction)
326
+ */
327
+ function friction(factor: number): ParticleUpdater;
328
+
329
+ /**
330
+ * Apply wind force.
331
+ * @param forceX - X force
332
+ * @param forceY - Y force
333
+ */
334
+ function wind(forceX: number, forceY: number): ParticleUpdater;
335
+
336
+ /**
337
+ * Constrain particles to bounds.
338
+ * @param bounds - Bounding box
339
+ * @param bounce - Bounce factor (0-1)
340
+ */
341
+ function bounds(bounds: { x: number; y: number; width: number; height: number }, bounce?: number): ParticleUpdater;
342
+
343
+ /**
344
+ * Color transition over lifetime.
345
+ * @param startColor - Starting color
346
+ * @param endColor - Ending color
347
+ */
348
+ function colorTransition(startColor: ParticleColor, endColor: ParticleColor): ParticleUpdater;
349
+
350
+ /**
351
+ * Attract/repel from a point.
352
+ * @param x - Attractor X position
353
+ * @param y - Attractor Y position
354
+ * @param strength - Attraction strength (negative = repel)
355
+ */
356
+ function attract(x: number, y: number, strength: number): ParticleUpdater;
357
+
358
+ /**
359
+ * Apply turbulence/noise to velocity.
360
+ * @param strength - Turbulence strength
361
+ * @param scale - Noise scale
362
+ */
363
+ function turbulence(strength: number, scale?: number): ParticleUpdater;
364
+
365
+ /**
366
+ * Orbital motion around a point.
367
+ * @param centerX - Center X
368
+ * @param centerY - Center Y
369
+ * @param speed - Angular speed
370
+ */
371
+ function orbital(centerX: number, centerY: number, speed: number): ParticleUpdater;
372
+ }
373
+
package/types/shapes.d.ts CHANGED
@@ -713,21 +713,56 @@ export class PatternRectangle extends Rectangle {
713
713
 
714
714
  /** Options for ImageShape */
715
715
  export interface ImageShapeOptions extends ShapeOptions {
716
- /** Image source URL */
717
- src?: string;
718
- /** Image element */
719
- image?: HTMLImageElement;
716
+ /** Anchor point for positioning (e.g., "center", "top-left") */
717
+ anchor?: string;
718
+ /** Enable image smoothing (default: true) */
719
+ smoothing?: boolean;
720
720
  }
721
721
 
722
+ /** Type for bitmap sources that ImageShape accepts */
723
+ export type BitmapSource = HTMLImageElement | HTMLCanvasElement | ImageBitmap | HTMLVideoElement | ImageData;
724
+
722
725
  /**
723
- * Image shape.
726
+ * Image shape for rendering arbitrary pixel buffers.
727
+ * Supports HTMLImageElement, HTMLCanvasElement, ImageBitmap, HTMLVideoElement, and ImageData.
728
+ *
729
+ * @example
730
+ * const data = Painter.img.getImageData(0, 0, 320, 200);
731
+ * const shape = new ImageShape(data, { x: 100, y: 50, anchor: "center" });
732
+ * scene.add(shape);
724
733
  */
725
734
  export class ImageShape extends Shape {
726
- constructor(options?: ImageShapeOptions);
735
+ /**
736
+ * Create an ImageShape.
737
+ * @param bitmap - Image source (HTMLImageElement, HTMLCanvasElement, ImageBitmap, HTMLVideoElement, or ImageData)
738
+ * @param options - Shape options including anchor and smoothing
739
+ */
740
+ constructor(bitmap: BitmapSource | null, options?: ImageShapeOptions);
741
+
742
+ /** The internal bitmap */
743
+ get bitmap(): BitmapSource | null;
744
+ set bitmap(v: BitmapSource | null);
745
+
746
+ /** Anchor position (e.g., "center", "top-left") */
747
+ anchor: string;
727
748
 
728
- /** The image element */
729
- get image(): HTMLImageElement | null;
730
- set image(v: HTMLImageElement | null);
749
+ /** Whether image smoothing is enabled */
750
+ smoothing: boolean;
751
+
752
+ /**
753
+ * Update the canvas buffer for ImageData sources.
754
+ * @param bitmap - ImageData to buffer
755
+ */
756
+ buffer(bitmap: ImageData): void;
757
+
758
+ /** Reset the image to an empty state */
759
+ reset(): void;
760
+
761
+ /**
762
+ * Set the anchor point.
763
+ * @param anchor - Anchor position string
764
+ */
765
+ setAnchor(anchor: string): void;
731
766
  }
732
767
 
733
768
  // ==========================================================================
@@ -801,6 +836,69 @@ export class Sphere extends Shape {
801
836
  constructor(radius: number, options?: ShapeOptions);
802
837
  }
803
838
 
839
+ /** Options for Sphere3D */
840
+ export interface Sphere3DOptions extends ShapeOptions {
841
+ /** Sphere radius */
842
+ radius?: number;
843
+ /** Number of latitude segments */
844
+ latSegments?: number;
845
+ /** Number of longitude segments */
846
+ lonSegments?: number;
847
+ /** Base color */
848
+ color?: string;
849
+ /** Light direction [x, y, z] */
850
+ lightDirection?: [number, number, number];
851
+ /** Ambient light intensity (0-1) */
852
+ ambientLight?: number;
853
+ /** Whether to use glow effect */
854
+ glow?: boolean;
855
+ /** Glow color */
856
+ glowColor?: string;
857
+ /** Glow intensity */
858
+ glowIntensity?: number;
859
+ /** Whether to use wireframe */
860
+ wireframe?: boolean;
861
+ /** Wireframe color */
862
+ wireframeColor?: string;
863
+ }
864
+
865
+ /**
866
+ * 3D sphere with Camera3D projection support.
867
+ * Renders a proper 3D sphere with lighting and optional effects.
868
+ *
869
+ * @example
870
+ * const sphere = new Sphere3D({
871
+ * x: 0, y: 0, z: 0,
872
+ * radius: 100,
873
+ * color: '#ff6600',
874
+ * glow: true
875
+ * });
876
+ */
877
+ export class Sphere3D extends Shape {
878
+ /** Sphere radius */
879
+ radius: number;
880
+ /** Z position in 3D space */
881
+ z: number;
882
+ /** Camera3D instance for projection */
883
+ camera: any;
884
+
885
+ constructor(options?: Sphere3DOptions);
886
+
887
+ /**
888
+ * Set the camera for 3D projection.
889
+ * @param camera - Camera3D instance
890
+ */
891
+ setCamera(camera: any): Sphere3D;
892
+
893
+ /**
894
+ * Set position in 3D space.
895
+ * @param x - X position
896
+ * @param y - Y position
897
+ * @param z - Z position
898
+ */
899
+ setPosition(x: number, y: number, z: number): Sphere3D;
900
+ }
901
+
804
902
  // ==========================================================================
805
903
  // Text Shapes
806
904
  // ==========================================================================