@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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Fluid System Demo (Simplified)</title>
|
|
7
|
+
<link rel="stylesheet" href="demos.css" />
|
|
8
|
+
<script src="./js/info-toggle.js"></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="info">
|
|
12
|
+
<strong>FluidSystem Demo</strong> — Simplified fluid simulation.<br/>
|
|
13
|
+
<span style="color:#CCC">
|
|
14
|
+
<li>Click to push particles, hover to attract</li>
|
|
15
|
+
<li>Switch between Liquid and Gas physics</li>
|
|
16
|
+
</span>
|
|
17
|
+
</div>
|
|
18
|
+
<canvas id="game"></canvas>
|
|
19
|
+
<script type="module" src="./js/fluid-simple.js"></script>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
|
22
|
+
|
package/demos/fluid.html
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Fluid & Gas Playground</title>
|
|
8
|
+
<link rel="stylesheet" href="demos.css" />
|
|
9
|
+
<script src="./js/info-toggle.js"></script>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<div id="info">
|
|
14
|
+
<strong>Fluid & Gas Playground</strong> — SPH-like liquid + lightweight gas using math-only helpers.<br />
|
|
15
|
+
<span style="color:#9ef">
|
|
16
|
+
<li>Move mouse to stir, hold click to push.</li>
|
|
17
|
+
<li>Press 1 for Liquid, 2 for Gas, Space toggles.</li>
|
|
18
|
+
<li>Gas mode: blue=cold (top), red=hot (bottom).</li>
|
|
19
|
+
<li>Drag the browser window to shake the bottle!</li>
|
|
20
|
+
</span>
|
|
21
|
+
</div>
|
|
22
|
+
<canvas id="game"></canvas>
|
|
23
|
+
|
|
24
|
+
<script type="module">
|
|
25
|
+
import { FluidGasGame } from "./js/fluid.js";
|
|
26
|
+
window.addEventListener("load", () => {
|
|
27
|
+
const canvas = document.getElementById("game");
|
|
28
|
+
const game = new FluidGasGame(canvas);
|
|
29
|
+
game.setFPS(60);
|
|
30
|
+
game.start();
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
33
|
+
</body>
|
|
34
|
+
|
|
35
|
+
</html>
|
|
36
|
+
|
|
37
|
+
|
package/demos/index.html
CHANGED
|
@@ -219,6 +219,8 @@
|
|
|
219
219
|
<a href="baskara.html" target="demo-frame">Root Dance</a>
|
|
220
220
|
<hr />
|
|
221
221
|
<h2 style="margin-bottom: 0.3em">Math & Physics</h2>
|
|
222
|
+
<a href="fluid.html" target="demo-frame">Fluid Playground</a>
|
|
223
|
+
<a href="fluid-simple.html" target="demo-frame">Fluid System</a>
|
|
222
224
|
<a href="schrodinger.html" target="demo-frame">Schrodinger Wave</a>
|
|
223
225
|
<a href="spacetime.html" target="demo-frame">Spacetime Curvature</a>
|
|
224
226
|
<a href="schwarzschild.html" target="demo-frame"
|
package/demos/js/blob.js
CHANGED
|
@@ -243,6 +243,7 @@ class BlobScene extends Scene {
|
|
|
243
243
|
// Set initial blob size (smaller)
|
|
244
244
|
this.blobPhysics.baseRadius = CONFIG.startRadius;
|
|
245
245
|
this.blobPhysics.currentRadius = CONFIG.startRadius;
|
|
246
|
+
this.blobPhysics.healthyRadius = CONFIG.startRadius; // Track healthy size before hunger effects
|
|
246
247
|
|
|
247
248
|
// Control points around the blob (in polar coordinates for easy animation)
|
|
248
249
|
this.blobPoints = [];
|
|
@@ -1095,11 +1096,16 @@ class BlobScene extends Scene {
|
|
|
1095
1096
|
this.gameState.lastEatTime = 0;
|
|
1096
1097
|
this.gameState.isHungry = false;
|
|
1097
1098
|
|
|
1098
|
-
// Grow the blob
|
|
1099
|
+
// Grow the blob - restore to healthy radius plus growth
|
|
1099
1100
|
const physics = this.blobPhysics;
|
|
1100
|
-
|
|
1101
|
+
// Ensure healthyRadius is initialized
|
|
1102
|
+
if (physics.healthyRadius === undefined) {
|
|
1103
|
+
physics.healthyRadius = physics.baseRadius;
|
|
1104
|
+
}
|
|
1105
|
+
const newRadius = Math.min(CONFIG.maxRadius, physics.healthyRadius + CONFIG.growthPerCollect);
|
|
1101
1106
|
physics.baseRadius = newRadius;
|
|
1102
1107
|
physics.currentRadius = newRadius;
|
|
1108
|
+
physics.healthyRadius = newRadius; // Update healthy radius to new size
|
|
1103
1109
|
|
|
1104
1110
|
// Also give energy boost
|
|
1105
1111
|
physics.energy = Math.min(1, physics.energy + 0.15);
|
|
@@ -1150,10 +1156,14 @@ class BlobScene extends Scene {
|
|
|
1150
1156
|
const wasHungry = this.gameState.isHungry;
|
|
1151
1157
|
this.gameState.isHungry = this.gameState.lastEatTime > hungerThreshold;
|
|
1152
1158
|
|
|
1153
|
-
// If just became hungry, show warning
|
|
1159
|
+
// If just became hungry, show warning and capture healthy radius
|
|
1154
1160
|
if (this.gameState.isHungry && !wasHungry) {
|
|
1155
1161
|
this.showFloatingText("HUNGRY!", this.game.width / 2, this.game.height / 2);
|
|
1156
1162
|
this.playHungryWarning();
|
|
1163
|
+
// Capture the current radius as the healthy radius when hunger starts
|
|
1164
|
+
if (physics.healthyRadius === undefined || physics.healthyRadius < physics.baseRadius) {
|
|
1165
|
+
physics.healthyRadius = physics.baseRadius;
|
|
1166
|
+
}
|
|
1157
1167
|
}
|
|
1158
1168
|
|
|
1159
1169
|
// If hungry, shrink and lose points
|
|
@@ -1169,7 +1179,7 @@ class BlobScene extends Scene {
|
|
|
1169
1179
|
const hungerMultiplier = 1 + Math.min(hungerDuration / 2, 1);
|
|
1170
1180
|
const shrinkAmount = shrinkRate * hungerMultiplier * dt;
|
|
1171
1181
|
|
|
1172
|
-
// Apply shrinking
|
|
1182
|
+
// Apply shrinking from healthy radius (but don't modify healthyRadius)
|
|
1173
1183
|
const newRadius = Math.max(CONFIG.minRadius, physics.baseRadius - shrinkAmount);
|
|
1174
1184
|
if (newRadius < physics.baseRadius) {
|
|
1175
1185
|
// Calculate score penalty
|
|
@@ -1177,7 +1187,7 @@ class BlobScene extends Scene {
|
|
|
1177
1187
|
const scorePenalty = Math.ceil(radiusLost * CONFIG.shrinkScorePenalty);
|
|
1178
1188
|
this.gameState.score = Math.max(0, this.gameState.score - scorePenalty);
|
|
1179
1189
|
|
|
1180
|
-
// Apply size reduction
|
|
1190
|
+
// Apply size reduction (healthyRadius stays unchanged)
|
|
1181
1191
|
physics.baseRadius = newRadius;
|
|
1182
1192
|
physics.currentRadius = newRadius;
|
|
1183
1193
|
}
|
|
@@ -1288,6 +1298,7 @@ class BlobScene extends Scene {
|
|
|
1288
1298
|
this.collectionParticles = [];
|
|
1289
1299
|
this.blobPhysics.baseRadius = CONFIG.startRadius;
|
|
1290
1300
|
this.blobPhysics.currentRadius = CONFIG.startRadius;
|
|
1301
|
+
this.blobPhysics.healthyRadius = CONFIG.startRadius;
|
|
1291
1302
|
// Reset color to normal
|
|
1292
1303
|
this.blobPhysics.currentColor = [...this.blobPhysics.baseColor];
|
|
1293
1304
|
// Reset pop sound scale
|
|
@@ -1357,6 +1368,7 @@ class BlobScene extends Scene {
|
|
|
1357
1368
|
// Reset physics
|
|
1358
1369
|
physics.baseRadius = CONFIG.startRadius;
|
|
1359
1370
|
physics.currentRadius = CONFIG.startRadius;
|
|
1371
|
+
physics.healthyRadius = CONFIG.startRadius;
|
|
1360
1372
|
physics.currentX = this.game.width / 2;
|
|
1361
1373
|
physics.currentY = this.game.height / 2;
|
|
1362
1374
|
physics.vx = 0;
|
|
@@ -2190,6 +2202,7 @@ class BlobUIScene extends Scene {
|
|
|
2190
2202
|
// Reset physics - use CONFIG for starting size
|
|
2191
2203
|
physics.baseRadius = CONFIG.startRadius;
|
|
2192
2204
|
physics.currentRadius = CONFIG.startRadius;
|
|
2205
|
+
physics.healthyRadius = CONFIG.startRadius;
|
|
2193
2206
|
physics.energy = 1.0;
|
|
2194
2207
|
physics.baseColor = [64, 180, 255];
|
|
2195
2208
|
physics.vx = 0;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simplified Fluid Demo using FluidSystem
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how the FluidSystem class dramatically reduces
|
|
5
|
+
* the boilerplate needed for fluid simulations.
|
|
6
|
+
*/
|
|
7
|
+
import {
|
|
8
|
+
Game,
|
|
9
|
+
FPSCounter,
|
|
10
|
+
FluidSystem,
|
|
11
|
+
applyAnchor,
|
|
12
|
+
Position,
|
|
13
|
+
Button,
|
|
14
|
+
ToggleButton,
|
|
15
|
+
HorizontalLayout,
|
|
16
|
+
} from "../../src/index.js";
|
|
17
|
+
|
|
18
|
+
const PARTICLE_SIZE = 32;
|
|
19
|
+
|
|
20
|
+
const CONFIG = {
|
|
21
|
+
particleSize: PARTICLE_SIZE,
|
|
22
|
+
maxParticles: 500,
|
|
23
|
+
gravity: 200,
|
|
24
|
+
container: {
|
|
25
|
+
marginX: 80,
|
|
26
|
+
marginY: 200,
|
|
27
|
+
strokeColor: "#22c55e",
|
|
28
|
+
strokeWidth: 2,
|
|
29
|
+
},
|
|
30
|
+
pointer: {
|
|
31
|
+
radius: PARTICLE_SIZE * 4,
|
|
32
|
+
push: 3000,
|
|
33
|
+
pull: 600,
|
|
34
|
+
},
|
|
35
|
+
ui: {
|
|
36
|
+
margin: 12,
|
|
37
|
+
width: 130,
|
|
38
|
+
height: 32,
|
|
39
|
+
spacing: 6,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Simplified fluid demo using FluidSystem.
|
|
45
|
+
*/
|
|
46
|
+
class FluidSimpleDemo extends Game {
|
|
47
|
+
constructor(canvas) {
|
|
48
|
+
super(canvas);
|
|
49
|
+
this.backgroundColor = "#0f172a";
|
|
50
|
+
this.enableFluidSize();
|
|
51
|
+
this.pointer = { x: 0, y: 0, down: false };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
init() {
|
|
55
|
+
super.init();
|
|
56
|
+
|
|
57
|
+
// Create container bounds
|
|
58
|
+
this._updateBounds();
|
|
59
|
+
|
|
60
|
+
// Create FluidSystem - ALL the physics is handled internally!
|
|
61
|
+
this.fluid = new FluidSystem(this, {
|
|
62
|
+
maxParticles: CONFIG.maxParticles,
|
|
63
|
+
particleSize: CONFIG.particleSize,
|
|
64
|
+
width: this.bounds.w,
|
|
65
|
+
height: this.bounds.h,
|
|
66
|
+
bounds: this.bounds,
|
|
67
|
+
physics: "liquid",
|
|
68
|
+
debug: true,
|
|
69
|
+
debugColor: CONFIG.container.strokeColor,
|
|
70
|
+
gravity: CONFIG.gravity,
|
|
71
|
+
particleColor: { r: 80, g: 180, b: 255, a: 0.9 },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Spawn particles
|
|
75
|
+
this.fluid.spawn(CONFIG.maxParticles);
|
|
76
|
+
|
|
77
|
+
this.pipeline.add(this.fluid);
|
|
78
|
+
|
|
79
|
+
// Build UI controls
|
|
80
|
+
this._buildUI();
|
|
81
|
+
|
|
82
|
+
// FPS counter
|
|
83
|
+
this.pipeline.add(
|
|
84
|
+
new FPSCounter(this, { color: "#6af", anchor: "top-right" })
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Mouse interaction
|
|
88
|
+
this._setupInteraction();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Build the UI control bar.
|
|
93
|
+
*/
|
|
94
|
+
_buildUI() {
|
|
95
|
+
const { margin, width, height, spacing } = CONFIG.ui;
|
|
96
|
+
|
|
97
|
+
// Create horizontal layout for buttons, anchored to bottom left
|
|
98
|
+
const uiPanel = new HorizontalLayout(this, {
|
|
99
|
+
width: width * 3 + spacing * 2,
|
|
100
|
+
height: height,
|
|
101
|
+
spacing,
|
|
102
|
+
padding: 0,
|
|
103
|
+
align: "center",
|
|
104
|
+
});
|
|
105
|
+
applyAnchor(uiPanel, {
|
|
106
|
+
anchor: Position.BOTTOM_LEFT,
|
|
107
|
+
anchorMargin: margin,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
this.btnMode = new ToggleButton(this, {
|
|
111
|
+
width,
|
|
112
|
+
height,
|
|
113
|
+
text: "Mode: Liquid",
|
|
114
|
+
startToggled: false,
|
|
115
|
+
onToggle: (on) => {
|
|
116
|
+
this.fluid.setPhysicsMode(on ? "gas" : "liquid");
|
|
117
|
+
this.btnMode.text = on ? "Mode: Gas" : "Mode: Liquid";
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
uiPanel.add(this.btnMode);
|
|
121
|
+
|
|
122
|
+
this.btnGravity = new ToggleButton(this, {
|
|
123
|
+
width,
|
|
124
|
+
height,
|
|
125
|
+
text: "Gravity: On",
|
|
126
|
+
startToggled: true,
|
|
127
|
+
onToggle: (on) => {
|
|
128
|
+
this.fluid.gravityEnabled = on;
|
|
129
|
+
this.btnGravity.text = on ? "Gravity: On" : "Gravity: Off";
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
uiPanel.add(this.btnGravity);
|
|
133
|
+
|
|
134
|
+
this.btnReset = new Button(this, {
|
|
135
|
+
width,
|
|
136
|
+
height,
|
|
137
|
+
text: "Reset",
|
|
138
|
+
onClick: () => this.fluid.reset(),
|
|
139
|
+
});
|
|
140
|
+
uiPanel.add(this.btnReset);
|
|
141
|
+
|
|
142
|
+
this.pipeline.add(uiPanel);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
_updateBounds() {
|
|
146
|
+
const { marginX, marginY } = CONFIG.container;
|
|
147
|
+
this.bounds = {
|
|
148
|
+
x: marginX,
|
|
149
|
+
y: marginY,
|
|
150
|
+
w: this.width - marginX * 2,
|
|
151
|
+
h: this.height - marginY * 2,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
onResize() {
|
|
156
|
+
this._updateBounds();
|
|
157
|
+
if (this.fluid) {
|
|
158
|
+
this.fluid.setBounds(this.bounds);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_setupInteraction() {
|
|
163
|
+
// Track pointer position and state
|
|
164
|
+
this.events.on("inputmove", (e) => {
|
|
165
|
+
this.pointer.x = e.x;
|
|
166
|
+
this.pointer.y = e.y;
|
|
167
|
+
});
|
|
168
|
+
this.events.on("inputdown", () => (this.pointer.down = true));
|
|
169
|
+
this.events.on("inputup", () => (this.pointer.down = false));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Apply continuous pointer forces to particles.
|
|
174
|
+
* Push when clicking, gentle pull when hovering.
|
|
175
|
+
* @param {number} dt - Delta time
|
|
176
|
+
*/
|
|
177
|
+
_applyPointerForces(dt) {
|
|
178
|
+
const { radius, push, pull } = CONFIG.pointer;
|
|
179
|
+
const r2 = radius * radius;
|
|
180
|
+
const mx = this.pointer.x;
|
|
181
|
+
const my = this.pointer.y;
|
|
182
|
+
|
|
183
|
+
for (const p of this.fluid.particles) {
|
|
184
|
+
const dx = mx - p.x;
|
|
185
|
+
const dy = my - p.y;
|
|
186
|
+
const dist2 = dx * dx + dy * dy;
|
|
187
|
+
|
|
188
|
+
if (dist2 >= r2 || dist2 < 1) continue;
|
|
189
|
+
|
|
190
|
+
const dist = Math.sqrt(dist2);
|
|
191
|
+
const t = 1 - dist / radius;
|
|
192
|
+
const strength = (this.pointer.down ? push : -pull) * t * t;
|
|
193
|
+
|
|
194
|
+
p.vx += (dx / dist) * strength * dt;
|
|
195
|
+
p.vy += (dy / dist) * strength * dt;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
update(dt) {
|
|
200
|
+
// Apply pointer forces continuously
|
|
201
|
+
this._applyPointerForces(dt);
|
|
202
|
+
|
|
203
|
+
super.update(dt);
|
|
204
|
+
this._colorByVelocity();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Color particles by velocity (Sebastian Lague style).
|
|
209
|
+
*/
|
|
210
|
+
_colorByVelocity() {
|
|
211
|
+
const maxSpeed = 300;
|
|
212
|
+
|
|
213
|
+
for (const p of this.fluid.particles) {
|
|
214
|
+
const speed = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
|
|
215
|
+
const t = Math.min(1, speed / maxSpeed);
|
|
216
|
+
|
|
217
|
+
// Blue (slow) -> Cyan -> Green -> Yellow -> Orange (fast)
|
|
218
|
+
const hue = 210 - t * 180;
|
|
219
|
+
const sat = 80;
|
|
220
|
+
const light = 50 + t * 15;
|
|
221
|
+
|
|
222
|
+
// Simple HSL to RGB approximation
|
|
223
|
+
const c = ((1 - Math.abs((2 * light) / 100 - 1)) * sat) / 100;
|
|
224
|
+
const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));
|
|
225
|
+
const m = light / 100 - c / 2;
|
|
226
|
+
|
|
227
|
+
let r, g, b;
|
|
228
|
+
if (hue < 60) {
|
|
229
|
+
r = c; g = x; b = 0;
|
|
230
|
+
} else if (hue < 120) {
|
|
231
|
+
r = x; g = c; b = 0;
|
|
232
|
+
} else if (hue < 180) {
|
|
233
|
+
r = 0; g = c; b = x;
|
|
234
|
+
} else if (hue < 240) {
|
|
235
|
+
r = 0; g = x; b = c;
|
|
236
|
+
} else if (hue < 300) {
|
|
237
|
+
r = x; g = 0; b = c;
|
|
238
|
+
} else {
|
|
239
|
+
r = c; g = 0; b = x;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
p.color.r = Math.round((r + m) * 255);
|
|
243
|
+
p.color.g = Math.round((g + m) * 255);
|
|
244
|
+
p.color.b = Math.round((b + m) * 255);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
window.addEventListener("load", () => {
|
|
250
|
+
const canvas = document.getElementById("game");
|
|
251
|
+
const demo = new FluidSimpleDemo(canvas);
|
|
252
|
+
demo.start();
|
|
253
|
+
});
|