akhaliq HF Staff commited on
Commit
c4c386f
Β·
verified Β·
1 Parent(s): 011ac1b

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +108 -143
index.html CHANGED
@@ -3,33 +3,23 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Enhanced Three.js Flight Simulator</title>
7
  <style>
8
  body { margin: 0; background-color: #000; overflow: hidden; }
9
  canvas { display: block; }
10
- #controls { position: absolute; top: 10px; left: 10px; background: rgba(255,255,255,0.7); padding: 10px; font-family: monospace; font-size: 14px; }
11
  #instruments { position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,0.7); color: #0F0; padding: 10px; font-family: monospace; font-size: 14px; }
12
  </style>
13
  </head>
14
  <body>
15
 
16
- <div id="controls">
17
- <b>Flight Simulator Controls:</b><br>
18
- W / ↑ : Pitch Up (Climb)<br>
19
- S / ↓ : Pitch Down (Dive)<br>
20
- A / ← : Yaw Left (Turn Left, but use roll for real turns)<br>
21
- D / β†’ : Yaw Right (Turn Right, but use roll for real turns)<br>
22
- Q / E : Roll Left/Right (Bank for turns)<br>
23
- ↑↑ Speed up (gradually)<br>
24
- ↓↓ Slow down (gradually)<br>
25
- Mouse Look (drag to change view direction)
26
- </div>
27
-
28
  <div id="instruments">
29
- <b>Flight Instruments:</b><br>
30
  Alt: <span id="altimeter">0 ft</span><br>
31
  Airspeed: <span id="airspeed">0 kts</span><br>
32
- Heading: <span id="heading">0Β°</span>
 
 
 
33
  </div>
34
 
35
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
@@ -37,7 +27,10 @@
37
  // Scene
38
  let scene = new THREE.Scene();
39
 
40
- // Skybox (gradient sky)
 
 
 
41
  let skyGeom = new THREE.SphereGeometry(500, 32, 32);
42
  let skyMat = new THREE.ShaderMaterial({
43
  vertexShader: `
@@ -49,67 +42,58 @@ let skyMat = new THREE.ShaderMaterial({
49
  }
50
  `,
51
  fragmentShader: `
 
52
  varying vec3 vWorldPosition;
53
  void main() {
54
- float heightFactor = (vWorldPosition.y + 250.0) / 500.0;
55
- heightFactor = clamp(heightFactor, 0.0, 1.0);
56
- vec3 topColor = vec3(0.1, 0.4, 0.8); // Light blue
57
- vec3 bottomColor = vec3(0.8, 0.6, 0.2); // Light brown
58
- gl_FragColor = vec4(mix(bottomColor, topColor, heightFactor), 1.0);
 
 
 
 
59
  }
60
  `,
61
- side: THREE.BackSide
 
62
  });
63
  let sky = new THREE.Mesh(skyGeom, skyMat);
64
  scene.add(sky);
65
 
66
- // Ground (simple hills)
67
- let groundGeom = new THREE.PlaneGeometry(200, 200, 64, 64);
68
- for (let i = 0; i < groundGeom.attributes.position.count; i++) {
69
- let x = groundGeom.attributes.position.getX(i);
70
- let z = groundGeom.attributes.position.getZ(i);
71
- let y = Math.sin(x * 0.1) * Math.cos(z * 0.1) * 5.0; // Simple hills
72
- groundGeom.attributes.position.setY(i, y);
 
73
  }
74
- let groundMat = new THREE.MeshLambertMaterial({ color: 0x228B22 }); // Forest green
75
- let ground = new THREE.Mesh(groundGeom, groundMat);
76
- ground.rotation.x = -Math.PI / 2;
77
- ground.receiveShadow = true;
78
- scene.add(ground);
79
 
80
- // Airplane (slightly nicer mesh)
81
  let planeGeom = new THREE.Group();
82
  let fuselageGeom = new THREE.BoxGeometry(2, 0.4, 6);
83
  let fuselageMat = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });
