enzostvs HF staff commited on
Commit
7fa5a96
·
verified ·
1 Parent(s): fd81989

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +295 -111
index.html CHANGED
@@ -95,9 +95,9 @@
95
  // Game configuration
96
  const config = {
97
  roadLength: 10000,
98
- roadWidth: 10,
99
- playerSpeed: 0.2,
100
- trafficSpeed: 0.3,
101
  colors: [
102
  { color: 0xff0000, name: "Red" },
103
  { color: 0x0000ff, name: "Blue" },
@@ -105,11 +105,21 @@
105
  { color: 0x000000, name: "Black" },
106
  { color: 0x800080, name: "Purple" },
107
  { color: 0xa52a2a, name: "Brown" },
 
 
108
  ],
109
- maxTrafficCars: 30,
110
- lanePositions: [-3.5, 0, 3.5],
 
 
 
 
 
 
 
 
 
111
  };
112
-
113
  // Game state
114
  const state = {
115
  score: 0,
@@ -122,7 +132,7 @@
122
 
123
  // Scene, camera, and renderer setup
124
  const scene = new THREE.Scene();
125
- scene.fog = new THREE.Fog(0x87ceeb, 10, 50);
126
  const camera = new THREE.PerspectiveCamera(
127
  75,
128
  window.innerWidth / window.innerHeight,
@@ -136,79 +146,168 @@
136
  // Lighting
137
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
138
  scene.add(ambientLight);
139
-
140
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
141
  directionalLight.position.set(0, 10, 0);
142
  scene.add(directionalLight);
143
 
144
- // Create a car model
145
- function createCarModel(color, isPlayer = false) {
 
146
  const group = new THREE.Group();
 
147
 
148
- // Adjust the base height to ensure wheels are above the road
149
- const carHeight = 0.6;
150
-
151
- // Base of the car
152
- const baseGeometry = new THREE.BoxGeometry(1, 0.4, 2);
 
153
  const baseMaterial = new THREE.MeshPhongMaterial({ color: color });
154
  const base = new THREE.Mesh(baseGeometry, baseMaterial);
155
- base.position.y = carHeight - 0.2;
156
  group.add(base);
157
 
158
- // Roof
159
- const roofGeometry = new THREE.BoxGeometry(0.8, 0.4, 1.5);
160
- const roofMaterial = new THREE.MeshPhongMaterial({
161
- color: isPlayer ? 0xff4500 : color,
162
- opacity: 1,
163
- transparent: false,
164
- });
165
- const roof = new THREE.Mesh(roofGeometry, roofMaterial);
166
- roof.position.y = carHeight + 0.2;
167
- group.add(roof);
168
-
169
- // Windows
170
- const windowMaterial = new THREE.MeshPhongMaterial({
171
- color: 0x87ceeb,
172
- opacity: 0.7,
173
- transparent: true,
174
- });
175
-
176
- const windowFront = new THREE.Mesh(
177
- new THREE.PlaneGeometry(0.8, 0.4),
178
- windowMaterial
179
- );
180
- windowFront.rotation.y = Math.PI / 2;
181
- windowFront.position.set(0.51, carHeight + 0.2, 0);
182
- group.add(windowFront);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
- const windowBack = windowFront.clone();
185
- windowBack.position.set(-0.51, carHeight + 0.2, 0);
186
- group.add(windowBack);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
  // Wheels
189
- const wheelGeometry = new THREE.CylinderGeometry(0.2, 0.2, 0.2, 16);
 
 
 
 
 
 
190
  const wheelMaterial = new THREE.MeshPhongMaterial({ color: 0x000000 });
191
 
192
- // Front left wheel
193
- const wheelFL = new THREE.Mesh(wheelGeometry, wheelMaterial);
194
- wheelFL.rotation.z = Math.PI / 2;
195
- wheelFL.position.set(-0.4, carHeight - 0.4, 0.7);
196
- group.add(wheelFL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
- // Front right wheel
199
- const wheelFR = wheelFL.clone();
200
- wheelFR.position.set(0.4, carHeight - 0.4, 0.7);
201
- group.add(wheelFR);
 
 
202
 
203
- // Back left wheel
204
- const wheelBL = wheelFL.clone();
205
- wheelBL.position.set(-0.4, carHeight - 0.4, -0.7);
206
- group.add(wheelBL);
207
 
208
- // Back right wheel
209
- const wheelBR = wheelFL.clone();
210
- wheelBR.position.set(0.4, carHeight - 0.4, -0.7);
211
- group.add(wheelBR);
 
 
 
 
212
 
213
  return group;
214
  }
@@ -232,52 +331,114 @@
232
  road.rotation.x = -Math.PI / 2;
233
  scene.add(road);
234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  // Player Car
236
  const playerColor = 0xff0000;
237
- const playerCar = createCarModel(playerColor, true);
238
  playerCar.position.y = 0;
239
  scene.add(playerCar);
240
 
241
- // Traffic Cars
242
- const trafficCars = [];
243
- function createTrafficCar() {
 
 
 
 
 
244
  const colorObj =
245
  config.colors[Math.floor(Math.random() * config.colors.length)];
246
- const car = createCarModel(colorObj.color);
247
 
248
- // Randomize lane position
249
- car.position.x =
250
- config.lanePositions[
251
- Math.floor(Math.random() * config.lanePositions.length)
252
- ];
253
 
254
- // Stagger car positions
255
- car.position.z = (-Math.random() * config.roadLength) / 2;
 
 
 
 
 
 
256
 
257
- scene.add(car);
258
- trafficCars.push(car);
 
 
 
 
259
  }
260
 
261
  // Spawn initial traffic
262
  function initTraffic() {
263
- for (let i = 0; i < config.maxTrafficCars; i++) {
264
- createTrafficCar();
 
265
  }
266
  }
267
 
268
  // Camera positioning
269
- camera.position.y = 2;
270
- camera.position.z = 5;
271
  camera.lookAt(playerCar.position);
272
 
273
- // Collision detection
274
  function checkCollisions() {
275
- trafficCars.forEach((car) => {
276
- const distance = playerCar.position.distanceTo(car.position);
277
- if (distance < 1) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  endGame();
 
279
  }
280
- });
281
  }
282
 
283
  // Format time to MM:SS
@@ -304,13 +465,13 @@
304
 
305
  if (
306
  keys["ArrowLeft"] &&
307
- playerCar.position.x > -(config.roadWidth / 2 - 0.5)
308
  ) {
309
  playerCar.position.x -= config.playerSpeed;
310
  }
311
  if (
312
  keys["ArrowRight"] &&
313
- playerCar.position.x < config.roadWidth / 2 - 0.5
314
  ) {
315
  playerCar.position.x += config.playerSpeed;
316
  }
@@ -326,21 +487,41 @@
326
  }
327
  }
