LukasBe commited on
Commit
12d864c
·
verified ·
1 Parent(s): 89f819b

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +1166 -133
index.html CHANGED
@@ -3,97 +3,761 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>3D Wormhole Simulator</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.min.js"></script>
10
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/GLTFLoader.min.js"></script>
 
11
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
12
  body {
13
  margin: 0;
14
  overflow: hidden;
15
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 
 
 
16
  }
 
17
  #canvas {
18
  display: block;
 
 
 
 
19
  }
20
- #ui {
21
- position: absolute;
 
22
  top: 0;
23
  left: 0;
24
  width: 100%;
25
  height: 100%;
 
26
  pointer-events: none;
 
 
 
 
 
27
  }
28
- #controls {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  position: absolute;
30
- bottom: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  left: 50%;
32
  transform: translateX(-50%);
33
- background: rgba(0, 0, 0, 0.5);
34
- padding: 10px 20px;
35
- border-radius: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  display: flex;
37
- gap: 10px;
 
 
 
 
 
 
 
 
 
38
  pointer-events: all;
39
  }
40
- button {
41
- background: rgba(255, 255, 255, 0.2);
42
- color: white;
43
- border: 1px solid rgba(255, 255, 255, 0.3);
44
- padding: 8px 16px;
45
- border-radius: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  cursor: pointer;
47
- transition: all 0.3s;
48
  }
49
- button:hover {
50
- background: rgba(255, 255, 255, 0.3);
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
- #info {
 
 
 
 
 
 
 
53
  position: absolute;
54
- top: 20px;
55
- left: 20px;
56
- color: white;
57
- background: rgba(0, 0, 0, 0.5);
58
- padding: 10px;
59
- border-radius: 10px;
60
- max-width: 300px;
 
61
  }
62
- .particle {
 
63
  position: absolute;
64
- width: 2px;
65
- height: 2px;
66
- background: white;
 
 
 
 
67
  border-radius: 50%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  pointer-events: none;
 
 
 
69
  }
70
- @keyframes pulse {
71
- 0% { opacity: 0.2; }
72
- 50% { opacity: 1; }
73
- 100% { opacity: 0.2; }
74
  }
75
- .pulse {
76
- animation: pulse 2s infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
78
  </style>
79
  </head>
80
  <body>
81
  <div id="canvas"></div>
82
- <div id="ui">
83
- <div id="info">
84
- <h1 class="text-xl font-bold mb-2">Wormhole Simulator</h1>
85
- <p class="text-sm">Experience a journey through a cosmic wormhole with dynamic effects.</p>
86
- <div class="mt-2 text-xs">
87
- <div class="flex items-center"><div class="w-3 h-3 bg-blue-500 rounded-full mr-2"></div> Stars</div>
88
- <div class="flex items-center"><div class="w-3 h-3 bg-yellow-500 rounded-full mr-2"></div> Sparks</div>
89
- <div class="flex items-center"><div class="w-3 h-3 bg-red-500 rounded-full mr-2"></div> Explosions</div>
90
- <div class="flex items-center"><div class="w-3 h-3 bg-gray-400 rounded-full mr-2"></div> Debris</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  </div>
92
  </div>
93
- <div id="controls">
94
- <button id="startBtn">Start Journey</button>
95
- <button id="resetBtn">Reset</button>
96
- <button id="autoPilot">Auto Pilot</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  </div>
98
  </div>
99
 
@@ -109,13 +773,22 @@
109
  let debrisParticles = [];
110
  let sparkParticles = [];
111
  let starParticles = [];
 
 
 
 
 
 
 
 
 
112
 
113
  // Initialize the scene
114
  function init() {
115
  // Create scene
116
  scene = new THREE.Scene();
117
- scene.background = new THREE.Color(0x000000);
118
- scene.fog = new THREE.FogExp2(0x000000, 0.002);
119
 
120
  // Create camera
121
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
@@ -125,6 +798,7 @@
125
  renderer = new THREE.WebGLRenderer({ antialias: true });
126
  renderer.setSize(window.innerWidth, window.innerHeight);
127
  renderer.shadowMap.enabled = true;
 
128
  document.getElementById('canvas').appendChild(renderer.domElement);
129
 
130
  // Add orbit controls
@@ -141,6 +815,15 @@
141
  directionalLight.castShadow = true;
142
  scene.add(directionalLight);
143
 
 
 
 
 
 
 
 
 
 
144
  // Create wormhole
145
  createWormhole();
146
 
@@ -155,6 +838,23 @@
155
  document.getElementById('startBtn').addEventListener('click', startJourney);
156
  document.getElementById('resetBtn').addEventListener('click', resetScene);
157
  document.getElementById('autoPilot').addEventListener('click', toggleAutoPilot);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
  // Start animation loop
160
  animate();
@@ -166,10 +866,11 @@
166
  const material = new THREE.MeshPhongMaterial({
167
  color: 0x00aaff,
168
  emissive: 0x0066ff,
169
- emissiveIntensity: 0.5,
170
  transparent: true,
171
- opacity: 0.8,
172
- wireframe: true
 
173
  });
174
 
175
  wormhole = new THREE.Mesh(geometry, material);
@@ -181,10 +882,21 @@
181
  const innerGlowMaterial = new THREE.MeshBasicMaterial({
182
  color: 0x00aaff,
183
  transparent: true,
184
- opacity: 0.2
185
  });
186
  const innerGlow = new THREE.Mesh(innerGlowGeometry, innerGlowMaterial);
187
  wormhole.add(innerGlow);
 
 
 
 
 
 
 
 
 
 
 
188
  }
189
 
190
  // Create spaceship
@@ -193,9 +905,9 @@
193
  const material = new THREE.MeshPhongMaterial({
194
  color: 0xffffff,
195
  emissive: 0xaaaaaa,
196
- emissiveIntensity: 0.2,
197
  specular: 0x111111,
198
- shininess: 30
199
  });
200
 
201
  ship = new THREE.Mesh(geometry, material);
@@ -208,36 +920,73 @@
208
  const engineGlowMaterial = new THREE.MeshBasicMaterial({
209
  color: 0x00ffff,
210
  transparent: true,
211
- opacity: 0.8
212
  });
213
  const engineGlow = new THREE.Mesh(engineGlowGeometry, engineGlowMaterial);
214
  engineGlow.position.set(0, -1.5, 0);
215
  ship.add(engineGlow);
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  }
217
 
218
  // Create various particles
219
  function createParticles() {
220
  // Stars background
221
- for (let i = 0; i < 1000; i++) {
222
- const star = new THREE.Mesh(
223
- new THREE.SphereGeometry(0.05 + Math.random() * 0.2, 8, 8),
224
- new THREE.MeshBasicMaterial({ color: 0xffffff })
225
- );
226
- star.position.set(
 
 
 
 
 
 
 
227
  Math.random() * 2000 - 1000,
228
  Math.random() * 2000 - 1000,
229
  Math.random() * 2000 - 1000
230
  );
231
- scene.add(star);
232
- starParticles.push(star);
 
 
 
 
 
 
233
  }
 
 
 
 
 
 
 
234
 
235
  // Debris
236
- for (let i = 0; i < 100; i++) {
237
- const size = 0.2 + Math.random() * 1;
238
  const debris = new THREE.Mesh(
239
  new THREE.BoxGeometry(size, size, size),
240
- new THREE.MeshPhongMaterial({ color: 0x888888 })
 
 
 
 
241
  );
242
  debris.position.set(
243
  Math.random() * 100 - 50,
@@ -254,6 +1003,11 @@
254
  Math.random() * 0.2 - 0.1,
255
  Math.random() * 0.2 - 0.1,
256
  Math.random() * 0.2 - 0.1
 
 
 
 
 
257
  )
258
  };
259
  scene.add(debris);
@@ -263,59 +1017,93 @@
263
 
264
  // Create explosion effect
265
  function createExplosion(position) {
266
- for (let i = 0; i < 50; i++) {
267
- const size = 0.1 + Math.random() * 0.3;
268
- const particle = new THREE.Mesh(
269
- new THREE.SphereGeometry(size, 8, 8),
270
- new THREE.MeshBasicMaterial({
271
- color: new THREE.Color(
272
- 0.8 + Math.random() * 0.2,
273
- 0.3 + Math.random() * 0.3,
274
- Math.random() * 0.2
275
- ),
276
- transparent: true,
277
- opacity: 0.8
278
- })
 
 
 
 
279
  );
280
- particle.position.copy(position);
281
- particle.userData = {
282
- velocity: new THREE.Vector3(
283
- Math.random() * 2 - 1,
284
- Math.random() * 2 - 1,
285
- Math.random() * 2 - 1
286
- ),
287
- lifetime: 100 + Math.random() * 50,
288
- age: 0
289
- };
290
- scene.add(particle);
291
- explosionParticles.push(particle);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  }
293
  }
294
 
295
  // Create spark effect
296
  function createSparks(position) {
297
- for (let i = 0; i < 20; i++) {
298
- const spark = new THREE.Mesh(
299
- new THREE.SphereGeometry(0.05 + Math.random() * 0.1, 4, 4),
300
- new THREE.MeshBasicMaterial({
301
- color: 0xffff00,
302
- transparent: true,
303
- opacity: 0.8
304
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  );
306
- spark.position.copy(position);
307
- spark.userData = {
308
- velocity: new THREE.Vector3(
309
- Math.random() * 0.5 - 0.25,
310
- Math.random() * 0.5 - 0.25,
311
- Math.random() * 0.5 - 0.25
312
- ),
313
- lifetime: 50 + Math.random() * 30,
314
- age: 0
315
- };
316
- scene.add(spark);
317
- sparkParticles.push(spark);
318
  }
 
 
 
 
 
 
 
 
 
 
 
319
  }
320
 
321
  // Bezier curve for smooth flight path
@@ -349,6 +1137,14 @@
349
  if (!isAnimating) {
350
  isAnimating = true;
351
  journeyProgress = 0;
 
 
 
 
 
 
 
 
352
  }
353
  }
354
 
@@ -360,12 +1156,135 @@
360
  ship.position.set(0, 0, -50);
361
  camera.position.set(0, 0, 50);
362
  controls.reset();
 
 
 
 
 
 
 
 
 
363
  }
364
 
365
  // Toggle autopilot mode
366
  function toggleAutoPilot() {
367
  autoPilot = !autoPilot;
368
- document.getElementById('autoPilot').textContent = autoPilot ? 'Manual Control' : 'Auto Pilot';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  }
370
 
371
  // Handle window resize
@@ -375,6 +1294,78 @@
375
  renderer.setSize(window.innerWidth, window.innerHeight);
376
  }
