@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
@@ -77,6 +77,81 @@ export class Collision {
77
77
  return distSq <= radii * radii;
78
78
  }
79
79
 
80
+ /**
81
+ * Get circle-circle overlap info for collision response.
82
+ * Returns separation vector and overlap amount.
83
+ *
84
+ * @param {Object} a - First circle { x, y, radius }
85
+ * @param {Object} b - Second circle { x, y, radius }
86
+ * @returns {Object|null} { overlap, nx, ny, dist } or null if no collision
87
+ * - overlap: penetration depth
88
+ * - nx, ny: normalized direction from b to a
89
+ * - dist: distance between centers
90
+ */
91
+ static getCircleOverlap(a, b) {
92
+ const dx = a.x - b.x;
93
+ const dy = a.y - b.y;
94
+ const distSq = dx * dx + dy * dy;
95
+ const minDist = a.radius + b.radius;
96
+
97
+ if (distSq >= minDist * minDist || distSq < 0.0001) {
98
+ return null;
99
+ }
100
+
101
+ const dist = Math.sqrt(distSq);
102
+ const overlap = minDist - dist;
103
+ const invDist = 1 / dist;
104
+
105
+ return {
106
+ overlap,
107
+ nx: dx * invDist, // Normal from b toward a
108
+ ny: dy * invDist,
109
+ dist,
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Apply separation forces between overlapping circles.
115
+ * Mutates the provided force arrays.
116
+ *
117
+ * @param {Array<Object>} particles - Array of { x, y, size } particles
118
+ * @param {Array<Object>} forces - Array of { x, y } force accumulators
119
+ * @param {Object} [options={}] - Options
120
+ * @param {number} [options.strength=5000] - Repulsion force strength
121
+ * @param {boolean} [options.useSizeAsRadius=true] - Use particle.size as diameter
122
+ */
123
+ static applyCircleSeparation(particles, forces, options = {}) {
124
+ const strength = options.strength ?? 5000;
125
+ const useSizeAsRadius = options.useSizeAsRadius ?? true;
126
+ const n = particles.length;
127
+
128
+ for (let i = 0; i < n; i++) {
129
+ const pi = particles[i];
130
+ const ri = useSizeAsRadius ? pi.size * 0.5 : (pi.radius ?? 10);
131
+
132
+ for (let j = i + 1; j < n; j++) {
133
+ const pj = particles[j];
134
+ const rj = useSizeAsRadius ? pj.size * 0.5 : (pj.radius ?? 10);
135
+
136
+ const overlap = Collision.getCircleOverlap(
137
+ { x: pi.x, y: pi.y, radius: ri },
138
+ { x: pj.x, y: pj.y, radius: rj }
139
+ );
140
+
141
+ if (overlap) {
142
+ const force = strength * (overlap.overlap / (ri + rj));
143
+ const fx = overlap.nx * force;
144
+ const fy = overlap.ny * force;
145
+
146
+ forces[i].x += fx;
147
+ forces[i].y += fy;
148
+ forces[j].x -= fx;
149
+ forces[j].y -= fy;
150
+ }
151
+ }
152
+ }
153
+ }
154
+
80
155
  /**
81
156
  * Test if a point is inside a circle
82
157
  *
package/src/game/index.js CHANGED
@@ -46,4 +46,5 @@
46
46
  export { Game } from "./game.js";
47
47
  export { Pipeline } from "./pipeline.js";
48
48
  export * from "./objects";
49
- export * from "./ui";
49
+ export * from "./ui";
50
+ export * from "./systems";
@@ -52,7 +52,6 @@ export class Pipeline extends Loggable {
52
52
  * @private
53
53
  */
54
54
  _hoverObject(obj, e) {
55
- //console.log("hoverObject", obj.constructor.name, obj.interactive, obj._hitTest != null);
56
55
  // Only applies to interactive objects with a shape and a _hitTest method.
57
56
  if (!obj.interactive || !obj._hitTest) return;
58
57
  const hit = obj._hitTest(e.x, e.y);
@@ -60,7 +59,6 @@ export class Pipeline extends Loggable {
60
59
  // Pointer entered this object
61
60
  obj._hovered = true;
62
61
  obj.events.emit("mouseover", e);
63
- //this.logger.log("Mouseover", obj, e.x, e.y);
64
62
  } else if (!hit && obj._hovered) {
65
63
  // Pointer left this object
66
64
  obj._hovered = false;
@@ -75,6 +73,9 @@ export class Pipeline extends Loggable {
75
73
  * @private
76
74
  */
77
75
  _hoverScene(scene, e) {
76
+ if (!scene.children || scene.children.length === 0) {
77
+ return;
78
+ }
78
79
  for (let i = scene.children.length - 1; i >= 0; i--) {
79
80
  const child = scene.children[i];
80
81
  if (child instanceof Scene) {
@@ -130,7 +131,6 @@ export class Pipeline extends Loggable {
130
131
  // Check from topmost to bottommost for hover changes.
131
132
  for (let i = this.gameObjects.length - 1; i >= 0; i--) {
132
133
  const obj = this.gameObjects[i];
133
- //this.logger.log("Hover test for", obj, e.x, e.y);
134
134
  if (obj instanceof Scene) {
135
135
  this._hoverScene(obj, e);
136
136
  } else {