84
  let fuselage = new THREE.Mesh(fuselageGeom, fuselageMat);
85
  fuselage.castShadow = true;
86
  let wingGeom = new THREE.BufferGeometry();
87
- const wingVertices = new Float32Array([
88
- -2, 0, 1, 2, 0, 1, 2, 0, -2,
89
- -2, 0, 1, 2, 0, -2, -2, 0, -2,
90
- ]);
91
- let posAttr = new THREE.BufferAttribute(wingVertices, 3);
92
- wingGeom.setAttribute('position', posAttr);
93
  let wingMat = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });
94
  let wingLeft = new THREE.Mesh(wingGeom, wingMat);
95
  wingLeft.position.x = -0.5;
96
- wingLeft.castShadow = true;
97
  let wingRight = wingLeft.clone();
98
  wingRight.position.x = 0.5;
99
- let tailGeom = new THREE.BufferGeometry();
100
- const tailVertices = new Float32Array([
101
- 0, 0.5, -3, -0.5, 0, -3, 0.5, 0, -3
102
- ]);
103
- let tailAttr = new THREE.BufferAttribute(tailVertices, 3);
104
- tailGeom.setAttribute('position', tailAttr);
105
- let tailMat = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });
106
- let tail = new THREE.Mesh(tailGeom, tailMat);
107
- tail.castShadow = true;
108
  planeGeom.add(fuselage);
109
  planeGeom.add(wingLeft);
110
  planeGeom.add(wingRight);
111
- planeGeom.add(tail);
112
- scene.add(planeGeom);
113
 
114
  // Camera
115
  let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
@@ -120,14 +104,6 @@ camera.position.z = 2;
120
  // Lighting
121
  let ambientLight = new THREE.AmbientLight(0x333333);
122
  scene.add(ambientLight);
123
- let dirLight = new THREE.DirectionalLight(0xFFFFFF, 0.8);
124
- dirLight.position.set(10, 20, 10);
125
- dirLight.castShadow = true;
126
- dirLight.shadow.mapSize.width = 2048;
127
- dirLight.shadow.mapSize.height = 2048;
128
- dirLight.shadow.camera.near = 1;
129
- dirLight.shadow.camera.far = 100;
130
- scene.add(dirLight);
131
 
132
  // Renderer
133
  let renderer = new THREE.WebGLRenderer({ antialias: true });
@@ -136,124 +112,113 @@ renderer.shadowMap.enabled = true;
136
  document.body.appendChild(renderer.domElement);
137
 
138
  // Flight dynamics
139
- let pitch = 0; // radians
140
- let yaw = 0;
141
- let roll = 0;
142
- let velocity = new THREE.Vector3(0, 0, 0); // m/s
143
- let airspeed = 0; // knots
144
- let altitude = 0; // meters
145
- let heading = 0; // degrees
146
- let liftForce = 0;
147
- let dragForce = 0;
148
- let gravity = new THREE.Vector3(0, -9.81, 0); // m/sΒ²
149
- let mass = 1000; // kg (just a number)
150
- let wingLiftCoefficient = 10.0; // Made-up lift coeff
151
- let dragCoefficient = 0.5; // Parasitic drag
152
- let maxStallAngle = Math.PI / 6; // 30 degrees
153
-
154
- // Controls state
155
- let keys = {
156
- w: false, s: false, a: false, d: false, q: false, e: false
157
- };
158
  document.addEventListener('keydown', (e) => {
159
  switch (e.key) {
160
- case 'w': case 'ArrowUp': keys.w = true; break;
161
- case 's': case 'ArrowDown': keys.s = true; break;
162
- case 'a': case 'ArrowLeft': keys.a = true; break;
163
- case 'd': case 'ArrowRight': keys.d = true; break;
164
  case 'q': keys.q = true; break;
165
  case 'e': keys.e = true; break;
 
166
  }
167
  });