377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  // Animation loop
379
  function animate() {
380
  requestAnimationFrame(animate);
@@ -382,14 +1373,15 @@
382
  // Update controls
383
  controls.update();
384
 
385
- // Rotate wormhole
386
- wormhole.rotation.z += 0.005;
387
 
388
  // Update debris particles
389
  debrisParticles.forEach(debris => {
390
  debris.position.add(debris.userData.velocity);
391
- debris.rotation.x += 0.01;
392
- debris.rotation.y += 0.01;
 
393
 
394
  // Wrap around if out of bounds
395
  if (Math.abs(debris.position.x) > 100) debris.position.x = -debris.position.x;
@@ -399,14 +1391,29 @@
399
 
400
  // Update explosion particles
401
  for (let i = explosionParticles.length - 1; i >= 0; i--) {
402
- const particle = explosionParticles[i];
403
- particle.position.add(particle.userData.velocity);
404
- particle.userData.age++;
405
- particle.userData.velocity.multiplyScalar(0.98);
406
- particle.material.opacity = 0.8 * (1 - particle.userData.age / particle.userData.lifetime);
 
 
 
 
 
 
 
 
 
407
 
408
- if (particle.userData.age >= particle.userData.lifetime) {
409
- scene.remove(particle);
 
 
 
 
 
 
410
  explosionParticles.splice(i, 1);
411
  }
412
  }
@@ -414,9 +1421,24 @@
414
  // Update spark particles
415
  for (let i = sparkParticles.length - 1; i >= 0; i--) {
416
  const spark = sparkParticles[i];
417
- spark.position.add(spark.userData.velocity);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  spark.userData.age++;
419
- spark.userData.velocity.multiplyScalar(0.95);
 
420
  spark.material.opacity = 0.8 * (1 - spark.userData.age / spark.userData.lifetime);
421
 
422
  if (spark.userData.age >= spark.userData.lifetime) {
@@ -425,8 +1447,8 @@
425
  }
426
  }
427
 
428
- // Randomly create explosions and sparks
429
- if (Math.random() < 0.02) {
430
  createExplosion(new THREE.Vector3(
431
  Math.random() * 40 - 20,
432
  Math.random() * 40 - 20,
@@ -434,7 +1456,7 @@
434
  ));
435
  }
436
 
437
- if (Math.random() < 0.05) {
438
  createSparks(new THREE.Vector3(
439
  Math.random() * 30 - 15,
440
  Math.random() * 30 - 15,
@@ -449,6 +1471,9 @@
449
  if (journeyProgress >= 1) {
450
  journeyProgress = 1;
451
  isAnimating = false;
 
 
 
452
  }
453
 
454
  const shipPos = getBezierPoint(journeyProgress);
@@ -463,14 +1488,22 @@
463
  journeySpeed = 0.001 + Math.sin(Date.now() * 0.001) * 0.0005;
464
 
465
  // Auto camera follow in autopilot mode
466
- if (autoPilot) {
467
  const cameraOffset = new THREE.Vector3(0, 5, -10);
468
  cameraOffset.applyQuaternion(ship.quaternion);
469
  camera.position.copy(ship.position).add(cameraOffset);
470
  camera.lookAt(ship.position);
471
  }
 
 
 
 
472
  }
473
 
 
 
 
 
474
  renderer.render(scene, camera);
475
  }
476
 
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Cosmic Journey - Wormhole Simulator</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.min.js"></script>
10
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/GLTFLoader.min.js"></script>
11
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
12
  <style>
13
+ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700&display=swap');
14
+
15
+ :root {
16
+ --primary: #00f0ff;
17
+ --secondary: #7b2dff;
18
+ --tertiary: #ff2d7b;
19
+ --dark: #0a0a1a;
20
+ --darker: #050510;
21
+ --light: #e0e0ff;
22
+ --accent: #ff2d7b;
23
+ }
24
+
25
  body {
26
  margin: 0;
27
  overflow: hidden;
28
+ font-family: 'Space Grotesk', 'Orbitron', sans-serif;
29
+ background-color: var(--dark);
30
+ color: var(--light);
31
+ touch-action: none;
32
  }
33
+
34
  #canvas {
35
  display: block;
36
+ position: fixed;
37
+ top: 0;
38
+ left: 0;
39
+ z-index: 1;
40
  }
41
+
42
+ #ui-overlay {
43
+ position: fixed;
44
  top: 0;
45
  left: 0;
46
  width: 100%;
47
  height: 100%;
48
+ z-index: 2;
49
  pointer-events: none;
50
+ display: flex;
51
+ flex-direction: column;
52
+ justify-content: space-between;
53
+ padding: 1.5rem;
54
+ box-sizing: border-box;
55
  }
56
+
57
+ .glass-panel {
58
+ background: rgba(10, 10, 26, 0.4);
59
+ backdrop-filter: blur(16px);
60
+ -webkit-backdrop-filter: blur(16px);
61
+ border-radius: 1.5rem;
62
+ border: 1px solid rgba(224, 224, 255, 0.1);
63
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
64
+ padding: 1.25rem;
65
+ pointer-events: all;
66
+ transition: all 0.3s ease;
67
+ }
68
+
69
+ .glass-panel:hover {
70
+ border-color: rgba(224, 224, 255, 0.2);
71
+ box-shadow: 0 8px 32px rgba(0, 240, 255, 0.1);
72
+ }
73
+
74
+ .control-btn {
75
+ width: 3.5rem;
76
+ height: 3.5rem;
77
+ border-radius: 50%;
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ background: linear-gradient(135deg, rgba(0, 240, 255, 0.1), rgba(123, 45, 255, 0.1));
82
+ border: 1px solid rgba(224, 224, 255, 0.1);
83
+ color: var(--primary);
84
+ font-size: 1.25rem;
85
+ transition: all 0.3s ease;
86
+ cursor: pointer;
87
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
88
+ }
89
+
90
+ .control-btn:hover {
91
+ background: linear-gradient(135deg, rgba(0, 240, 255, 0.2), rgba(123, 45, 255, 0.2));
92
+ transform: translateY(-2px);
93
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
94
+ color: white;
95
+ }
96
+
97
+ .control-btn.active {
98
+ background: linear-gradient(135deg, rgba(0, 240, 255, 0.3), rgba(123, 45, 255, 0.3));
99
+ color: white;
100
+ border-color: var(--primary);
101
+ box-shadow: 0 0 15px rgba(0, 240, 255, 0.5);
102
+ }
103
+
104
+ .control-btn i {
105
+ pointer-events: none;
106
+ }
107
+
108
+ .progress-track {
109
+ height: 0.5rem;
110
+ background: rgba(224, 224, 255, 0.1);
111
+ border-radius: 1rem;
112
+ overflow: hidden;
113
+ }
114
+
115
+ .progress-bar {
116
+ height: 100%;
117
+ background: linear-gradient(90deg, var(--primary), var(--secondary));
118
+ border-radius: 1rem;
119
+ transition: width 0.3s ease;
120
+ box-shadow: 0 0 10px rgba(0, 240, 255, 0.5);
121
+ }
122
+
123
+ .hud-element {
124
  position: absolute;
125
+ background: rgba(10, 10, 26, 0.3);
126
+ border-radius: 0.75rem;
127
+ padding: 0.75rem;
128
+ border: 1px solid rgba(224, 224, 255, 0.05);
129
+ display: flex;
130
+ align-items: center;
131
+ gap: 0.5rem;
132
+ font-size: 0.875rem;
133
+ font-weight: 500;
134
+ transition: all 0.3s ease;
135
+ }
136
+
137
+ .hud-element:hover {
138
+ background: rgba(10, 10, 26, 0.5);
139
+ border-color: rgba(224, 224, 255, 0.2);
140
+ }
141
+
142
+ .hud-element i {
143
+ font-size: 1rem;
144
+ color: var(--primary);
145
+ }
146
+
147
+ .particle-indicator {
148
+ width: 0.75rem;
149
+ height: 0.75rem;
150
+ border-radius: 50%;
151
+ display: inline-block;
152
+ margin-right: 0.25rem;
153
+ box-shadow: 0 0 5px currentColor;
154
+ }
155
+
156
+ .neon-text {
157
+ text-shadow: 0 0 8px rgba(0, 240, 255, 0.6);
158
+ }
159
+
160
+ .pulse {
161
+ animation: pulse 2s infinite;
162
+ }
163
+
164
+ @keyframes pulse {
165
+ 0% { opacity: 0.6; }
166
+ 50% { opacity: 1; }
167
+ 100% { opacity: 0.6; }
168
+ }
169
+
170
+ .slide-in {
171
+ animation: slideIn 0.5s ease-out forwards;
172
+ }
173
+
174
+ @keyframes slideIn {
175
+ from { transform: translateY(100%); opacity: 0; }
176
+ to { transform: translateY(0); opacity: 1; }
177
+ }
178
+
179
+ .notification {
180
+ position: fixed;
181
+ top: 1.5rem;
182
  left: 50%;
183
  transform: translateX(-50%);
184
+ background: rgba(10, 10, 26, 0.9);
185
+ border-left: 4px solid var(--primary);
186
+ padding: 0.75rem 1.25rem;
187
+ border-radius: 0.5rem;
188
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
189
+ z-index: 100;
190
+ display: flex;
191
+ align-items: center;
192
+ gap: 0.75rem;
193
+ animation: slideIn 0.3s ease-out;
194
+ max-width: 90%;
195
+ width: auto;
196
+ }
197
+
198
+ .notification i {
199
+ color: var(--primary);
200
+ font-size: 1.25rem;
201
+ }
202
+
203
+ .tooltip {
204
+ position: absolute;
205
+ background: rgba(10, 10, 26, 0.9);
206
+ color: var(--light);
207
+ padding: 0.5rem 0.75rem;
208
+ border-radius: 0.5rem;
209
+ font-size: 0.75rem;
210
+ white-space: nowrap;
211
+ pointer-events: none;
212
+ opacity: 0;
213
+ transition: opacity 0.2s;
214
+ z-index: 10;
215
+ border: 1px solid rgba(224, 224, 255, 0.1);
216
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
217
+ }
218
+
219
+ .control-btn:hover .tooltip {
220
+ opacity: 1;
221
+ }
222
+
223
+ .modal {
224
+ position: fixed;
225
+ top: 0;
226
+ left: 0;
227
+ width: 100%;
228
+ height: 100%;
229
+ background: rgba(5, 5, 16, 0.9);
230
  display: flex;
231
+ align-items: center;
232
+ justify-content: center;
233
+ z-index: 1000;
234
+ opacity: 0;
235
+ pointer-events: none;
236
+ transition: opacity 0.3s ease;
237
+ }
238
+
239
+ .modal.active {
240
+ opacity: 1;
241
  pointer-events: all;
242
  }
243
+
244
+ .modal-content {
245
+ background: var(--darker);
246
+ border-radius: 1.5rem;
247
+ padding: 2rem;
248
+ max-width: 500px;
249
+ width: 90%;
250
+ max-height: 90vh;
251
+ overflow-y: auto;
252
+ border: 1px solid rgba(0, 240, 255, 0.2);
253
+ box-shadow: 0 0 30px rgba(0, 240, 255, 0.2);
254
+ }
255
+
256
+ .close-modal {
257
+ position: absolute;
258
+ top: 1rem;
259
+ right: 1rem;
260
+ background: none;
261
+ border: none;
262
+ color: var(--light);
263
+ font-size: 1.5rem;
264
  cursor: pointer;
 
265
  }
266
+
267
+ .settings-option {
268
+ display: flex;
269
+ justify-content: space-between;
270
+ align-items: center;
271
+ padding: 0.75rem 0;
272
+ border-bottom: 1px solid rgba(224, 224, 255, 0.1);
273
+ }
274
+
275
+ .toggle-switch {
276
+ position: relative;
277
+ display: inline-block;
278
+ width: 50px;
279
+ height: 24px;
280
  }
281
+
282
+ .toggle-switch input {
283
+ opacity: 0;
284
+ width: 0;
285
+ height: 0;
286
+ }
287
+
288
+ .slider {
289
  position: absolute;
290
+ cursor: pointer;
291
+ top: 0;
292
+ left: 0;
293
+ right: 0;
294
+ bottom: 0;
295
+ background-color: rgba(224, 224, 255, 0.1);
296
+ transition: .4s;
297
+ border-radius: 24px;
298
  }
299
+
300
+ .slider:before {
301
  position: absolute;
302
+ content: "";
303
+ height: 16px;
304
+ width: 16px;
305
+ left: 4px;
306
+ bottom: 4px;
307
+ background-color: var(--light);
308
+ transition: .4s;
309
  border-radius: 50%;
310
+ }
311
+
312
+ input:checked + .slider {
313
+ background-color: var(--primary);
314
+ }
315
+
316
+ input:checked + .slider:before {
317
+ transform: translateX(26px);
318
+ }
319
+
320
+ .slider-text {
321
+ margin-left: 0.5rem;
322
+ font-size: 0.875rem;
323
+ color: var(--light);
324
+ }
325
+
326
+ .range-slider {
327
+ width: 100%;
328
+ -webkit-appearance: none;
329
+ height: 6px;
330
+ border-radius: 3px;
331
+ background: rgba(224, 224, 255, 0.1);
332
+ outline: none;
333
+ }
334
+
335
+ .range-slider::-webkit-slider-thumb {
336
+ -webkit-appearance: none;
337
+ appearance: none;
338
+ width: 18px;
339
+ height: 18px;
340
+ border-radius: 50%;
341
+ background: var(--primary);
342
+ cursor: pointer;
343
+ box-shadow: 0 0 5px rgba(0, 240, 255, 0.8);
344
+ }
345
+
346
+ .range-slider::-moz-range-thumb {
347
+ width: 18px;
348
+ height: 18px;
349
+ border-radius: 50%;
350
+ background: var(--primary);
351
+ cursor: pointer;
352
+ box-shadow: 0 0 5px rgba(0, 240, 255, 0.8);
353
+ }
354
+
355
+ .destination-card {
356
+ background: rgba(10, 10, 26, 0.5);
357
+ border-radius: 0.75rem;
358
+ padding: 1rem;
359
+ margin-bottom: 1rem;
360
+ border: 1px solid rgba(224, 224, 255, 0.1);
361
+ transition: all 0.3s ease;
362
+ cursor: pointer;
363
+ }
364
+
365
+ .destination-card:hover {
366
+ background: rgba(10, 10, 26, 0.7);
367
+ border-color: var(--primary);
368
+ transform: translateY(-2px);
369
+ }
370
+
371
+ .destination-card.active {
372
+ background: rgba(0, 240, 255, 0.1);
373
+ border-color: var(--primary);
374
+ box-shadow: 0 0 15px rgba(0, 240, 255, 0.2);
375
+ }
376
+
377
+ .warp-effect {
378
+ position: fixed;
379
+ top: 0;
380
+ left: 0;
381
+ width: 100%;
382
+ height: 100%;
383
+ background: radial-gradient(circle, rgba(0,240,255,0.1) 0%, rgba(123,45,255,0.05) 50%, rgba(0,0,0,0) 70%);
384
  pointer-events: none;
385
+ z-index: 5;
386
+ opacity: 0;
387
+ transition: opacity 0.5s ease;
388
  }
389
+
390
+ .warp-effect.active {
391
+ opacity: 1;
 
392
  }
393
+
394
+ /* Responsive adjustments */
395
+ @media (max-width: 768px) {
396
+ #ui-overlay {
397
+ padding: 1rem;
398
+ }
399
+
400
+ .glass-panel {
401
+ padding: 1rem;
402
+ }
403
+
404
+ .control-btn {
405
+ width: 3rem;
406
+ height: 3rem;
407
+ font-size: 1rem;
408
+ }
409
+
410
+ .hud-element {
411
+ font-size: 0.75rem;
412
+ padding: 0.5rem;
413
+ }
414
  }
415
  </style>
416
  </head>
417
  <body>
418
  <div id="canvas"></div>
419
+ <div id="warp-effect" class="warp-effect"></div>
420
+
421
+ <div id="ui-overlay">
422
+ <!-- Top Bar -->
423
+ <div class="glass-panel w-full max-w-2xl mx-auto">
424
+ <div class="flex justify-between items-center">
425
+ <div>
426
+ <h1 class="text-xl font-bold neon-text">COSMIC JOURNEY</h1>
427
+ <p class="text-xs opacity-80">WORMHOLE SIMULATOR v2.1</p>
428
+ </div>
429
+ <div class="flex items-center gap-2">
430
+ <div class="hud-element">
431
+ <i class="fas fa-satellite-dish"></i>
432
+ <span>STABLE CONNECTION</span>
433
+ </div>
434
+ <div class="hud-element">
435
+ <i class="fas fa-battery-three-quarters"></i>
436
+ <span id="power-level">87% POWER</span>
437
+ </div>
438
+ </div>
439
+ </div>
440
+ </div>
441
+
442
+ <!-- Center HUD -->
443
+ <div class="flex flex-col items-center justify-center gap-4 pointer-events-none">
444
+ <div class="glass-panel px-6 py-3 flex items-center gap-4">
445
+ <div class="text-center">
446
+ <div class="text-xs opacity-80">WARP SPEED</div>
447
+ <div class="text-2xl font-bold neon-text" id="speed-display">0.7<span class="text-sm">x</span></div>
448
+ </div>
449
+ <div class="h-8 w-px bg-gradient-to-b from-transparent via-white/20 to-transparent"></div>
450
+ <div class="text-center">
451
+ <div class="text-xs opacity-80">DISTANCE</div>
452
+ <div class="text-2xl font-bold neon-text" id="distance-display">1.4<span class="text-sm">LY</span></div>
453
+ </div>
454
+ <div class="h-8 w-px bg-gradient-to-b from-transparent via-white/20 to-transparent"></div>
455
+ <div class="text-center">
456
+ <div class="text-xs opacity-80">TIME DILATION</div>
457
+ <div class="text-2xl font-bold neon-text" id="time-dilation-display">3.2<span class="text-sm">x</span></div>
458
+ </div>
459
+ </div>
460
+
461
+ <div id="target-indicator" class="w-16 h-16 rounded-full border-2 border-white/20 flex items-center justify-center pulse">
462
+ <div class="w-10 h-10 rounded-full border-2 border-primary/50 animate-ping"></div>
463
+ </div>
464
+ </div>
465
+
466
+ <!-- Bottom Controls -->
467
+ <div class="glass-panel w-full max-w-md mx-auto slide-in">
468
+ <div class="flex flex-col gap-4">
469
+ <div class="flex justify-between items-center">
470
+ <div class="text-sm font-medium">JOURNEY PROGRESS</div>
471
+ <div class="text-xs opacity-80">PHASE: <span id="phase-text">INITIALIZATION</span></div>
472
+ </div>
473
+ <div class="progress-track">
474
+ <div id="progress-bar" class="progress-bar" style="width: 0%"></div>
475
+ </div>
476
+
477
+ <div class="flex justify-between items-center gap-4">
478
+ <button id="startBtn" class="control-btn active" data-tooltip="Begin journey">
479
+ <i class="fas fa-play"></i>
480
+ <span class="tooltip">Begin journey</span>
481
+ </button>
482
+
483
+ <button id="resetBtn" class="control-btn" data-tooltip="Reset simulation">
484
+ <i class="fas fa-undo"></i>
485
+ <span class="tooltip">Reset simulation</span>
486
+ </button>
487
+
488
+ <button id="autoPilot" class="control-btn" data-tooltip="Toggle autopilot">
489
+ <i class="fas fa-robot"></i>
490
+ <span class="tooltip">Toggle autopilot</span>
491
+ </button>
492
+
493
+ <button id="effectsBtn" class="control-btn" data-tooltip="Effects settings">
494
+ <i class="fas fa-magic"></i>
495
+ <span class="tooltip">Effects settings</span>
496
+ </button>
497
+
498
+ <button id="infoBtn" class="control-btn" data-tooltip="Information">
499
+ <i class="fas fa-info-circle"></i>
500
+ <span class="tooltip">Information</span>
501
+ </button>
502
+
503
+ <button id="destinationsBtn" class="control-btn" data-tooltip="Destinations">
504
+ <i class="fas fa-map-marked-alt"></i>
505
+ <span class="tooltip">Destinations</span>
506
+ </button>
507
+ </div>
508
+ </div>
509
+ </div>
510
+
511
+ <!-- Particle Legend (Bottom Left) -->
512
+ <div class="glass-panel absolute bottom-4 left-4 w-48">
513
+ <div class="text-xs font-medium mb-2">PARTICLE VISUALIZATION</div>
514
+ <div class="space-y-1">
515
+ <div class="flex items-center">
516
+ <span class="particle-indicator bg-blue-500"></span>
517
+ <span>Stars</span>
518
+ </div>
519
+ <div class="flex items-center">
520
+ <span class="particle-indicator bg-yellow-500"></span>
521
+ <span>Sparks</span>
522
+ </div>
523
+ <div class="flex items-center">
524
+ <span class="particle-indicator bg-red-500"></span>
525
+ <span>Explosions</span>
526
+ </div>
527
+ <div class="flex items-center">
528
+ <span class="particle-indicator bg-gray-400"></span>
529
+ <span>Debris</span>
530
+ </div>
531
+ </div>
532
+ </div>
533
+
534
+ <!-- System Status (Bottom Right) -->
535
+ <div class="glass-panel absolute bottom-4 right-4 w-48">
536
+ <div class="text-xs font-medium mb-2">SYSTEM STATUS</div>
537
+ <div class="space-y-1 text-xs">
538
+ <div class="flex justify-between">
539
+ <span>Wormhole Stability:</span>
540
+ <span id="stability-status" class="text-green-400">Optimal</span>
541
+ </div>
542
+ <div class="flex justify-between">
543
+ <span>Gravity Field:</span>
544
+ <span id="gravity-status" class="text-blue-400">Balanced</span>
545
+ </div>
546
+ <div class="flex justify-between">
547
+ <span>Radiation Levels:</span>
548
+ <span id="radiation-status" class="text-yellow-400">Moderate</span>
549
+ </div>
550
+ <div class="flex justify-between">
551
+ <span>Time Distortion:</span>
552
+ <span id="time-status" class="text-purple-400">3.2x</span>
553
+ </div>
554
+ </div>
555
+ </div>
556
+ </div>
557
+
558
+ <!-- Notification System -->
559
+ <div id="notification" class="notification hidden">
560
+ <i class="fas fa-info-circle"></i>
561
+ <div>
562
+ <div class="font-medium">System Notification</div>
563
+ <div class="text-xs opacity-80" id="notification-message">Message content here</div>
564
+ </div>
565
+ </div>
566
+
567
+ <!-- Settings Modal -->
568
+ <div id="settingsModal" class="modal">
569
+ <div class="modal-content relative">
570
+ <button class="close-modal" id="closeSettings">&times;</button>
571
+ <h2 class="text-xl font-bold mb-4 neon-text">SIMULATION SETTINGS</h2>
572
+
573
+ <div class="settings-option">
574
+ <div>
575
+ <div class="font-medium">Particle Density</div>
576
+ <div class="text-xs opacity-80">Adjust the number of visual particles</div>
577
+ </div>
578
+ <input type="range" min="1" max="100" value="50" class="range-slider" id="particleDensity">
579
+ </div>
580
+
581
+ <div class="settings-option">
582
+ <div>
583
+ <div class="font-medium">Warp Effects</div>
584
+ <div class="text-xs opacity-80">Enable/disable visual warp effects</div>
585
+ </div>
586
+ <label class="toggle-switch">
587
+ <input type="checkbox" id="warpEffectsToggle" checked>
588
+ <span class="slider"></span>
589
+ </label>
590
+ </div>
591
+
592
+ <div class="settings-option">
593
+ <div>
594
+ <div class="font-medium">Sound Effects</div>
595
+ <div class="text-xs opacity-80">Enable/disable sound effects</div>
596
+ </div>
597
+ <label class="toggle-switch">
598
+ <input type="checkbox" id="soundEffectsToggle" checked>
599
+ <span class="slider"></span>
600
+ </label>
601
+ </div>
602
+
603
+ <div class="settings-option">
604
+ <div>
605
+ <div class="font-medium">Motion Blur</div>
606
+ <div class="text-xs opacity-80">Add motion blur during warp</div>
607
+ </div>
608
+ <label class="toggle-switch">
609
+ <input type="checkbox" id="motionBlurToggle">
610
+ <span class="slider"></span>
611
+ </label>
612
+ </div>
613
+
614
+ <div class="settings-option">
615
+ <div>
616
+ <div class="font-medium">Auto Camera</div>
617
+ <div class="text-xs opacity-80">Automatically adjust camera during warp</div>
618
+ </div>
619
+ <label class="toggle-switch">
620
+ <input type="checkbox" id="autoCameraToggle" checked>
621
+ <span class="slider"></span>
622
+ </label>
623
+ </div>
624
+
625
+ <div class="mt-6">
626
+ <button id="saveSettings" class="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white py-2 px-4 rounded-lg hover:from-blue-600 hover:to-purple-700 transition-all">
627
+ SAVE SETTINGS
628
+ </button>
629
+ </div>
630
+ </div>
631
+ </div>
632
+
633
+ <!-- Information Modal -->
634
+ <div id="infoModal" class="modal">
635
+ <div class="modal-content relative">
636
+ <button class="close-modal" id="closeInfo">&times;</button>
637
+ <h2 class="text-xl font-bold mb-4 neon-text">ABOUT COSMIC JOURNEY</h2>
638
+
639
+ <div class="mb-4">
640
+ <p class="text-sm mb-2">Welcome to the Wormhole Simulator, an interactive experience that lets you travel through a theoretical Einstein-Rosen bridge.</p>
641
+ <p class="text-sm mb-2">This simulation demonstrates the visual and physical effects predicted to occur during wormhole traversal, including:</p>
642
+ <ul class="text-xs list-disc pl-5 mb-4">
643
+ <li>Gravitational lensing</li>
644
+ <li>Time dilation effects</li>
645
+ <li>Cosmic particle interactions</li>
646
+ <li>Warp field visualization</li>
647
+ </ul>
648
+ <p class="text-xs opacity-80">Version 2.1 | Quantum Physics Engine v3.4</p>
649
+ </div>
650
+
651
+ <div class="border-t border-gray-700 pt-4">
652
+ <h3 class="font-medium mb-2">CONTROLS</h3>
653
+ <div class="grid grid-cols-2 gap-2 text-xs">
654
+ <div class="flex items-center gap-2">
655
+ <div class="w-6 h-6 rounded-full bg-blue-900 flex items-center justify-center">
656
+ <i class="fas fa-play text-xs"></i>
657
+ </div>
658
+ <span>Start Journey</span>
659
+ </div>
660
+ <div class="flex items-center gap-2">
661
+ <div class="w-6 h-6 rounded-full bg-purple-900 flex items-center justify-center">
662
+ <i class="fas fa-undo text-xs"></i>
663
+ </div>
664
+ <span>Reset Simulation</span>
665
+ </div>
666
+ <div class="flex items-center gap-2">
667
+ <div class="w-6 h-6 rounded-full bg-green-900 flex items-center justify-center">
668
+ <i class="fas fa-robot text-xs"></i>
669
+ </div>
670
+ <span>Autopilot</span>
671
+ </div>
672
+ <div class="flex items-center gap-2">
673
+ <div class="w-6 h-6 rounded-full bg-pink-900 flex items-center justify-center">
674
+ <i class="fas fa-magic text-xs"></i>
675
+ </div>
676
+ <span>Effects</span>
677
+ </div>
678
+ </div>
679
+ </div>
680
+
681
+ <div class="mt-4 border-t border-gray-700 pt-4">
682
+ <h3 class="font-medium mb-2">CREDITS</h3>
683
+ <p class="text-xs">Developed by Quantum Simulations Lab<br>
684
+ Using Three.js and WebGL<br>
685
+ © 2023 Cosmic Journey Project</p>
686
  </div>
687
  </div>
688
+ </div>
689
+
690
+ <!-- Destinations Modal -->
691
+ <div id="destinationsModal" class="modal">
692
+ <div class="modal-content relative">
693
+ <button class="close-modal" id="closeDestinations">&times;</button>
694
+ <h2 class="text-xl font-bold mb-4 neon-text">SELECT DESTINATION</h2>
695
+
696
+ <div class="mb-4">
697
+ <p class="text-sm mb-4">Choose your cosmic destination from our catalog of theoretical wormhole endpoints.</p>
698
+
699
+ <div class="destination-card active" data-destination="andromeda">
700
+ <div class="flex justify-between items-center">
701
+ <div>
702
+ <h3 class="font-medium">Andromeda Galaxy</h3>
703
+ <p class="text-xs opacity-80">2.5 million light-years</p>
704
+ </div>
705
+ <i class="fas fa-check-circle text-blue-400"></i>
706
+ </div>
707
+ <div class="text-xs mt-2">
708
+ <span class="text-yellow-400">Time dilation: 4.8x</span>
709
+ </div>
710
+ </div>
711
+
712
+ <div class="destination-card" data-destination="centaurus">
713
+ <div class="flex justify-between items-center">
714
+ <div>
715
+ <h3 class="font-medium">Centaurus A</h3>
716
+ <p class="text-xs opacity-80">13 million light-years</p>
717
+ </div>
718
+ <i class="fas fa-lock text-gray-500"></i>
719
+ </div>
720
+ <div class="text-xs mt-2">
721
+ <span class="text-yellow-400">Time dilation: 8.2x</span>
722
+ </div>
723
+ </div>
724
+
725
+ <div class="destination-card" data-destination="orion">
726
+ <div class="flex justify-between items-center">
727
+ <div>
728
+ <h3 class="font-medium">Orion Nebula</h3>
729
+ <p class="text-xs opacity-80">1,344 light-years</p>
730
+ </div>
731
+ <i class="fas fa-lock text-gray-500"></i>
732
+ </div>
733
+ <div class="text-xs mt-2">
734
+ <span class="text-yellow-400">Time dilation: 1.2x</span>
735
+ </div>
736
+ </div>
737
+
738
+ <div class="destination-card" data-destination="quasar">
739
+ <div class="flex justify-between items-center">
740
+ <div>
741
+ <h3 class="font-medium">3C 273 Quasar</h3>
742
+ <p class="text-xs opacity-80">2.4 billion light-years</p>
743
+ </div>
744
+ <i class="fas fa-lock text-gray-500"></i>
745
+ </div>
746
+ <div class="text-xs mt-2">
747
+ <span class="text-yellow-400">Time dilation: 12.7x</span>
748
+ </div>
749
+ </div>
750
+ </div>
751
+
752
+ <div class="mt-4 text-xs opacity-80">
753
+ <p>Additional destinations unlock as you complete journeys.</p>
754
+ </div>
755
+
756
+ <div class="mt-6">
757
+ <button id="confirmDestination" class="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white py-2 px-4 rounded-lg hover:from-blue-600 hover:to-purple-700 transition-all">
758
+ CONFIRM DESTINATION
759
+ </button>
760
+ </div>
761
  </div>
762
  </div>
763
 
 
773
  let debrisParticles = [];
774
  let sparkParticles = [];
775
  let starParticles = [];
776
+ let powerLevel = 87;
777
+ let selectedDestination = 'andromeda';
778
+ let settings = {
779
+ particleDensity: 50,
780
+ warpEffects: true,
781
+ soundEffects: true,
782
+ motionBlur: false,
783
+ autoCamera: true
784
+ };
785
 
786
  // Initialize the scene
787
  function init() {
788
  // Create scene
789
  scene = new THREE.Scene();
790
+ scene.background = new THREE.Color(0x0a0a1a);
791
+ scene.fog = new THREE.FogExp2(0x0a0a1a, 0.002);
792
 
793
  // Create camera
794
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
 
798
  renderer = new THREE.WebGLRenderer({ antialias: true });
799
  renderer.setSize(window.innerWidth, window.innerHeight);
800
  renderer.shadowMap.enabled = true;
801
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
802
  document.getElementById('canvas').appendChild(renderer.domElement);
803
 
804
  // Add orbit controls
 
815
  directionalLight.castShadow = true;
816
  scene.add(directionalLight);
817
 
818
+ // Add colorful ambient light
819
+ const coloredLight1 = new THREE.PointLight(0x7b2dff, 0.5, 100);
820
+ coloredLight1.position.set(20, 20, 20);
821
+ scene.add(coloredLight1);
822
+
823
+ const coloredLight2 = new THREE.PointLight(0x00f0ff, 0.5, 100);
824
+ coloredLight2.position.set(-20, -20, -20);
825
+ scene.add(coloredLight2);
826
+
827
  // Create wormhole
828
  createWormhole();
829
 
 
838
  document.getElementById('startBtn').addEventListener('click', startJourney);
839
  document.getElementById('resetBtn').addEventListener('click', resetScene);
840
  document.getElementById('autoPilot').addEventListener('click', toggleAutoPilot);
841
+ document.getElementById('effectsBtn').addEventListener('click', openSettingsModal);
842
+ document.getElementById('infoBtn').addEventListener('click', openInfoModal);
843
+ document.getElementById('destinationsBtn').addEventListener('click', openDestinationsModal);
844
+ document.getElementById('closeSettings').addEventListener('click', closeSettingsModal);
845
+ document.getElementById('closeInfo').addEventListener('click', closeInfoModal);
846
+ document.getElementById('closeDestinations').addEventListener('click', closeDestinationsModal);
847
+ document.getElementById('saveSettings').addEventListener('click', saveSettings);
848
+ document.getElementById('confirmDestination').addEventListener('click', confirmDestination);
849
+
850
+ // Initialize UI elements
851
+ updateProgressBar();
852
+ updateHUD();
853
+ updatePowerLevel();
854
+ updateSystemStatus();
855
+
856
+ // Set up destination selection
857
+ setupDestinationSelection();
858
 
859
  // Start animation loop
860
  animate();
 
866
  const material = new THREE.MeshPhongMaterial({
867
  color: 0x00aaff,
868
  emissive: 0x0066ff,
869
+ emissiveIntensity: 0.8,
870
  transparent: true,
871
+ opacity: 0.9,
872
+ wireframe: true,
873
+ wireframeLinewidth: 2
874
  });
875
 
876
  wormhole = new THREE.Mesh(geometry, material);
 
882
  const innerGlowMaterial = new THREE.MeshBasicMaterial({
883
  color: 0x00aaff,
884
  transparent: true,
885
+ opacity: 0.3
886
  });
887
  const innerGlow = new THREE.Mesh(innerGlowGeometry, innerGlowMaterial);
888
  wormhole.add(innerGlow);
889
+
890
+ // Add energy field
891
+ const energyFieldGeometry = new THREE.SphereGeometry(16, 64, 64);
892
+ const energyFieldMaterial = new THREE.MeshBasicMaterial({
893
+ color: 0x7b2dff,
894
+ transparent: true,
895
+ opacity: 0.05,
896
+ wireframe: true
897
+ });
898
+ const energyField = new THREE.Mesh(energyFieldGeometry, energyFieldMaterial);
899
+ wormhole.add(energyField);
900
  }
901
 
902
  // Create spaceship
 
905
  const material = new THREE.MeshPhongMaterial({
906
  color: 0xffffff,
907
  emissive: 0xaaaaaa,
908
+ emissiveIntensity: 0.5,
909
  specular: 0x111111,
910
+ shininess: 50
911
  });
912
 
913
  ship = new THREE.Mesh(geometry, material);
 
920
  const engineGlowMaterial = new THREE.MeshBasicMaterial({
921
  color: 0x00ffff,
922
  transparent: true,
923
+ opacity: 0.9
924
  });
925
  const engineGlow = new THREE.Mesh(engineGlowGeometry, engineGlowMaterial);
926
  engineGlow.position.set(0, -1.5, 0);
927
  ship.add(engineGlow);
928
+
929
+ // Add engine trail
930
+ const trailGeometry = new THREE.CylinderGeometry(0.2, 0.8, 3, 8);
931
+ const trailMaterial = new THREE.MeshBasicMaterial({
932
+ color: 0x00aaff,
933
+ transparent: true,
934
+ opacity: 0.6,
935
+ side: THREE.DoubleSide
936
+ });
937
+ const trail = new THREE.Mesh(trailGeometry, trailMaterial);
938
+ trail.position.set(0, -3, 0);
939
+ trail.rotation.x = Math.PI / 2;
940
+ ship.add(trail);
941
  }