328
 
329
- // Update traffic cars
330
- function updateTrafficCars() {
331
  // Increase difficulty based on score and time
332
  state.difficultyMultiplier =
333
- 1 + state.score / 1000 + state.elapsedTime / 60000;
334
-
335
- trafficCars.forEach((car, index) => {
336
- // Move cars forward with increasing speed
337
- car.position.z += config.trafficSpeed * state.difficultyMultiplier;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
 
339
- // Remove cars that are out of view and create new ones
340
- if (car.position.z > 10) {
341
- scene.remove(car);
342
- trafficCars.splice(index, 1);
343
- createTrafficCar();
344
  }
345
  });
346
  }
@@ -356,16 +537,21 @@
356
  // Animation loop
357
  function animate() {
358
  requestAnimationFrame(animate);
359
-
360
  updatePlayerMovement();
361
- updateTrafficCars();
362
  checkCollisions();
363
  updateTimer();
364
 
365
  // Update camera to follow player
366
  camera.position.x = playerCar.position.x;
367
- camera.position.z = playerCar.position.z + 5;
368
- camera.lookAt(playerCar.position);
 
 
 
 
 
 
369
 
370
  renderer.render(scene, camera);
371
  }
@@ -384,13 +570,13 @@
384
  document.getElementById("gameOverScreen").style.display = "none";
385
  document.getElementById("hud").style.display = "block";
386
 
387
- // Reset player and traffic positions
388
  playerCar.position.x = 0;
389
  playerCar.position.z = 0;
390
 
391
  // Clear existing traffic
392
- trafficCars.forEach((car) => scene.remove(car));
393
- trafficCars.length = 0;
394
 
395
  // Respawn traffic