168
  document.addEventListener('keyup', (e) => {
169
  switch (e.key) {
170
- case 'w': case 'ArrowUp': keys.w = false; break;
171
- case 's': case 'ArrowDown': keys.s = false; break;
172
- case 'a': case 'ArrowLeft': keys.a = false; break;
173
- case 'd': case 'ArrowRight': keys.d = false; break;
174
  case 'q': keys.q = false; break;
175
  case 'e': keys.e = false; break;
176
  }
177
  });
178
 
179
- // Mouse look
180
- let mouseDown = false;
181
- let lastMouseX, lastMouseY;
182
- let sensitivity = 0.005;
183
- document.addEventListener('mousedown', (e) => {
184
- mouseDown = true;
185
- lastMouseX = e.clientX;
186
- lastMouseY = e.clientY;
187
- });
188
- document.addEventListener('mouseup', () => mouseDown = false);
189
- document.addEventListener('mousemove', (e) => {
190
- if (mouseDown) {
191
- let dx = e.clientX - lastMouseX;
192
- let dy = e.clientY - lastMouseY;
193
- yaw -= dx * sensitivity;
194
- pitch -= dy * sensitivity;
195
- pitch = Math.max(-Math.PI/2, Math.min(Math.PI/2, pitch));
196
- lastMouseX = e.clientX;
197
- lastMouseY = e.clientY;
198
- }
199
- });
200
-
201
- // Update instruments display
202
  function updateInstruments() {
203
- document.getElementById('altimeter').innerText = Math.round(altitude * 3.28084) + ' ft'; // meters to feet
204
- document.getElementById('airspeed').innerText = Math.round(airspeed) + ' kts';
205
- document.getElementById('heading').innerText = Math.round(THREE.Math.radToDeg(yaw)) % 360 + 'Β°';
 
 
 
206
  }
207
 
