@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.
- package/demos/fluid-simple.html +22 -0
- package/demos/fluid.html +37 -0
- package/demos/index.html +2 -0
- package/demos/js/blob.js +18 -5
- package/demos/js/fluid-simple.js +253 -0
- package/demos/js/fluid.js +527 -0
- package/demos/js/tde/accretiondisk.js +64 -11
- package/demos/js/tde/blackholescene.js +2 -2
- package/demos/js/tde/config.js +2 -2
- package/demos/js/tde/index.js +152 -27
- package/demos/js/tde/lensedstarfield.js +32 -25
- package/demos/js/tde/tdestar.js +78 -98
- package/demos/js/tde/tidalstream.js +23 -7
- package/docs/README.md +230 -222
- package/docs/api/FluidSystem.md +173 -0
- package/docs/concepts/architecture-overview.md +204 -204
- package/docs/concepts/rendering-pipeline.md +279 -279
- package/docs/concepts/two-layer-architecture.md +229 -229
- package/docs/fluid-dynamics.md +97 -0
- package/docs/getting-started/first-game.md +354 -354
- package/docs/getting-started/installation.md +175 -157
- package/docs/modules/collision/README.md +2 -2
- package/docs/modules/fluent/README.md +6 -6
- package/docs/modules/game/README.md +303 -303
- package/docs/modules/isometric-camera.md +2 -2
- package/docs/modules/isometric.md +1 -1
- package/docs/modules/painter/README.md +328 -328
- package/docs/modules/particle/README.md +3 -3
- package/docs/modules/shapes/README.md +221 -221
- package/docs/modules/shapes/base/euclidian.md +123 -123
- package/docs/modules/shapes/base/shape.md +262 -262
- package/docs/modules/shapes/base/transformable.md +243 -243
- package/docs/modules/state/README.md +2 -2
- package/docs/modules/util/README.md +1 -1
- package/docs/modules/util/camera3d.md +3 -3
- package/docs/modules/util/scene3d.md +1 -1
- package/package.json +3 -1
- package/readme.md +19 -5
- package/src/collision/collision.js +75 -0
- package/src/game/index.js +2 -1
- package/src/game/pipeline.js +3 -3
- package/src/game/systems/FluidSystem.js +835 -0
- package/src/game/systems/index.js +11 -0
- package/src/game/ui/button.js +39 -18
- package/src/game/ui/cursor.js +14 -0
- package/src/game/ui/fps.js +12 -4
- package/src/game/ui/index.js +2 -0
- package/src/game/ui/stepper.js +549 -0
- package/src/game/ui/theme.js +121 -0
- package/src/game/ui/togglebutton.js +9 -3
- package/src/game/ui/tooltip.js +11 -4
- package/src/math/fluid.js +507 -0
- package/src/math/index.js +2 -0
- package/src/mixins/anchor.js +17 -7
- package/src/motion/tweenetik.js +16 -0
- package/src/shapes/index.js +1 -0
- package/src/util/camera3d.js +218 -12
- package/types/fluent.d.ts +361 -0
- package/types/game.d.ts +303 -0
- package/types/index.d.ts +144 -5
- package/types/math.d.ts +361 -0
- package/types/motion.d.ts +271 -0
- package/types/particle.d.ts +373 -0
- package/types/shapes.d.ts +107 -9
- package/types/util.d.ts +353 -0
- package/types/webgl.d.ts +109 -0
- package/disk_example.png +0 -0
- 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
package/src/game/pipeline.js
CHANGED
|
@@ -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 {
|