396
  initTraffic();
@@ -407,15 +593,13 @@
407
  function endGame() {
408
  state.gameOver = true;
409
 
410
- // Stop rendering
411
- cancelAnimationFrame(animate);
412
-
413
  // Show game over screen
414
  document.getElementById("hud").style.display = "none";
415
  document.getElementById("gameOverScreen").style.display = "flex";
416
  document.getElementById("finalScore").textContent = `Score: ${
417
  state.score
418
- }\nTime: ${formatTime(state.elapsedTime)}`;
 
419
  }
420
 
421
  // Event Listeners
@@ -434,4 +618,4 @@
434
  });
435
  </script>
436
  </body>
437
- </html>
 
95
  // Game configuration
96
  const config = {
97
  roadLength: 10000,
98
+ roadWidth: 15, // Wider road for 3 lanes
99
+ playerSpeed: 0.3, // Decreased player speed
100
+ trafficSpeed: 0.8, // Increased base traffic speed
101
  colors: [
102
  { color: 0xff0000, name: "Red" },
103
  { color: 0x0000ff, name: "Blue" },
 
105
  { color: 0x000000, name: "Black" },
106
  { color: 0x800080, name: "Purple" },
107
  { color: 0xa52a2a, name: "Brown" },
108
+ { color: 0xffa500, name: "Orange" },
109
+ { color: 0xffff00, name: "Yellow" },
110
  ],
111
+ maxTrafficVehicles: 220, // Increased for more traffic
112
+ clusterChance: 0.9, // Chance of creating a vehicle cluster
113
+ clusterSize: { min: 2, max: 5 }, // Range of vehicles in a cluster
114
+ clusterSpacing: { min: 3, max: 5 }, // Spacing between vehicles in a cluster
115
+ lanePositions: [-5, 0, 5], // Three lanes
116
+ vehicleTypes: ["car", "bus", "truck"],
117
+ vehicleProperties: {
118
+ car: { length: 2, width: 1, height: 0.8, speed: 1.1 }, // Increased speed
119
+ bus: { length: 3.5, width: 1.2, height: 1.2, speed: 1 }, // Increased speed
120
+ truck: { length: 4, width: 1.3, height: 1.5, speed: 0.9 }, // Increased speed
121
+ },
122
  };
 
123
  // Game state