942
 
943
  // Create various particles
944
  function createParticles() {
945
  // Stars background
946
+ const starGeometry = new THREE.BufferGeometry();
947
+ const starMaterial = new THREE.PointsMaterial({
948
+ color: 0xffffff,
949
+ size: 0.2,
950
+ transparent: true,
951
+ opacity: 0.8
952
+ });
953
+
954
+ const starPositions = [];
955
+ const starColors = [];
956
+
957
+ for (let i = 0; i < 2000; i++) {
958
+ starPositions.push(
959
  Math.random() * 2000 - 1000,
960
  Math.random() * 2000 - 1000,
961
  Math.random() * 2000 - 1000
962
  );
963
+
964
+ // Add some color variation
965
+ const colorIntensity = 0.7 + Math.random() * 0.3;
966
+ starColors.push(
967
+ colorIntensity,
968
+ colorIntensity,
969
+ colorIntensity
970
+ );
971
  }
972
+
973
+ starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
974
+ starGeometry.setAttribute('color', new THREE.Float32BufferAttribute(starColors, 3));
975
+
976
+ const stars = new THREE.Points(starGeometry, starMaterial);
977
+ scene.add(stars);
978
+ starParticles.push(stars);
979
 
980
  // Debris
981
+ for (let i = 0; i < 150; i++) {
982
+ const size = 0.2 + Math.random() * 1.5;
983
  const debris = new THREE.Mesh(
984
  new THREE.BoxGeometry(size, size, size),
985
+ new THREE.MeshPhongMaterial({
986
+ color: 0x888888,
987
+ emissive: 0x333333,
988
+ emissiveIntensity: 0.1
989
+ })
990
  );
991
  debris.position.set(
992
  Math.random() * 100 - 50,
 
1003
  Math.random() * 0.2 - 0.1,
1004
  Math.random() * 0.2 - 0.1,
1005
  Math.random() * 0.2 - 0.1
1006
+ ),
1007
+ rotationSpeed: new THREE.Vector3(
1008
+ Math.random() * 0.02 - 0.01,
1009
+ Math.random() * 0.02 - 0.01,
1010
+ Math.random() * 0.02 - 0.01
1011
  )
1012
  };
1013
  scene.add(debris);
 
1017
 
1018
  // Create explosion effect
1019
  function createExplosion(position) {
1020
+ const explosionGeometry = new THREE.BufferGeometry();
1021
+ const explosionMaterial = new THREE.PointsMaterial({
1022
+ size: 0.3,
1023
+ vertexColors: true,
1024
+ transparent: true,
1025
+ blending: THREE.AdditiveBlending
1026
+ });
1027
+
1028
+ const explosionPositions = [];
1029
+ const explosionColors = [];
1030
+ const explosionSpeeds = [];
1031
+
1032
+ for (let i = 0; i < 100; i++) {
1033
+ explosionPositions.push(
1034
+ position.x,
1035
+ position.y,
1036
+ position.z
1037
  );
1038
+
1039
+ // Color variation from yellow to red
1040
+ const r = 0.8 + Math.random() * 0.2;
1041
+ const g = 0.3 + Math.random() * 0.3;
1042
+ const b = Math.random() * 0.2;
1043
+ explosionColors.push(r, g, b);
1044
+
1045
+ explosionSpeeds.push(
1046
+ Math.random() * 2 - 1,
1047
+ Math.random() * 2 - 1,
1048
+ Math.random() * 2 - 1
1049
+ );
1050
+ }
1051
+
1052
+ explosionGeometry.setAttribute('position', new THREE.Float32BufferAttribute(explosionPositions, 3));
1053
+ explosionGeometry.setAttribute('color', new THREE.Float32BufferAttribute(explosionColors, 3));
1054
+
1055
+ const explosion = new THREE.Points(explosionGeometry, explosionMaterial);
1056
+ explosion.userData = {
1057
+ speeds: explosionSpeeds,
1058
+ lifetime: 100 + Math.random() * 50,
1059
+ age: 0
1060
+ };
1061
+ scene.add(explosion);
1062
+ explosionParticles.push(explosion);
1063
+
1064
+ // Play explosion sound (would be implemented with Howler.js in a real app)
1065
+ if (settings.soundEffects) {
1066
+ showNotification("Cosmic anomaly detected");
1067
  }
1068
  }
1069
 
1070
  // Create spark effect
1071
  function createSparks(position) {
1072
+ const sparkGeometry = new THREE.BufferGeometry();
1073
+ const sparkMaterial = new THREE.PointsMaterial({
1074
+ color: 0xffff00,
1075
+ size: 0.1,
1076
+ transparent: true,
1077
+ blending: THREE.AdditiveBlending
1078
+ });
1079
+
1080
+ const sparkPositions = [];
1081
+ const sparkSpeeds = [];
1082
+
1083
+ for (let i = 0; i < 50; i++) {
1084
+ sparkPositions.push(
1085
+ position.x,
1086
+ position.y,
1087
+ position.z
1088
+ );
1089
+
1090
+ sparkSpeeds.push(
1091
+ Math.random() * 0.5 - 0.25,
1092
+ Math.random() * 0.5 - 0.25,
1093
+ Math.random() * 0.5 - 0.25
1094
  );
 
 
 
 
 
 
 
 
 
 
 
 
1095
  }
1096
+
1097
+ sparkGeometry.setAttribute('position', new THREE.Float32BufferAttribute(sparkPositions, 3));
1098
+
1099
+ const sparks = new THREE.Points(sparkGeometry, sparkMaterial);
1100
+ sparks.userData = {
1101
+ speeds: sparkSpeeds,
1102
+ lifetime: 50 + Math.random() * 30,
1103
+ age: 0
1104
+ };
1105
+ scene.add(sparks);
1106
+ sparkParticles.push(sparks);
1107
  }
1108
 
1109
  // Bezier curve for smooth flight path
 
1137
  if (!isAnimating) {
1138
  isAnimating = true;
1139
  journeyProgress = 0;
1140
+ document.getElementById('startBtn').classList.add('active');
1141
+ document.getElementById('phase-text').textContent = "ACCELERATION";
1142
+ showNotification("Initiating warp sequence to " + getDestinationName(selectedDestination));
1143
+
1144
+ // Activate warp effects if enabled
1145
+ if (settings.warpEffects) {
1146
+ document.getElementById('warp-effect').classList.add('active');
1147
+ }
1148
  }
1149
  }
