@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.
- package/dist/gcanvas.es.js +25656 -0
- package/dist/gcanvas.es.min.js +1 -0
- package/dist/gcanvas.umd.js +1 -0
- package/dist/gcanvas.umd.min.js +1 -0
- package/package.json +23 -6
- package/src/game/objects/index.js +1 -0
- package/src/game/objects/spritesheet.js +260 -0
- package/src/game/ui/theme.js +6 -0
- package/src/io/keys.js +9 -1
- package/src/math/boolean.js +481 -0
- package/src/math/index.js +1 -0
- package/.github/workflows/release.yaml +0 -70
- package/.jshintrc +0 -4
- package/.vscode/settings.json +0 -22
- package/CLAUDE.md +0 -310
- package/blackhole.jpg +0 -0
- package/demo.png +0 -0
- package/demos/CNAME +0 -1
- package/demos/animations.html +0 -31
- package/demos/basic.html +0 -38
- package/demos/baskara.html +0 -31
- package/demos/bezier.html +0 -35
- package/demos/beziersignature.html +0 -29
- package/demos/blackhole.html +0 -28
- package/demos/blob.html +0 -35
- package/demos/coordinates.html +0 -698
- package/demos/cube3d.html +0 -23
- package/demos/demos.css +0 -303
- package/demos/dino.html +0 -42
- package/demos/easing.html +0 -28
- package/demos/events.html +0 -195
- package/demos/fluent.html +0 -647
- package/demos/fluid-simple.html +0 -22
- package/demos/fluid.html +0 -37
- package/demos/fractals.html +0 -36
- package/demos/gameobjects.html +0 -626
- package/demos/genart.html +0 -26
- package/demos/gendream.html +0 -26
- package/demos/group.html +0 -36
- package/demos/home.html +0 -587
- package/demos/index.html +0 -376
- package/demos/isometric.html +0 -34
- package/demos/js/animations.js +0 -452
- package/demos/js/basic.js +0 -204
- package/demos/js/baskara.js +0 -751
- package/demos/js/bezier.js +0 -692
- package/demos/js/beziersignature.js +0 -241
- package/demos/js/blackhole/accretiondisk.obj.js +0 -379
- package/demos/js/blackhole/blackhole.obj.js +0 -318
- package/demos/js/blackhole/index.js +0 -409
- package/demos/js/blackhole/particle.js +0 -56
- package/demos/js/blackhole/starfield.obj.js +0 -218
- package/demos/js/blob.js +0 -2276
- package/demos/js/coordinates.js +0 -840
- package/demos/js/cube3d.js +0 -789
- package/demos/js/dino.js +0 -1420
- package/demos/js/easing.js +0 -477
- package/demos/js/fluent.js +0 -183
- package/demos/js/fluid-simple.js +0 -253
- package/demos/js/fluid.js +0 -527
- package/demos/js/fractals.js +0 -931
- package/demos/js/fractalworker.js +0 -93
- package/demos/js/gameobjects.js +0 -176
- package/demos/js/genart.js +0 -268
- package/demos/js/gendream.js +0 -209
- package/demos/js/group.js +0 -140
- package/demos/js/info-toggle.js +0 -25
- package/demos/js/isometric.js +0 -863
- package/demos/js/kerr.js +0 -1556
- package/demos/js/lavalamp.js +0 -590
- package/demos/js/layout.js +0 -354
- package/demos/js/mondrian.js +0 -285
- package/demos/js/opacity.js +0 -275
- package/demos/js/painter.js +0 -484
- package/demos/js/particles-showcase.js +0 -514
- package/demos/js/particles.js +0 -299
- package/demos/js/patterns.js +0 -397
- package/demos/js/penrose/artifact.js +0 -69
- package/demos/js/penrose/blackhole.js +0 -121
- package/demos/js/penrose/constants.js +0 -73
- package/demos/js/penrose/game.js +0 -943
- package/demos/js/penrose/lore.js +0 -278
- package/demos/js/penrose/penrosescene.js +0 -892
- package/demos/js/penrose/ship.js +0 -216
- package/demos/js/penrose/sounds.js +0 -211
- package/demos/js/penrose/voidparticle.js +0 -55
- package/demos/js/penrose/voidscene.js +0 -258
- package/demos/js/penrose/voidship.js +0 -144
- package/demos/js/penrose/wormhole.js +0 -46
- package/demos/js/pipeline.js +0 -555
- package/demos/js/plane3d.js +0 -256
- package/demos/js/platformer.js +0 -1579
- package/demos/js/scene.js +0 -304
- package/demos/js/scenes.js +0 -320
- package/demos/js/schrodinger.js +0 -410
- package/demos/js/schwarzschild.js +0 -1023
- package/demos/js/shapes.js +0 -628
- package/demos/js/space/alien.js +0 -171
- package/demos/js/space/boom.js +0 -98
- package/demos/js/space/boss.js +0 -353
- package/demos/js/space/buff.js +0 -73
- package/demos/js/space/bullet.js +0 -102
- package/demos/js/space/constants.js +0 -85
- package/demos/js/space/game.js +0 -1884
- package/demos/js/space/hud.js +0 -112
- package/demos/js/space/laserbeam.js +0 -179
- package/demos/js/space/lightning.js +0 -277
- package/demos/js/space/minion.js +0 -192
- package/demos/js/space/missile.js +0 -212
- package/demos/js/space/player.js +0 -430
- package/demos/js/space/powerup.js +0 -90
- package/demos/js/space/starfield.js +0 -58
- package/demos/js/space/starpower.js +0 -90
- package/demos/js/spacetime.js +0 -559
- package/demos/js/sphere3d.js +0 -229
- package/demos/js/sprite.js +0 -473
- package/demos/js/svgtween.js +0 -204
- package/demos/js/tde/accretiondisk.js +0 -471
- package/demos/js/tde/blackhole.js +0 -219
- package/demos/js/tde/blackholescene.js +0 -209
- package/demos/js/tde/config.js +0 -59
- package/demos/js/tde/index.js +0 -820
- package/demos/js/tde/jets.js +0 -290
- package/demos/js/tde/lensedstarfield.js +0 -154
- package/demos/js/tde/tdestar.js +0 -297
- package/demos/js/tde/tidalstream.js +0 -372
- package/demos/js/tde_old/blackhole.obj.js +0 -354
- package/demos/js/tde_old/debris.obj.js +0 -791
- package/demos/js/tde_old/flare.obj.js +0 -239
- package/demos/js/tde_old/index.js +0 -448
- package/demos/js/tde_old/star.obj.js +0 -812
- package/demos/js/tiles.js +0 -312
- package/demos/js/tweendemo.js +0 -79
- package/demos/js/visibility.js +0 -102
- package/demos/kerr.html +0 -28
- package/demos/lavalamp.html +0 -27
- package/demos/layouts.html +0 -37
- package/demos/logo.svg +0 -4
- package/demos/loop.html +0 -84
- package/demos/mondrian.html +0 -32
- package/demos/og_image.png +0 -0
- package/demos/opacity.html +0 -36
- package/demos/painter.html +0 -39
- package/demos/particles-showcase.html +0 -28
- package/demos/particles.html +0 -24
- package/demos/patterns.html +0 -33
- package/demos/penrose-game.html +0 -31
- package/demos/pipeline.html +0 -737
- package/demos/plane3d.html +0 -24
- package/demos/platformer.html +0 -43
- package/demos/scene.html +0 -33
- package/demos/scenes.html +0 -96
- package/demos/schrodinger.html +0 -27
- package/demos/schwarzschild.html +0 -27
- package/demos/shapes.html +0 -16
- package/demos/space.html +0 -85
- package/demos/spacetime.html +0 -27
- package/demos/sphere3d.html +0 -24
- package/demos/sprite.html +0 -18
- package/demos/svgtween.html +0 -29
- package/demos/tde.html +0 -28
- package/demos/tiles.html +0 -28
- package/demos/transforms.html +0 -400
- package/demos/tween.html +0 -45
- package/demos/visibility.html +0 -33
- package/docs/README.md +0 -230
- package/docs/api/FluidSystem.md +0 -173
- package/docs/concepts/architecture-overview.md +0 -204
- package/docs/concepts/coordinate-system.md +0 -384
- package/docs/concepts/lifecycle.md +0 -255
- package/docs/concepts/rendering-pipeline.md +0 -279
- package/docs/concepts/shapes-vs-gameobjects.md +0 -187
- package/docs/concepts/tde-zorder.md +0 -106
- package/docs/concepts/two-layer-architecture.md +0 -229
- package/docs/fluid-dynamics.md +0 -99
- package/docs/getting-started/first-game.md +0 -354
- package/docs/getting-started/hello-world.md +0 -269
- package/docs/getting-started/installation.md +0 -175
- package/docs/modules/collision/README.md +0 -453
- package/docs/modules/fluent/README.md +0 -1075
- package/docs/modules/game/README.md +0 -303
- package/docs/modules/isometric-camera.md +0 -210
- package/docs/modules/isometric.md +0 -275
- package/docs/modules/painter/README.md +0 -328
- package/docs/modules/particle/README.md +0 -559
- package/docs/modules/shapes/README.md +0 -221
- package/docs/modules/shapes/base/euclidian.md +0 -123
- package/docs/modules/shapes/base/geometry2d.md +0 -204
- package/docs/modules/shapes/base/renderable.md +0 -215
- package/docs/modules/shapes/base/shape.md +0 -262
- package/docs/modules/shapes/base/transformable.md +0 -243
- package/docs/modules/shapes/hierarchy.md +0 -218
- package/docs/modules/state/README.md +0 -577
- package/docs/modules/util/README.md +0 -99
- package/docs/modules/util/camera3d.md +0 -412
- package/docs/modules/util/scene3d.md +0 -395
- package/index.html +0 -17
- package/jsdoc.json +0 -50
- package/scripts/build-demo.js +0 -69
- package/scripts/bundle4llm.js +0 -276
- package/scripts/clearconsole.js +0 -48
- package/test/math/orbital.test.js +0 -61
- package/test/math/tensor.test.js +0 -114
- package/test/particle/emitter.test.js +0 -204
- package/test/particle/particle-system.test.js +0 -310
- package/test/particle/particle.test.js +0 -116
- package/test/particle/updaters.test.js +0 -386
- package/test/setup.js +0 -120
- package/test/shapes/euclidian.test.js +0 -44
- package/test/shapes/geometry.test.js +0 -86
- package/test/shapes/group.test.js +0 -86
- package/test/shapes/rectangle.test.js +0 -64
- package/test/shapes/transform.test.js +0 -379
- package/test/util/camera3d.test.js +0 -428
- package/test/util/scene3d.test.js +0 -352
- package/vite.config.js +0 -50
- package/vitest.config.js +0 -13
package/demos/js/schrodinger.js
DELETED
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schrodinger Wave Packet - Math & Physics Demo
|
|
3
|
-
*
|
|
4
|
-
* 3D visualization of a Gaussian wave packet showing the complex
|
|
5
|
-
* wave function as a helix/spiral traveling through space.
|
|
6
|
-
*
|
|
7
|
-
* Ψ(x,t) = A * e^(-(x-vt)²/4a²) * e^(i(kx-ωt))
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { Game, Painter, Camera3D, Text, applyAnchor, Position, Scene, verticalLayout, applyLayout } from "../../src/index.js";
|
|
11
|
-
import { gaussianWavePacket } from "../../src/math/quantum.js";
|
|
12
|
-
|
|
13
|
-
// Configuration
|
|
14
|
-
const CONFIG = {
|
|
15
|
-
// Wave packet parameters
|
|
16
|
-
amplitude: 1.0,
|
|
17
|
-
sigma: 0.8, // Width of Gaussian envelope
|
|
18
|
-
k: 8.0, // Wave number (controls oscillation frequency)
|
|
19
|
-
omega: 4.0, // Angular frequency
|
|
20
|
-
velocity: 0.5, // Group velocity of packet
|
|
21
|
-
|
|
22
|
-
// Visualization
|
|
23
|
-
numPoints: 300, // Points along the wave
|
|
24
|
-
xRange: 12, // Total x range (-xRange/2 to +xRange/2)
|
|
25
|
-
helixRadius: 80, // Radius of the helix (Re/Im amplitude)
|
|
26
|
-
zScale: 40, // Scale for z-axis (position)
|
|
27
|
-
|
|
28
|
-
// 3D view
|
|
29
|
-
rotationX: 0.3, // Tilt angle
|
|
30
|
-
rotationY: -0.4, // Side rotation
|
|
31
|
-
perspective: 800, // Perspective depth
|
|
32
|
-
|
|
33
|
-
// Grid
|
|
34
|
-
gridSize: 16, // Grid lines count
|
|
35
|
-
gridSpacing: 30, // Spacing between grid lines
|
|
36
|
-
gridY: 120, // Y offset for grid plane
|
|
37
|
-
|
|
38
|
-
// Animation
|
|
39
|
-
timeScale: 1.0,
|
|
40
|
-
|
|
41
|
-
// Colors
|
|
42
|
-
waveColor: [80, 160, 255], // Cyan-blue for the helix
|
|
43
|
-
waveGlow: [150, 200, 255], // Brighter for the center
|
|
44
|
-
gridColor: "rgba(60, 80, 120, 0.4)",
|
|
45
|
-
axisColor: "rgba(100, 150, 200, 0.6)",
|
|
46
|
-
envelopeColor: "rgba(255, 100, 100, 0.5)", // Red envelope line
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
class SchrodingerDemo extends Game {
|
|
50
|
-
constructor(canvas) {
|
|
51
|
-
super(canvas);
|
|
52
|
-
this.backgroundColor = "#000000";
|
|
53
|
-
this.enableFluidSize();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
init() {
|
|
57
|
-
super.init();
|
|
58
|
-
this.time = 0;
|
|
59
|
-
|
|
60
|
-
// Create 3D camera with mouse controls
|
|
61
|
-
this.camera = new Camera3D({
|
|
62
|
-
rotationX: CONFIG.rotationX,
|
|
63
|
-
rotationY: CONFIG.rotationY,
|
|
64
|
-
perspective: CONFIG.perspective,
|
|
65
|
-
minRotationX: -1.2,
|
|
66
|
-
maxRotationX: 1.2,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Enable mouse/touch rotation
|
|
70
|
-
this.camera.enableMouseControl(this.canvas);
|
|
71
|
-
|
|
72
|
-
// Override double-click to also reset time
|
|
73
|
-
this.canvas.addEventListener("dblclick", () => {
|
|
74
|
-
this.time = 0;
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Create info panel container anchored to top center
|
|
78
|
-
this.infoPanel = new Scene(this, { x: 0, y: 0 });
|
|
79
|
-
applyAnchor(this.infoPanel, {
|
|
80
|
-
anchor: Position.TOP_CENTER,
|
|
81
|
-
anchorOffsetY: 150,
|
|
82
|
-
});
|
|
83
|
-
this.pipeline.add(this.infoPanel);
|
|
84
|
-
|
|
85
|
-
// Create all text items
|
|
86
|
-
const { amplitude, sigma, k, omega, velocity } = CONFIG;
|
|
87
|
-
|
|
88
|
-
this.titleText = new Text(this, "Gaussian Wave Packet", {
|
|
89
|
-
font: "bold 16px monospace",
|
|
90
|
-
color: "#7af",
|
|
91
|
-
align: "center",
|
|
92
|
-
baseline: "middle",
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
this.equationText = new Text(this, "\u03A8(x,t) = A\u00B7e^(-(x-vt)\u00B2/4\u03C3\u00B2) \u00B7 e^(i(kx-\u03C9t))", {
|
|
96
|
-
font: "14px monospace",
|
|
97
|
-
color: "#fff",
|
|
98
|
-
align: "center",
|
|
99
|
-
baseline: "middle",
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
this.paramsText = new Text(this, `A=${amplitude} \u03C3=${sigma} k=${k} \u03C9=${omega} v=${velocity}`, {
|
|
103
|
-
font: "12px monospace",
|
|
104
|
-
color: "#6d8",
|
|
105
|
-
align: "center",
|
|
106
|
-
baseline: "middle",
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
this.liveText = new Text(this, "t=0.00s x\u2080=0.00", {
|
|
110
|
-
font: "12px monospace",
|
|
111
|
-
color: "#fa6",
|
|
112
|
-
align: "center",
|
|
113
|
-
baseline: "middle",
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Use vertical layout to position items
|
|
117
|
-
const textItems = [this.titleText, this.equationText, this.paramsText, this.liveText];
|
|
118
|
-
const layout = verticalLayout(textItems, { spacing: 20, align: "center" });
|
|
119
|
-
applyLayout(textItems, layout.positions);
|
|
120
|
-
|
|
121
|
-
// Add all to panel
|
|
122
|
-
textItems.forEach(item => this.infoPanel.add(item));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Compute Gaussian wave packet using quantum.js module.
|
|
127
|
-
* Ψ(x,t) = A * e^(-(x-vt)²/4σ²) * e^(i(kx-ωt))
|
|
128
|
-
*/
|
|
129
|
-
computeWavePacket(x, t) {
|
|
130
|
-
return gaussianWavePacket(x, t, {
|
|
131
|
-
amplitude: CONFIG.amplitude,
|
|
132
|
-
sigma: CONFIG.sigma,
|
|
133
|
-
k: CONFIG.k,
|
|
134
|
-
omega: CONFIG.omega,
|
|
135
|
-
velocity: CONFIG.velocity,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* 3D rotation and projection - delegates to Camera3D
|
|
141
|
-
*/
|
|
142
|
-
project3D(x, y, z) {
|
|
143
|
-
return this.camera.project(x, y, z);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
update(dt) {
|
|
147
|
-
super.update(dt);
|
|
148
|
-
this.time += dt * CONFIG.timeScale;
|
|
149
|
-
|
|
150
|
-
// Loop when wave packet exits the visible range
|
|
151
|
-
const packetCenter = CONFIG.velocity * this.time;
|
|
152
|
-
if (packetCenter > CONFIG.xRange * 0.6) {
|
|
153
|
-
this.time = -CONFIG.xRange * 0.6 / CONFIG.velocity;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Update live text values
|
|
157
|
-
if (this.liveText) {
|
|
158
|
-
const t = this.time.toFixed(2);
|
|
159
|
-
const x0 = (CONFIG.velocity * this.time).toFixed(2);
|
|
160
|
-
this.liveText.text = `t=${t}s x\u2080=${x0}`;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
render() {
|
|
165
|
-
const w = this.width;
|
|
166
|
-
const h = this.height;
|
|
167
|
-
const cx = w / 2;
|
|
168
|
-
const cy = h / 2 - 30;
|
|
169
|
-
|
|
170
|
-
super.render();
|
|
171
|
-
|
|
172
|
-
// Compute wave packet points
|
|
173
|
-
const points = [];
|
|
174
|
-
const { numPoints, xRange, helixRadius, zScale } = CONFIG;
|
|
175
|
-
|
|
176
|
-
for (let i = 0; i < numPoints; i++) {
|
|
177
|
-
const t_param = i / (numPoints - 1);
|
|
178
|
-
const x = (t_param - 0.5) * xRange;
|
|
179
|
-
|
|
180
|
-
const { psi, envelope } = this.computeWavePacket(x, this.time);
|
|
181
|
-
|
|
182
|
-
// 3D coordinates: helix in Re/Im plane, extending along Z
|
|
183
|
-
const px = psi.real * helixRadius; // Re(Ψ) -> X
|
|
184
|
-
const py = psi.imag * helixRadius; // Im(Ψ) -> Y
|
|
185
|
-
const pz = x * zScale; // position -> Z
|
|
186
|
-
|
|
187
|
-
const projected = this.project3D(px, py, pz);
|
|
188
|
-
|
|
189
|
-
points.push({
|
|
190
|
-
x: cx + projected.x,
|
|
191
|
-
y: cy + projected.y,
|
|
192
|
-
z: projected.z,
|
|
193
|
-
scale: projected.scale,
|
|
194
|
-
envelope,
|
|
195
|
-
psi,
|
|
196
|
-
worldX: x,
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Draw grid plane
|
|
201
|
-
this.drawGrid(cx, cy);
|
|
202
|
-
|
|
203
|
-
// Draw axis line (position axis)
|
|
204
|
-
this.drawAxis(cx, cy);
|
|
205
|
-
|
|
206
|
-
// Draw envelope curves (Gaussian bell on grid)
|
|
207
|
-
this.drawEnvelope(cx, cy, points);
|
|
208
|
-
|
|
209
|
-
// Sort points by depth for proper rendering
|
|
210
|
-
const sortedIndices = points
|
|
211
|
-
.map((p, i) => ({ z: p.z, i }))
|
|
212
|
-
.sort((a, b) => a.z - b.z)
|
|
213
|
-
.map(item => item.i);
|
|
214
|
-
|
|
215
|
-
// Draw the helix wave
|
|
216
|
-
this.drawHelix(points, sortedIndices);
|
|
217
|
-
|
|
218
|
-
// Draw projection on grid (2D wave)
|
|
219
|
-
this.drawProjection(cx, cy, points);
|
|
220
|
-
|
|
221
|
-
// Info text
|
|
222
|
-
this.drawInfo(w, h);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
drawGrid(cx, cy) {
|
|
226
|
-
const { gridSize, gridSpacing, gridY } = CONFIG;
|
|
227
|
-
const halfGrid = (gridSize * gridSpacing) / 2;
|
|
228
|
-
|
|
229
|
-
// Draw grid lines
|
|
230
|
-
for (let i = -gridSize / 2; i <= gridSize / 2; i++) {
|
|
231
|
-
// Lines along Z
|
|
232
|
-
const x1 = i * gridSpacing;
|
|
233
|
-
const z1 = -halfGrid;
|
|
234
|
-
const z2 = halfGrid;
|
|
235
|
-
|
|
236
|
-
const p1 = this.project3D(x1, gridY, z1);
|
|
237
|
-
const p2 = this.project3D(x1, gridY, z2);
|
|
238
|
-
|
|
239
|
-
Painter.useCtx((ctx) => {
|
|
240
|
-
ctx.strokeStyle = CONFIG.gridColor;
|
|
241
|
-
ctx.lineWidth = 1;
|
|
242
|
-
ctx.moveTo(cx + p1.x, cy + p1.y);
|
|
243
|
-
ctx.lineTo(cx + p2.x, cy + p2.y);
|
|
244
|
-
ctx.stroke();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Lines along X
|
|
248
|
-
const p3 = this.project3D(-halfGrid, gridY, i * gridSpacing);
|
|
249
|
-
const p4 = this.project3D(halfGrid, gridY, i * gridSpacing);
|
|
250
|
-
|
|
251
|
-
Painter.useCtx((ctx) => {
|
|
252
|
-
ctx.strokeStyle = CONFIG.gridColor;
|
|
253
|
-
ctx.lineWidth = 1;
|
|
254
|
-
ctx.moveTo(cx + p3.x, cy + p3.y);
|
|
255
|
-
ctx.lineTo(cx + p4.x, cy + p4.y);
|
|
256
|
-
ctx.stroke();
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
drawAxis(cx, cy) {
|
|
262
|
-
const { zScale, xRange } = CONFIG;
|
|
263
|
-
|
|
264
|
-
// Main position axis (Z direction in 3D space)
|
|
265
|
-
const p1 = this.project3D(0, 0, -xRange / 2 * zScale * 1.2);
|
|
266
|
-
const p2 = this.project3D(0, 0, xRange / 2 * zScale * 1.2);
|
|
267
|
-
|
|
268
|
-
// Glowing axis line
|
|
269
|
-
Painter.useCtx((ctx) => {
|
|
270
|
-
ctx.strokeStyle = CONFIG.axisColor;
|
|
271
|
-
ctx.lineWidth = 2;
|
|
272
|
-
ctx.moveTo(cx + p1.x, cy + p1.y);
|
|
273
|
-
ctx.lineTo(cx + p2.x, cy + p2.y);
|
|
274
|
-
ctx.stroke();
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
// Bright center dot where wave packet is
|
|
278
|
-
const packetCenter = CONFIG.velocity * this.time;
|
|
279
|
-
const centerProj = this.project3D(0, 0, packetCenter * zScale);
|
|
280
|
-
|
|
281
|
-
Painter.useCtx((ctx) => {
|
|
282
|
-
ctx.fillStyle = "#fff";
|
|
283
|
-
ctx.shadowColor = "#88ccff";
|
|
284
|
-
ctx.shadowBlur = 20;
|
|
285
|
-
ctx.arc(cx + centerProj.x, cy + centerProj.y, 4, 0, Math.PI * 2);
|
|
286
|
-
ctx.fill();
|
|
287
|
-
ctx.shadowBlur = 0;
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
drawEnvelope(cx, cy, points) {
|
|
292
|
-
const { gridY } = CONFIG;
|
|
293
|
-
|
|
294
|
-
// Precompute envelope path points
|
|
295
|
-
const pathPoints = points.map(p => {
|
|
296
|
-
const envHeight = p.envelope * CONFIG.helixRadius * 0.8;
|
|
297
|
-
return this.project3D(0, gridY - envHeight, p.worldX * CONFIG.zScale);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// Draw Gaussian envelope on the grid plane
|
|
301
|
-
Painter.useCtx((ctx) => {
|
|
302
|
-
ctx.strokeStyle = CONFIG.envelopeColor;
|
|
303
|
-
ctx.lineWidth = 2;
|
|
304
|
-
|
|
305
|
-
for (let i = 0; i < pathPoints.length; i++) {
|
|
306
|
-
const proj = pathPoints[i];
|
|
307
|
-
if (i === 0) {
|
|
308
|
-
ctx.moveTo(cx + proj.x, cy + proj.y);
|
|
309
|
-
} else {
|
|
310
|
-
ctx.lineTo(cx + proj.x, cy + proj.y);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
ctx.stroke();
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
drawHelix(points, sortedIndices) {
|
|
318
|
-
const { waveColor, waveGlow } = CONFIG;
|
|
319
|
-
|
|
320
|
-
// Draw helix as connected line segments with varying thickness
|
|
321
|
-
for (let j = 0; j < sortedIndices.length - 1; j++) {
|
|
322
|
-
const i = sortedIndices[j];
|
|
323
|
-
const p1 = points[i];
|
|
324
|
-
const p2 = points[i + 1] || points[i];
|
|
325
|
-
|
|
326
|
-
if (Math.abs(i - (sortedIndices[j + 1] || i)) > 2) continue;
|
|
327
|
-
|
|
328
|
-
// Thickness based on envelope (thicker where amplitude is higher)
|
|
329
|
-
const thickness = 1 + p1.envelope * 6;
|
|
330
|
-
|
|
331
|
-
// Color intensity based on envelope
|
|
332
|
-
const intensity = 0.3 + p1.envelope * 0.7;
|
|
333
|
-
|
|
334
|
-
const r = Math.floor(waveColor[0] + (waveGlow[0] - waveColor[0]) * p1.envelope);
|
|
335
|
-
const g = Math.floor(waveColor[1] + (waveGlow[1] - waveColor[1]) * p1.envelope);
|
|
336
|
-
const b = Math.floor(waveColor[2] + (waveGlow[2] - waveColor[2]) * p1.envelope);
|
|
337
|
-
|
|
338
|
-
Painter.useCtx((ctx) => {
|
|
339
|
-
ctx.lineCap = "round";
|
|
340
|
-
ctx.lineJoin = "round";
|
|
341
|
-
ctx.strokeStyle = `rgba(${r},${g},${b},${intensity})`;
|
|
342
|
-
ctx.lineWidth = thickness * p1.scale;
|
|
343
|
-
ctx.moveTo(p1.x, p1.y);
|
|
344
|
-
ctx.lineTo(p2.x, p2.y);
|
|
345
|
-
ctx.stroke();
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Add glow effect at high-amplitude regions
|
|
350
|
-
for (const p of points) {
|
|
351
|
-
if (p.envelope > 0.5) {
|
|
352
|
-
const size = p.envelope * 4 * p.scale;
|
|
353
|
-
Painter.useCtx((ctx) => {
|
|
354
|
-
ctx.shadowColor = "rgba(100, 180, 255, 0.8)";
|
|
355
|
-
ctx.shadowBlur = 15;
|
|
356
|
-
ctx.fillStyle = `rgba(200, 230, 255, ${p.envelope * 0.5})`;
|
|
357
|
-
ctx.arc(p.x, p.y, size, 0, Math.PI * 2);
|
|
358
|
-
ctx.fill();
|
|
359
|
-
ctx.shadowBlur = 0;
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
drawProjection(cx, cy, points) {
|
|
366
|
-
const { gridY, zScale } = CONFIG;
|
|
367
|
-
|
|
368
|
-
// Precompute projection path points
|
|
369
|
-
const pathPoints = points.map(p => {
|
|
370
|
-
const waveHeight = p.psi.real * CONFIG.helixRadius * 0.5;
|
|
371
|
-
return this.project3D(waveHeight, gridY, p.worldX * zScale);
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
// Draw 2D wave projection on grid (Re(Ψ) only)
|
|
375
|
-
Painter.useCtx((ctx) => {
|
|
376
|
-
ctx.strokeStyle = "rgba(80, 160, 255, 0.6)";
|
|
377
|
-
ctx.lineWidth = 1.5;
|
|
378
|
-
|
|
379
|
-
for (let i = 0; i < pathPoints.length; i++) {
|
|
380
|
-
const proj = pathPoints[i];
|
|
381
|
-
if (i === 0) {
|
|
382
|
-
ctx.moveTo(cx + proj.x, cy + proj.y);
|
|
383
|
-
} else {
|
|
384
|
-
ctx.lineTo(cx + proj.x, cy + proj.y);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
ctx.stroke();
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
drawInfo(w, h) {
|
|
392
|
-
Painter.useCtx((ctx) => {
|
|
393
|
-
// Controls hint (bottom right)
|
|
394
|
-
ctx.fillStyle = "#445";
|
|
395
|
-
ctx.font = "10px monospace";
|
|
396
|
-
ctx.textAlign = "right";
|
|
397
|
-
ctx.fillText("drag to rotate | double-click to reset", w - 15, h - 30);
|
|
398
|
-
|
|
399
|
-
// Legend
|
|
400
|
-
ctx.fillText("Helix = \u03A8 | Blue = Re(\u03A8) | Red = |\u03A8|\u00B2", w - 15, h - 15);
|
|
401
|
-
ctx.textAlign = "left";
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
window.addEventListener("load", () => {
|
|
407
|
-
const canvas = document.getElementById("game");
|
|
408
|
-
const demo = new SchrodingerDemo(canvas);
|
|
409
|
-
demo.start();
|
|
410
|
-
});
|