124
  const state = {
125
  score: 0,
 
132
 
133
  // Scene, camera, and renderer setup
134
  const scene = new THREE.Scene();
135
+ scene.fog = new THREE.Fog(0x87ceeb, 10, 70);
136
  const camera = new THREE.PerspectiveCamera(
137
  75,
138
  window.innerWidth / window.innerHeight,
 
146
  // Lighting
147
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
148
  scene.add(ambientLight);
 
149
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
150
  directionalLight.position.set(0, 10, 0);
151
  scene.add(directionalLight);
152
 
153
+ // Create vehicle models
154
+ function createVehicleModel(type, color, isPlayer = false) {
155
+ const props = config.vehicleProperties[type];
156
  const group = new THREE.Group();
157
+ const baseHeight = 0.6;
158
 
159
+ // Base of the vehicle
160
+ const baseGeometry = new THREE.BoxGeometry(
161
+ props.width,
162
+ props.height * 0.5,
163
+ props.length
164
+ );
165
  const baseMaterial = new THREE.MeshPhongMaterial({ color: color });
166
  const base = new THREE.Mesh(baseGeometry, baseMaterial);
167
+ base.position.y = baseHeight;
168
  group.add(base);
169
 
170
+ // Roof - different for each type
171
+ if (type === "car") {
172
+ const roofGeometry = new THREE.BoxGeometry(
173
+ props.width * 0.8,
174
+ props.height * 0.5,
175
+ props.length * 0.75
176
+ );
177
+ const roofMaterial = new THREE.MeshPhongMaterial({
178
+ color: isPlayer ? 0xff4500 : color,
179
+ opacity: 1,
180
+ transparent: false,
181
+ });
182
+ const roof = new THREE.Mesh(roofGeometry, roofMaterial);
183
+ roof.position.y = baseHeight + props.height * 0.5;
184
+ group.add(roof);
185
+ } else if (type === "bus") {
186
+ const roofGeometry = new THREE.BoxGeometry(
187
+ props.width,
188
+ props.height * 0.5,
189
+ props.length * 0.95
190
+ );
191
+ const roofMaterial = new THREE.MeshPhongMaterial({
192
+ color: isPlayer ? 0xff4500 : color,
193
+ });
194
+ const roof = new THREE.Mesh(roofGeometry, roofMaterial);
195
+ roof.position.y = baseHeight + props.height * 0.5;
196
+ group.add(roof);
197
+ } else if (type === "truck") {
198
+ // Cab for truck
199
+ const cabGeometry = new THREE.BoxGeometry(
200
+ props.width,
201
+ props.height * 0.7,
202
+ props.length * 0.3
203
+ );
204
+ const cabMaterial = new THREE.MeshPhongMaterial({
205
+ color: isPlayer ? 0xff4500 : color,
206
+ });
207
+ const cab = new THREE.Mesh(cabGeometry, cabMaterial);
208
+ cab.position.y = baseHeight + props.height * 0.35;
209
+ cab.position.z = props.length * 0.35;
210
+ group.add(cab);
211
+
212
+ // Cargo container
213
+ const cargoGeometry = new THREE.BoxGeometry(
214
+ props.width * 1.1,
215
+ props.height * 1,
216
+ props.length * 0.65
217
+ );
218
+ const cargoMaterial = new THREE.MeshPhongMaterial({
219
+ color: 0x888888,
220
+ });
221
+ const cargo = new THREE.Mesh(cargoGeometry, cargoMaterial);
222
+ cargo.position.y = baseHeight + props.height * 0.5;
223
+ cargo.position.z = -props.length * 0.17;
224
+ group.add(cargo);
225
+ }
226
 
227
+ // Windows (for cars and buses)
228
+ if (type !== "truck") {
229
+ const windowMaterial = new THREE.MeshPhongMaterial({
230
+ color: 0x87ceeb,
231
+ opacity: 0.7,
232
+ transparent: true,
233
+ });
234
+
235
+ // Side windows
236
+ const windowSize = type === "car" ? 0.4 : 0.6;
237
+ const windowFront = new THREE.Mesh(
238
+ new THREE.PlaneGeometry(props.width * 0.9, windowSize),
239
+ windowMaterial
240
+ );
241
+ windowFront.rotation.y = Math.PI / 2;
242
+ windowFront.position.set(
243
+ props.width / 2 + 0.01,
244
+ baseHeight + props.height * 0.5,
245
+ 0
246
+ );
247
+ group.add(windowFront);
248
+
249
+ const windowBack = windowFront.clone();
250
+ windowBack.position.set(
251
+ -props.width / 2 - 0.01,
252
+ baseHeight + props.height * 0.5,
253
+ 0
254
+ );
255
+ windowBack.rotation.y = -Math.PI / 2;
256
+ group.add(windowBack);
257
+ }
258
 
259
  // Wheels
260
+ const wheelRadius = type === "car" ? 0.2 : 0.3;
261
+ const wheelGeometry = new THREE.CylinderGeometry(
262
+ wheelRadius,
263
+ wheelRadius,
264
+ 0.2,
265
+ 16
266
+ );
267
  const wheelMaterial = new THREE.MeshPhongMaterial({ color: 0x000000 });
268
 
269
+ // Position wheels based on vehicle type
270
+ const wheelOffsetX = (props.width / 2) * 0.8;
271
+ const wheelOffsetY = baseHeight - props.height * 0.3;
272
+ let wheelZPositions;
273
+
274
+ if (type === "car") {
275
+ wheelZPositions = [props.length / 2 - 0.3, -props.length / 2 + 0.3];
276
+ } else if (type === "bus") {
277
+ wheelZPositions = [
278
+ props.length / 2 - 0.5,
279
+ 0,
280
+ -props.length / 2 + 0.5,
281
+ ];
282
+ } else {
283
+ // truck
284
+ wheelZPositions = [
285
+ props.length / 2 - 0.5,
286
+ 0,
287
+ -props.length / 2 + 0.5,
288
+ ];
289
+ }
290
 
291
+ // Add wheels
292
+ wheelZPositions.forEach((zPos) => {
293
+ const wheelLeft = new THREE.Mesh(wheelGeometry, wheelMaterial);
294
+ wheelLeft.rotation.z = Math.PI / 2;
295
+ wheelLeft.position.set(-wheelOffsetX, wheelOffsetY, zPos);
296
+ group.add(wheelLeft);
297
 
298
+ const wheelRight = wheelLeft.clone();
299
+ wheelRight.position.set(wheelOffsetX, wheelOffsetY, zPos);
300
+ group.add(wheelRight);
301
+ });
302
 
303
+ // Add collision box
304
+ group.userData = {
305
+ type: type,
306
+ width: props.width,
307
+ length: props.length,
308
+ speed: props.speed,
309
+ boundingBox: new THREE.Box3().setFromObject(group),
310
+ };
311
 
312
  return group;
313
  }
 
331
  road.rotation.x = -Math.PI / 2;
332
  scene.add(road);
333
 
334
+ // Lane markings
335
+ function createLaneMarkings() {
336
+ // Lane dividers
337
+ for (let i = -1; i <= 1; i += 2) {
338
+ const lineGeometry = new THREE.PlaneGeometry(0.15, config.roadLength);
339
+ const lineMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
340
+ const line = new THREE.Mesh(lineGeometry, lineMaterial);
341
+ line.rotation.x = -Math.PI / 2;
342
+ line.position.x = i * 2.5; // Center line between lanes
343
+ line.position.y = 0.01; // Slightly above road
344
+ scene.add(line);
345
+ }
346
+
347
+ // Dashed center lines
348
+ for (
349
+ let z = -config.roadLength / 2;
350
+ z < config.roadLength / 2;
351
+ z += 5
352
+ ) {
353
+ const dashGeometry = new THREE.PlaneGeometry(0.15, 3);
354
+ const dashMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
355
+
356
+ // Left dashed line
357
+ const leftDash = new THREE.Mesh(dashGeometry, dashMaterial);
358
+ leftDash.rotation.x = -Math.PI / 2;
359
+ leftDash.position.set(-2.5, 0.01, z);
360
+ scene.add(leftDash);
361
+
362
+ // Right dashed line
363
+ const rightDash = new THREE.Mesh(dashGeometry, dashMaterial);
364
+ rightDash.rotation.x = -Math.PI / 2;
365
+ rightDash.position.set(2.5, 0.01, z);
366
+ scene.add(rightDash);
367
+ }
368
+ }
369
+
370
  // Player Car
371
  const playerColor = 0xff0000;
372
+ const playerCar = createVehicleModel("car", playerColor, true);
373
  playerCar.position.y = 0;
374
  scene.add(playerCar);
375
 
376
+ // Traffic Vehicles
377
+ const trafficVehicles = [];
378
+ function createTrafficVehicle() {
379
+ // Randomly select vehicle type
380
+ const vehicleType =
381
+ config.vehicleTypes[
382
+ Math.floor(Math.random() * config.vehicleTypes.length)
383
+ ];
384
  const colorObj =
385
  config.colors[Math.floor(Math.random() * config.colors.length)];
 
386
 
387
+ const vehicle = createVehicleModel(vehicleType, colorObj.color);
 
 
 
 
388
 
389
+ // Place in a random lane
390
+ const laneIndex = Math.floor(
391
+ Math.random() * config.lanePositions.length
392
+ );
393
+ vehicle.position.x = config.lanePositions[laneIndex];
394
+
395
+ // Stagger vehicle positions - longer range for traffic jam effect
396
+ vehicle.position.z = -Math.random() * config.roadLength * 0.75;
397
 
398
+ // Add to scene and array
399
+ scene.add(vehicle);
400
+ trafficVehicles.push(vehicle);
401
+
402
+ // Update the bounding box after positioning
403
+ vehicle.userData.boundingBox.setFromObject(vehicle);
404
  }
405
 
406
  // Spawn initial traffic
407
  function initTraffic() {
408
+ createLaneMarkings();
409
+ for (let i = 0; i < config.maxTrafficVehicles; i++) {
410
+ createTrafficVehicle();
411
  }
412
  }
413
 
414
  // Camera positioning
415
+ camera.position.y = 3;
416
+ camera.position.z = 7;
417
  camera.lookAt(playerCar.position);
418
 
419
+ // Improved collision detection using bounding boxes
420
  function checkCollisions() {
421
+ if (state.gameOver) return;
422
+
423
+ // Update player bounding box
424
+ playerCar.userData.boundingBox.setFromObject(playerCar);
425
+
426
+ for (let i = 0; i < trafficVehicles.length; i++) {
427
+ // Update vehicle bounding box
428
+ trafficVehicles[i].userData.boundingBox.setFromObject(
429
+ trafficVehicles[i]
430
+ );
431
+
432
+ // Check for intersection
433
+ if (
434
+ playerCar.userData.boundingBox.intersectsBox(
435
+ trafficVehicles[i].userData.boundingBox
436
+ )
437
+ ) {
438
  endGame();
439
+ break;
440
  }
441
+ }
442
  }
443
 
444
  // Format time to MM:SS
 
465
 
466
  if (
467
  keys["ArrowLeft"] &&
468
+ playerCar.position.x > -(config.roadWidth / 2 - 1)
469
  ) {
470
  playerCar.position.x -= config.playerSpeed;
471
  }
472
  if (
473
  keys["ArrowRight"] &&
474
+ playerCar.position.x < config.roadWidth / 2 - 1
475
  ) {
476
  playerCar.position.x += config.playerSpeed;
477
  }
 
487
  }
488
  }