1150
 
 
1156
  ship.position.set(0, 0, -50);
1157
  camera.position.set(0, 0, 50);
1158
  controls.reset();
1159
+ document.getElementById('startBtn').classList.remove('active');
1160
+ document.getElementById('autoPilot').classList.remove('active');
1161
+ document.getElementById('phase-text').textContent = "INITIALIZATION";
1162
+ document.getElementById('warp-effect').classList.remove('active');
1163
+ updateProgressBar();
1164
+ updateHUD();
1165
+ updatePowerLevel();
1166
+ updateSystemStatus();
1167
+ showNotification("System reset complete");
1168
  }
1169
 
1170
  // Toggle autopilot mode
1171
  function toggleAutoPilot() {
1172
  autoPilot = !autoPilot;
1173
+ const btn = document.getElementById('autoPilot');
1174
+ btn.classList.toggle('active');
1175
+ btn.innerHTML = autoPilot ? '<i class="fas fa-user-astronaut"></i>' : '<i class="fas fa-robot"></i>';
1176
+ showNotification(autoPilot ? "Autopilot engaged" : "Manual control activated");
1177
+ }
1178
+
1179
+ // Show notification
1180
+ function showNotification(message) {
1181
+ const notification = document.getElementById('notification');
1182
+ const messageElement = document.getElementById('notification-message');
1183
+
1184
+ messageElement.textContent = message;
1185
+ notification.classList.remove('hidden');
1186
+
1187
+ setTimeout(() => {
1188
+ notification.classList.add('hidden');
1189
+ }, 3000);
1190
+ }
1191
+
1192
+ // Update progress bar
1193
+ function updateProgressBar() {
1194
+ const progressBar = document.getElementById('progress-bar');
1195
+ progressBar.style.width = `${journeyProgress * 100}%`;
1196
+
1197
+ // Update phase text based on progress
1198
+ if (journeyProgress > 0.8) {
1199
+ document.getElementById('phase-text').textContent = "DECELERATION";
1200
+ } else if (journeyProgress > 0.6) {
1201
+ document.getElementById('phase-text').textContent = "STABILIZATION";
1202
+ } else if (journeyProgress > 0.3) {
1203
+ document.getElementById('phase-text').textContent = "CRUISE";
1204
+ } else if (journeyProgress > 0) {
1205
+ document.getElementById('phase-text').textContent = "ACCELERATION";
1206
+ }
1207
+ }
1208
+
1209
+ // Update HUD elements
1210
+ function updateHUD() {
1211
+ // Update speed display
1212
+ const speed = 0.7 + journeyProgress * 2.3;
1213
+ document.getElementById('speed-display').textContent = speed.toFixed(1);
1214
+
1215
+ // Update distance display
1216
+ const distance = 1.4 + journeyProgress * 8.6;
1217
+ document.getElementById('distance-display').textContent = distance.toFixed(1);
1218
+
1219
+ // Update time dilation display
1220
+ const timeDilation = 3.2 + journeyProgress * 6.8;
1221
+ document.getElementById('time-dilation-display').textContent = timeDilation.toFixed(1);
1222
+ document.getElementById('time-status').textContent = timeDilation.toFixed(1) + "x";
1223
+ }
1224
+
1225
+ // Update power level with random fluctuations
1226
+ function updatePowerLevel() {
1227
+ if (isAnimating) {
1228
+ // More dramatic fluctuations during warp
1229
+ powerLevel = 80 + Math.sin(Date.now() * 0.002) * 10 + Math.random() * 5;
1230
+ } else {
1231
+ // Small fluctuations when idle
1232
+ powerLevel = 85 + Math.sin(Date.now() * 0.001) * 2 + Math.random() * 2;
1233
+ }
1234
+
1235
+ // Ensure power level stays within bounds
1236
+ powerLevel = Math.max(0, Math.min(100, powerLevel));
1237
+
1238
+ // Update display
1239
+ document.getElementById('power-level').textContent = Math.round(powerLevel) + "% POWER";
1240
+
1241
+ // Color code based on level
1242
+ const powerElement = document.getElementById('power-level');
1243
+ if (powerLevel > 80) {
1244
+ powerElement.className = "";
1245
+ powerElement.classList.add("text-green-400");
1246
+ } else if (powerLevel > 50) {
1247
+ powerElement.className = "";
1248
+ powerElement.classList.add("text-yellow-400");
1249
+ } else {
1250
+ powerElement.className = "";
1251
+ powerElement.classList.add("text-red-400");
1252
+ }
1253
+ }
1254
+
1255
+ // Update system status with random fluctuations
1256
+ function updateSystemStatus() {
1257
+ if (isAnimating) {
1258
+ // More dramatic status during warp
1259
+ const stability = Math.sin(Date.now() * 0.001) * 0.3 + 0.7;
1260
+ const gravity = Math.sin(Date.now() * 0.0015) * 0.4 + 0.6;
1261
+ const radiation = Math.sin(Date.now() * 0.002) * 0.5 + 0.5;
1262
+
1263
+ document.getElementById('stability-status').textContent =
1264
+ stability > 0.8 ? "Optimal" : stability > 0.5 ? "Stable" : "Fluctuating";
1265
+ document.getElementById('gravity-status').textContent =
1266
+ gravity > 0.7 ? "Balanced" : gravity > 0.4 ? "Variable" : "Unstable";
1267
+ document.getElementById('radiation-status').textContent =
1268
+ radiation > 0.7 ? "High" : radiation > 0.4 ? "Moderate" : "Low";
1269
+
1270
+ // Color coding
1271
+ document.getElementById('stability-status').className =
1272
+ stability > 0.8 ? "text-green-400" : stability > 0.5 ? "text-yellow-400" : "text-red-400";
1273
+ document.getElementById('gravity-status').className =
1274
+ gravity > 0.7 ? "text-blue-400" : gravity > 0.4 ? "text-yellow-400" : "text-red-400";
1275
+ document.getElementById('radiation-status').className =
1276
+ radiation > 0.7 ? "text-red-400" : radiation > 0.4 ? "text-yellow-400" : "text-green-400";
1277
+ } else {
1278
+ // Stable status when idle
1279
+ document.getElementById('stability-status').textContent = "Optimal";
1280
+ document.getElementById('gravity-status').textContent = "Balanced";
1281
+ document.getElementById('radiation-status').textContent = "Low";
1282
+
1283
+ // Color coding
1284
+ document.getElementById('stability-status').className = "text-green-400";
1285
+ document.getElementById('gravity-status').className = "text-blue-400";
1286
+ document.getElementById('radiation-status').className = "text-green-400";
1287
+ }
1288
  }