208
- // Main loop
209
  function animate() {
210
  requestAnimationFrame(animate);
211
 
 
 
 
 
 
 
 
 
 
 
212
  // Aerodynamics
213
- let velocityDir = new THREE.Vector3(0, 0, -1); // Plane's forward in local space
214
- velocityDir.applyQuaternion(planeGeom.quaternion).normalize();
215
- airspeed = velocity.length() * 1.94384; // m/s to knots (approx)
216
- let angleOfAttack = Math.acos(velocityDir.dot(new THREE.Vector3(0, 1, 0).applyQuaternion(planeGeom.quaternion)));
217
- liftForce = wingLiftCoefficient * airspeed * airspeed * Math.sin(angleOfAttack);
218
- if (angleOfAttack > maxStallAngle) liftForce *= (1 - (angleOfAttack - maxStallAngle) / (Math.PI / 2 - maxStallAngle)); // Stall
219
- dragForce = dragCoefficient * airspeed * airspeed;
220
 
221
  // Forces
222
- let lift = new THREE.Vector3(0, liftForce, 0).applyQuaternion(planeGeom.quaternion); // Lift always perpendicular to wings
223
- let drag = velocityDir.clone().multiplyScalar(-dragForce);
224
- let totalForce = new THREE.Vector3().add(gravity).add(lift).add(drag).divideScalar(mass);
 
225
 
226
- // Update velocity & position (Verlet-ish integration)
227
- velocity.add(totalForce.multiplyScalar(1/60)); // dt ~= 1/60s
228
  planeGeom.position.add(velocity.clone().multiplyScalar(1/60));
229
 
230
- // Collision with ground (very crude)
231
- altitude = planeGeom.position.y - groundGeom.attributes.position.getY(0); // approx
232
- if (altitude < 0) {
233
- planeGeom.position.y += -altitude; // push back up
234
- velocity.y = Math.max(0, velocity.y * 0.8); // dampen bounce
 
235
  }
236
 
237
  // Controls
238
- if (keys.w) pitch -= 0.005;
239
- if (keys.s) pitch += 0.005;
240
  if (keys.a) yaw -= 0.01;
241
  if (keys.d) yaw += 0.01;
242
  if (keys.q) roll -= 0.02;
243
  if (keys.e) roll += 0.02;
 
 
244
 
245
- // Limit angles
246
- pitch = Math.max(-Math.PI/3, Math.min(Math.PI/4, pitch)); // less extreme pitch
247
- roll = Math.max(-Math.PI/4, Math.min(Math.PI/4, roll));
248
-
249
- // Apply rotations (order matters)
250
- planeGeom.rotation.order = 'ZXY'; // Roll, Pitch, Yaw (aviation standard)
251
  planeGeom.rotation.z = roll;
252
  planeGeom.rotation.x = pitch;
253
  planeGeom.rotation.y = yaw;
254
 
255
- // Update camera direction (following plane's rotation)
256
- heading = THREE.Math.radToDeg(yaw) % 360;
 
 
 
 
 
257
 
258
  updateInstruments();
259
  renderer.render(scene, camera);
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Ultimate Three.js Flight Simulator</title>
7
  <style>
8
  body { margin: 0; background-color: #000; overflow: hidden; }
9
  canvas { display: block; }
 
10
  #instruments { position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,0.7); color: #0F0; padding: 10px; font-family: monospace; font-size: 14px; }
11
  </style>
12
  </head>
13
  <body>
14
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  <div id="instruments">
16
+ <b>Cockpit Instruments:</b><br>
17
  Alt: <span id="altimeter">0 ft</span><br>
18
  Airspeed: <span id="airspeed">0 kts</span><br>
19
+ Heading: <span id="heading">0Β°</span><br>
20
+ RPM: <span id="rpm">0</span><br>
21
+ Fuel: <span id="fuel">100%</span><br>
22
+ Flaps: <span id="flaps">0%</span>
23
  </div>
24
 
25
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
 
27
  // Scene
28
  let scene = new THREE.Scene();
29
 
30
+ // Skybox with sun (gradient sky)
31
+ let sun = new THREE.DirectionalLight(0xFFFFFF, 1);
32
+ sun.position.set(100, 100, 100);
33
+ scene.add(sun);
34
  let skyGeom = new THREE.SphereGeometry(500, 32, 32);
35
  let skyMat = new THREE.ShaderMaterial({
36
  vertexShader: `
 
42
  }
43
  `,
44
  fragmentShader: `
45
+ uniform vec3 sunPosition;
46
  varying vec3 vWorldPosition;
47
  void main() {
48
+ vec3 viewDirection = normalize(vWorldPosition);
49
+ vec3 sunDir = normalize(sunPosition);
50
+ float sunDot = max(dot(viewDirection, sunDir), 0.0);
51
+ vec3 dayColor = vec3(0.2, 0.5, 1.0); // Blue sky
52
+ vec3 sunsetColor = vec3(1.0, 0.5, 0.2); // Orange
53
+ vec3 nightColor = vec3(0.05, 0.05, 0.1); // Dark blue
54
+ float sunHeight = sunPosition.y / 100.0;
55
+ vec3 skyColor = mix(nightColor, mix(sunsetColor, dayColor, sunHeight), smoothstep(-0.1, 0.1, sunHeight));
56
+ gl_FragColor = vec4(skyColor + sunDot * 0.5, 1.0);
57
  }
58
  `,
59
+ side: THREE.BackSide,
60
+ uniforms: { sunPosition: { value: sun.position } }
61
  });
62
  let sky = new THREE.Mesh(skyGeom, skyMat);
63
  scene.add(sky);
64
 
65
+ // Terrain (Perlin noise hills)
66
+ let terrainSize = 256;
67
+ let terrainGeom = new THREE.PlaneGeometry(200, 200, terrainSize, terrainSize);
68
+ for (let i = 0; i < terrainGeom.attributes.position.count; i++) {
69
+ let x = terrainGeom.attributes.position.getX(i);
70
+ let z = terrainGeom.attributes.position.getZ(i);
71
+ let noise = (Math.sin(x * 0.1) + Math.sin(z * 0.1)) * 5 + (Math.random() * 2 - 1) * 2; // Simple noise
72
+ terrainGeom.attributes.position.setY(i, noise);
73
  }
74
+ let terrainMat = new THREE.MeshLambertMaterial({ color: 0x228B22 });
75
+ let terrain = new THREE.Mesh(terrainGeom, terrainMat);
76
+ terrain.rotation.x = -Math.PI / 2;
77
+ terrain.receiveShadow = true;
78
+ scene.add(terrain);
79
 
80
+ // Airplane (detailed mesh)
81
  let planeGeom = new THREE.Group();
82
  let fuselageGeom = new THREE.BoxGeometry(2, 0.4, 6);
83
  let fuselageMat = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });
84
  let fuselage = new THREE.Mesh(fuselageGeom, fuselageMat);
85
  fuselage.castShadow = true;
86
  let wingGeom = new THREE.BufferGeometry();
87
+ // ... (same wing vertices as before)
 
 
 
 
 
88
  let wingMat = new THREE.MeshLambertMaterial({ color: 0xFFFFFF });
89
  let wingLeft = new THREE.Mesh(wingGeom, wingMat);
90
  wingLeft.position.x = -0.5;
 
91
  let wingRight = wingLeft.clone();
92
  wingRight.position.x = 0.5;
 
 
 
 
 
 
 
 
 
93
  planeGeom.add(fuselage);
94
  planeGeom.add(wingLeft);
95
  planeGeom.add(wingRight);
96
+ // ... (add tail, wheels)
 
97
 
98
  // Camera
99
  let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
 
104
  // Lighting
105
  let ambientLight = new THREE.AmbientLight(0x333333);
106
  scene.add(ambientLight);
 
 
 
 
 
 
 
 
107
 
108
  // Renderer
109
  let renderer = new THREE.WebGLRenderer({ antialias: true });
 
112
  document.body.appendChild(renderer.domElement);
113
 
114
  // Flight dynamics
115
+ let mass = 1500; // kg
116
+ let wingArea = 10; // mΒ²
117
+ let wingLiftCoeff = 5.0;
118
+ let dragCoeff = 0.5;
119
+ let thrustMax = 5000; // Newtons (engine force)
120
+ let thrust = 0;
121
+ let rpm = 0;
122
+ let fuel = 100; // %
123
+ let flapsDeploy = 0; // 0-100%
124
+ let velocity = new THREE.Vector3();
125
+ let wind = new THREE.Vector3((Math.random() * 2 - 1) * 5, 0, (Math.random() * 2 - 1) * 5); // m/s
126
+
127
+ // Controls
128
+ let keys = { w: false, s: false, a: false, d: false, q: false, e: false, f: false };
 
 
 
 
 
129
  document.addEventListener('keydown', (e) => {
130
  switch (e.key) {
131
+ case 'w': keys.w = true; break;
132
+ case 's': keys.s = true; break;
133
+ case 'a': keys.a = true; break;
134
+ case 'd': keys.d = true; break;
135
  case 'q': keys.q = true; break;
136
  case 'e': keys.e = true; break;
137
+ case 'f': if (flapsDeploy < 100) flapsDeploy += 10; break;
138
  }
139
  });
140
  document.addEventListener('keyup', (e) => {
141
  switch (e.key) {
142
+ case 'w': keys.w = false; break;
143
+ case 's': keys.s = false; break;
144
+ case 'a': keys.a = false; break;
145
+ case 'd': keys.d = false; break;
146
  case 'q': keys.q = false; break;
147
  case 'e': keys.e = false; break;
148
  }
149
  });
150
 
151
+ // Instruments update
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  function updateInstruments() {
153
+ document.getElementById('altimeter').innerText = Math.round(planeGeom.position.y * 3.28084) + ' ft';
154
+ document.getElementById('airspeed').innerText = Math.round(velocity.length() * 1.94384) + ' kts';
155
+ document.getElementById('heading').innerText = Math.round(THREE.Math.radToDeg(planeGeom.rotation.y)) % 360 + 'Β°';
156
+ document.getElementById('rpm').innerText = Math.round(rpm);
157
+ document.getElementById('fuel').innerText = Math.round(fuel) + '%';
158
+ document.getElementById('flaps').innerText = flapsDeploy + '%';
159
  }