489
 
490
+ // Update traffic vehicles
491
+ function updateTrafficVehicles() {
492
  // Increase difficulty based on score and time
493
  state.difficultyMultiplier =
494
+ 1 + state.score / 2000 + state.elapsedTime / 80000;
495
+
496
+ trafficVehicles.forEach((vehicle, index) => {
497
+ // Move vehicles with their specific speeds
498
+ const vehicleSpeed =
499
+ config.trafficSpeed *
500
+ vehicle.userData.speed *
501
+ state.difficultyMultiplier;
502
+
503
+ vehicle.position.z += vehicleSpeed;
504
+
505
+ // Update bounding box with new position
506
+ vehicle.userData.boundingBox.setFromObject(vehicle);
507
+
508
+ // Award points when successfully dodging a vehicle
509
+ if (
510
+ !vehicle.userData.passed &&
511
+ vehicle.position.z > playerCar.position.z
512
+ ) {
513
+ vehicle.userData.passed = true;
514
+ state.score++;
515
+ document.getElementById(
516
+ "score"
517
+ ).textContent = `Score: ${state.score}`;
518
+ }
519
 
520
+ // Remove vehicles that are out of view and create new ones
521
+ if (vehicle.position.z > 15) {
522
+ scene.remove(vehicle);
523
+ trafficVehicles.splice(index, 1);
524
+ createTrafficVehicle();
525
  }
526
  });
527
  }
 