1289
 
1290
  // Handle window resize
 
1294
  renderer.setSize(window.innerWidth, window.innerHeight);
1295
  }
1296
 
1297
+ // Modal control functions
1298
+ function openSettingsModal() {
1299
+ document.getElementById('settingsModal').classList.add('active');
1300
+ // Load current settings into form
1301
+ document.getElementById('particleDensity').value = settings.particleDensity;
1302
+ document.getElementById('warpEffectsToggle').checked = settings.warpEffects;
1303
+ document.getElementById('soundEffectsToggle').checked = settings.soundEffects;
1304
+ document.getElementById('motionBlurToggle').checked = settings.motionBlur;
1305
+ document.getElementById('autoCameraToggle').checked = settings.autoCamera;
1306
+ }
1307
+
1308
+ function closeSettingsModal() {
1309
+ document.getElementById('settingsModal').classList.remove('active');
1310
+ }
1311
+
1312
+ function openInfoModal() {
1313
+ document.getElementById('infoModal').classList.add('active');
1314
+ }
1315
+
1316
+ function closeInfoModal() {
1317
+ document.getElementById('infoModal').classList.remove('active');
1318
+ }
1319
+
1320
+ function openDestinationsModal() {
1321
+ document.getElementById('destinationsModal').classList.add('active');
1322
+ }
1323
+
1324
+ function closeDestinationsModal() {
1325
+ document.getElementById('destinationsModal').classList.remove('active');
1326
+ }
1327
+
1328
+ function saveSettings() {
1329
+ settings.particleDensity = document.getElementById('particleDensity').value;
1330
+ settings.warpEffects = document.getElementById('warpEffectsToggle').checked;
1331
+ settings.soundEffects = document.getElementById('soundEffectsToggle').checked;
1332
+ settings.motionBlur = document.getElementById('motionBlurToggle').checked;
1333
+ settings.autoCamera = document.getElementById('autoCameraToggle').checked;
1334
+
1335
+ closeSettingsModal();
1336
+ showNotification("Settings saved successfully");
1337
+ }
1338
+
1339
+ function setupDestinationSelection() {
1340
+ const cards = document.querySelectorAll('.destination-card');
1341
+ cards.forEach(card => {
1342
+ card.addEventListener('click', function() {
1343
+ if (!this.classList.contains('active') && !this.querySelector('.fa-lock')) {
1344
+ // Remove active class from all cards
1345
+ cards.forEach(c => c.classList.remove('active'));
1346
+ // Add active class to clicked card
1347
+ this.classList.add('active');
1348
+ selectedDestination = this.dataset.destination;
1349
+ }
1350
+ });
1351
+ });
1352
+ }
1353
+
1354
+ function confirmDestination() {
1355
+ closeDestinationsModal();
1356
+ showNotification(`Destination set to ${getDestinationName(selectedDestination)}`);
1357
+ }
1358
+
1359
+ function getDestinationName(dest) {
1360
+ const names = {
1361
+ 'andromeda': 'Andromeda Galaxy',
1362
+ 'centaurus': 'Centaurus A',
1363
+ 'orion': 'Orion Nebula',
1364
+ 'quasar': '3C 273 Quasar'
1365
+ };
1366
+ return names[dest] || 'Unknown Destination';
1367
+ }
1368
+
1369
  // Animation loop