160
 
161
+ let pitch = 0, yaw = 0, roll = 0;
162
  function animate() {
163
  requestAnimationFrame(animate);
164
 
165
+ // Engine
166
+ if (keys.w && fuel > 0) {
167
+ thrust = Math.min(thrustMax, thrust + 100);
168
+ rpm = Math.min(2500, rpm + 50);
169
+ fuel -= 0.05; // Consume fuel
170
+ } else {
171
+ thrust = Math.max(0, thrust - 100);
172
+ rpm = Math.max(0, rpm - 50);
173
+ }
174
+
175
  // Aerodynamics
176
+ let airspeedVec = velocity.clone().sub(wind); // Relative airspeed
177
+ let airspeed = airspeedVec.length();
178
+ let angleOfAttack = Math.acos(airspeedVec.dot(new THREE.Vector3(0, 1, 0).applyQuaternion(planeGeom.quaternion)));
179
+ let lift = 0.5 * 1.225 * wingArea * wingLiftCoeff * airspeed * airspeed * Math.sin(angleOfAttack) * (1 + flapsDeploy / 100);
180
+ let drag = 0.5 * 1.225 * dragCoeff * wingArea * airspeed * airspeed;
181
+ if (angleOfAttack > Math.PI / 4) lift *= 0.5; // Stall
 
182
 
183
  // Forces
184
+ let liftVec = new THREE.Vector3(0, lift, 0).applyQuaternion(planeGeom.quaternion);
185
+ let dragVec = airspeedVec.clone().multiplyScalar(-drag / airspeed);
186
+ let thrustVec = new THREE.Vector3(0, 0, thrust).applyQuaternion(planeGeom.quaternion);
187
+ let totalForce = new THREE.Vector3().add(liftVec).add(dragVec).add(thrustVec).add(new THREE.Vector3(0, -mass * 9.81, 0));
188
 
189
+ // Update velocity & position
190
+ velocity.add(totalForce.divideScalar(mass).multiplyScalar(1/60));
191
  planeGeom.position.add(velocity.clone().multiplyScalar(1/60));
192
 
193
+ // Collision (raycast down)
194
+ let raycaster = new THREE.Raycaster(planeGeom.position, new THREE.Vector3(0, -1, 0));
195
+ let intersects = raycaster.intersectObject(terrain);
196
+ if (intersects.length > 0 && intersects[0].distance < 5) {
197
+ planeGeom.position.y = intersects[0].point.y + 2; // Don't go through ground
198
+ velocity.y = Math.max(0, velocity.y * 0.8);
199
  }
200
 
201
  // Controls
 
 
202
  if (keys.a) yaw -= 0.01;
203
  if (keys.d) yaw += 0.01;
204
  if (keys.q) roll -= 0.02;
205
  if (keys.e) roll += 0.02;
206
+ if (keys.s) pitch += 0.005;
207
+ if (keys.w) pitch -= 0.005;
208
 
209
+ // Apply rotations
210
+ planeGeom.rotation.order = 'ZXY';
 
 
 
 
211
  planeGeom.rotation.z = roll;
212
  planeGeom.rotation.x = pitch;
213
  planeGeom.rotation.y = yaw;
214
 
215
+ // Update sun position (day/night cycle)
216
+ let time = Date.now() * 0.00005;
217
+ sun.position.x = Math.sin(time) * 100;
218
+ sun.position.z = Math.cos(time) * 100;
219
+ sun.position.y = Math.sin(time * 0.5) * 50 + 50; // Rise/set
220
+ skyMat.uniforms.sunPosition.value.copy(sun.position);
221
+ ambientLight.intensity = 0.2 + sun.position.y / 200;
222
 
223
  updateInstruments();
224
  renderer.render(scene, camera);