537
  // Animation loop
538
  function animate() {
539
  requestAnimationFrame(animate);
 
540
  updatePlayerMovement();
541
+ updateTrafficVehicles();
542
  checkCollisions();
543
  updateTimer();
544
 
545
  // Update camera to follow player
546
  camera.position.x = playerCar.position.x;
547
+ camera.position.z = playerCar.position.z + 7; // Positioned further back
548
+ camera.lookAt(
549
+ new THREE.Vector3(
550
+ playerCar.position.x,
551
+ playerCar.position.y,
552
+ playerCar.position.z - 3
553
+ )
554
+ );
555
 
556
  renderer.render(scene, camera);
557
  }
 
570
  document.getElementById("gameOverScreen").style.display = "none";
571
  document.getElementById("hud").style.display = "block";
572
 
573
+ // Reset player position
574
  playerCar.position.x = 0;
575
  playerCar.position.z = 0;
576
 
577
  // Clear existing traffic
578
+ trafficVehicles.forEach((vehicle) => scene.remove(vehicle));
579
+ trafficVehicles.length = 0;
580
 
581
  // Respawn traffic
582
  initTraffic();
 
593
  function endGame() {
594
  state.gameOver = true;
595
 
 
 
 
596
  // Show game over screen
597
  document.getElementById("hud").style.display = "none";
598
  document.getElementById("gameOverScreen").style.display = "flex";
599
  document.getElementById("finalScore").textContent = `Score: ${
600
  state.score
601
+ }
602
+ Time: ${formatTime(state.elapsedTime)}`;
603
  }
604
 
605
  // Event Listeners
 
618
  });
619
  </script>
620
  </body>
621
+ </html>