1370
  function animate() {
1371
  requestAnimationFrame(animate);
 
1373
  // Update controls
1374
  controls.update();
1375
 
1376
+ // Rotate wormhole with dynamic speed
1377
+ wormhole.rotation.z += 0.005 + Math.sin(Date.now() * 0.001) * 0.002;
1378
 
1379
  // Update debris particles
1380
  debrisParticles.forEach(debris => {
1381
  debris.position.add(debris.userData.velocity);
1382
+ debris.rotation.x += debris.userData.rotationSpeed.x;
1383
+ debris.rotation.y += debris.userData.rotationSpeed.y;
1384
+ debris.rotation.z += debris.userData.rotationSpeed.z;
1385
 
1386
  // Wrap around if out of bounds
1387
  if (Math.abs(debris.position.x) > 100) debris.position.x = -debris.position.x;
 
1391
 
1392
  // Update explosion particles
1393
  for (let i = explosionParticles.length - 1; i >= 0; i--) {
1394
+ const explosion = explosionParticles[i];
1395
+ const positions = explosion.geometry.attributes.position.array;
1396
+ const speeds = explosion.userData.speeds;
1397
+
1398
+ for (let j = 0; j < positions.length; j += 3) {
1399
+ positions[j] += speeds[j];
1400
+ positions[j+1] += speeds[j+1];
1401
+ positions[j+2] += speeds[j+2];
1402
+
1403
+ // Slow down over time
1404
+ speeds[j] *= 0.98;
1405
+ speeds[j+1] *= 0.98;
1406
+ speeds[j+2] *= 0.98;
1407
+ }
1408
 
1409
+ explosion.geometry.attributes.position.needsUpdate = true;
1410
+ explosion.userData.age++;
1411
+
1412
+ // Fade out
1413
+ explosion.material.opacity = 0.8 * (1 - explosion.userData.age / explosion.userData.lifetime);
1414
+
1415
+ if (explosion.userData.age >= explosion.userData.lifetime) {
1416
+ scene.remove(explosion);
1417
  explosionParticles.splice(i, 1);
1418
  }
1419
  }
 
1421
  // Update spark particles
1422
  for (let i = sparkParticles.length - 1; i >= 0; i--) {
1423
  const spark = sparkParticles[i];
1424
+ const positions = spark.geometry.attributes.position.array;
1425
+ const speeds = spark.userData.speeds;
1426
+
1427
+ for (let j = 0; j < positions.length; j += 3) {
1428
+ positions[j] += speeds[j];
1429
+ positions[j+1] += speeds[j+1];
1430
+ positions[j+2] += speeds[j+2];
1431
+
1432
+ // Slow down over time
1433
+ speeds[j] *= 0.95;
1434
+ speeds[j+1] *= 0.95;
1435
+ speeds[j+2] *= 0.95;
1436
+ }
1437
+
1438
+ spark.geometry.attributes.position.needsUpdate = true;
1439
  spark.userData.age++;
1440
+
1441
+ // Fade out
1442
  spark.material.opacity = 0.8 * (1 - spark.userData.age / spark.userData.lifetime);
1443
 
1444
  if (spark.userData.age >= spark.userData.lifetime) {
 
1447
  }
1448
  }
1449
 
1450
+ // Randomly create explosions and sparks based on settings
1451
+ if (Math.random() < 0.02 * (settings.particleDensity / 50)) {
1452
  createExplosion(new THREE.Vector3(
1453
  Math.random() * 40 - 20,
1454
  Math.random() * 40 - 20,
 
1456
  ));
1457
  }
1458
 
1459
+ if (Math.random() < 0.05 * (settings.particleDensity / 50)) {
1460
  createSparks(new THREE.Vector3(
1461
  Math.random() * 30 - 15,
1462
  Math.random() * 30 - 15,
 
1471
  if (journeyProgress >= 1) {
1472
  journeyProgress = 1;
1473
  isAnimating = false;
1474
+ document.getElementById('phase-text').textContent = "ARRIVAL";
1475
+ document.getElementById('warp-effect').classList.remove('active');
1476
+ showNotification(`Arrived at ${getDestinationName(selectedDestination)}`);
1477
  }
1478
 
1479
  const shipPos = getBezierPoint(journeyProgress);
 
1488
  journeySpeed = 0.001 + Math.sin(Date.now() * 0.001) * 0.0005;
1489
 
1490
  // Auto camera follow in autopilot mode
1491
+ if (autoPilot && settings.autoCamera) {
1492
  const cameraOffset = new THREE.Vector3(0, 5, -10);
1493
  cameraOffset.applyQuaternion(ship.quaternion);
1494
  camera.position.copy(ship.position).add(cameraOffset);
1495
  camera.lookAt(ship.position);
1496
  }
1497
+
1498
+ // Update UI elements
1499
+ updateProgressBar();
1500
+ updateHUD();
1501
  }
1502
 
1503
+ // Update power level and system status
1504
+ updatePowerLevel();
1505
+ updateSystemStatus();
1506
+
1507
  renderer.render(scene, camera);
1508
  }
1509