awacke1 commited on
Commit
ee7f7b2
Β·
verified Β·
1 Parent(s): 3792cce

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +115 -14
index.html CHANGED
@@ -134,11 +134,11 @@
134
  </div>
135
  <div id="instructions">
136
  <h2>Welcome to the Isle of Mull Ferry Driving Simulator!</h2>
137
- <p>You're driving to catch the ferry to the Isle of Mull in Scotland. Practice safe driving on Scotland's unique single-track roads with passing places.</p>
138
 
139
  <h3>How to Play:</h3>
140
  <ul style="text-align: left;">
141
- <li>Drive on the <span class="highlight">left side</span> of the road</li>
142
  <li>Use <span class="highlight">W/S</span> or <span class="highlight">↑/↓</span> to accelerate/brake</li>
143
  <li>Use <span class="highlight">A/D</span> or <span class="highlight">←/β†’</span> to steer</li>
144
  <li>Press <span class="highlight">SPACE</span> or <span class="highlight">J</span> to jump (when driving fast)</li>
@@ -569,8 +569,8 @@
569
  car.castShadow = true;
570
  const {roadY,roadCurve} = getRoadPropertiesAtZ(worldZPosition);
571
 
572
- // Fix lane positioning - oncoming cars should be on player's right side
573
- const laneXOffset = isOncoming ? (roadWidth/4 + 0.25) : (-roadWidth/4 - 0.25);
574
  car.position.set(roadCurve + laneXOffset, 1+roadY, worldZPosition);
575
  car.rotation.y = isOncoming ? Math.PI : 0;
576
  scene.add(car);
@@ -579,7 +579,23 @@
579
  leftHeadlight.position.set(-0.7,0.3,1.9); car.add(leftHeadlight);
580
  const rightHeadlight = new THREE.Mesh(new THREE.SphereGeometry(0.2,8,8), headlightMat);
581
  rightHeadlight.position.set(0.7,0.3,1.9); car.add(rightHeadlight);
582
- aiCars.push({mesh:car,speed:isOncoming?8:10,isOncoming:isOncoming,honking:false,waiting:false,initialPositionZ:worldZPosition,flashing:false,waitingAtPassingPlace:false,flashingLights:false,leftHeadlight:leftHeadlight,rightHeadlight:rightHeadlight,politeness:Math.random()*0.8+0.2});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  }
584
 
585
  function createPassingPlaces() {
@@ -806,10 +822,12 @@
806
 
807
  aiCars.forEach(ai => {
808
  const {roadY:rY, roadCurve:rC} = getRoadPropertiesAtZ(ai.initialPositionZ);
809
- const lo = ai.isOncoming ? (roadWidth/4+0.25) : (-roadWidth/4-0.25);
 
810
  ai.mesh.position.set(rC+lo, 1+rY, ai.initialPositionZ);
811
  ai.mesh.rotation.y = ai.isOncoming ? Math.PI : 0;
812
- Object.assign(ai, {waiting:false,honking:false,waitingAtPassingPlace:false,flashingLights:false,isOvertaking:false});
 
813
  if(ai.leftHeadlight) ai.leftHeadlight.material.color.setHex(0xFFFFFF);
814
  if(ai.rightHeadlight) ai.rightHeadlight.material.color.setHex(0xFFFFFF);
815
  });
@@ -976,12 +994,44 @@
976
  function updateAICars(delta) {
977
  carsBehind = [];
978
  aiCars.forEach(ai => {
979
- const carM=ai.mesh; let curSpd=ai.waiting||ai.waitingAtPassingPlace?0:ai.speed;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
980
  const moveDist=curSpd*(ai.isOncoming?-1:1)*delta*2.5; carM.position.z+=moveDist;
981
  const {roadY,roadCurve}=getRoadPropertiesAtZ(carM.position.z);
982
- let tLaneXOff=ai.isOncoming?(roadWidth/4):(-roadWidth/4);
983
- if(ai.isOvertaking)tLaneXOff=ai.isOncoming?(-roadWidth/4):(roadWidth/4);
 
 
984
  const tX=roadCurve+tLaneXOff; carM.position.x+=(tX-carM.position.x)*0.1; carM.position.y=1+roadY;
 
985
  if(ai.isOncoming){
986
  const dToP=playerCar.position.distanceTo(carM.position);
987
  if(dToP<40&&!ai.waitingAtPassingPlace){
@@ -1006,8 +1056,11 @@
1006
  if(!ai.isOncoming&&carM.position.z<playerCar.position.z&&carM.position.z>playerCar.position.z-50)carsBehind.push(ai);
1007
  if(Math.abs(carM.position.z-(roadLength/2))>roadLength/2+100){
1008
  const iZ=ai.initialPositionZ; const{roadY:iRY,roadCurve:iRC}=getRoadPropertiesAtZ(iZ);
1009
- const lo=ai.isOncoming?(roadWidth/4+0.25):(-roadWidth/4-0.25);
1010
- carM.position.set(iRC+lo,1+iRY,iZ); Object.assign(ai,{waiting:false,waitingAtPassingPlace:false,isOvertaking:false,flashingLights:false});
 
 
 
1011
  }
1012
  });
1013
  updateRearViewMirror();
@@ -1017,7 +1070,8 @@
1017
  const pZ=playerCar.position.z,pX=playerCar.position.x; const{roadCurve:pRC}=getRoadPropertiesAtZ(pZ);
1018
  for(const pp of passingPlaces){
1019
  if(Math.abs(pZ-pp.position)<pp.length/2){
1020
- if(pp.side===-1){if(pX<pRC-roadWidth/4&&Math.abs(speed)<5)return true;}
 
1021
  }
1022
  }return false;
1023
  }
@@ -1042,7 +1096,54 @@
1042
  function checkCollisions() {
1043
  const playerBox = new THREE.Box3().setFromObject(playerCar);
1044
  potholes.forEach(pd=>{if(!pd.hit){const dist=playerCar.position.distanceTo(pd.mesh.position);if(dist<1.5){pd.hit=true;const oSpd=Math.abs(speed);speed*=0.6;decreaseHealth(15,"Hit a pothole!");if(oSpd>20){showMessage("Flat tire!",3);decreaseHealth(25,"Flat Tire!");}}}});
1045
- aiCars.forEach(aiD=>{const aiB=new THREE.Box3().setFromObject(aiD.mesh);if(playerBox.intersectsBox(aiB)){decreaseHealth(35,"Collided!");playerCar.position.z-=Math.sign(speed)*2.5;speed*=0.1;aiD.waiting=true;setTimeout(()=>{if(aiD)aiD.waiting=false;},2500);}});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1046
  }
1047
 
1048
  function updateHealthRegen(delta) {
 
134
  </div>
135
  <div id="instructions">
136
  <h2>Welcome to the Isle of Mull Ferry Driving Simulator!</h2>
137
+ <p>You're driving to catch the ferry to the Isle of Mull in Scotland. Practice safe driving on American-style roads.</p>
138
 
139
  <h3>How to Play:</h3>
140
  <ul style="text-align: left;">
141
+ <li>Drive on the <span class="highlight">right side</span> of the road</li>
142
  <li>Use <span class="highlight">W/S</span> or <span class="highlight">↑/↓</span> to accelerate/brake</li>
143
  <li>Use <span class="highlight">A/D</span> or <span class="highlight">←/β†’</span> to steer</li>
144
  <li>Press <span class="highlight">SPACE</span> or <span class="highlight">J</span> to jump (when driving fast)</li>
 
569
  car.castShadow = true;
570
  const {roadY,roadCurve} = getRoadPropertiesAtZ(worldZPosition);
571
 
572
+ // SWITCHED: For right-side driving, oncoming cars should be on player's left side
573
+ const laneXOffset = isOncoming ? (-roadWidth/4 - 0.25) : (roadWidth/4 + 0.25);
574
  car.position.set(roadCurve + laneXOffset, 1+roadY, worldZPosition);
575
  car.rotation.y = isOncoming ? Math.PI : 0;
576
  scene.add(car);
 
579
  leftHeadlight.position.set(-0.7,0.3,1.9); car.add(leftHeadlight);
580
  const rightHeadlight = new THREE.Mesh(new THREE.SphereGeometry(0.2,8,8), headlightMat);
581
  rightHeadlight.position.set(0.7,0.3,1.9); car.add(rightHeadlight);
582
+ aiCars.push({
583
+ mesh:car,
584
+ speed:isOncoming?8:10,
585
+ baseSpeed:isOncoming?8:10, // Store original speed
586
+ isOncoming:isOncoming,
587
+ honking:false,
588
+ waiting:false,
589
+ initialPositionZ:worldZPosition,
590
+ flashing:false,
591
+ waitingAtPassingPlace:false,
592
+ flashingLights:false,
593
+ leftHeadlight:leftHeadlight,
594
+ rightHeadlight:rightHeadlight,
595
+ politeness:Math.random()*0.8+0.2,
596
+ avoidingPlayer:false, // New property for collision avoidance
597
+ reactionDistance:30 + Math.random() * 20 // Variable reaction distance
598
+ });
599
  }
600
 
601
  function createPassingPlaces() {
 
822
 
823
  aiCars.forEach(ai => {
824
  const {roadY:rY, roadCurve:rC} = getRoadPropertiesAtZ(ai.initialPositionZ);
825
+ // SWITCHED: Updated for right-side driving
826
+ const lo = ai.isOncoming ? (-roadWidth/4-0.25) : (roadWidth/4+0.25);
827
  ai.mesh.position.set(rC+lo, 1+rY, ai.initialPositionZ);
828
  ai.mesh.rotation.y = ai.isOncoming ? Math.PI : 0;
829
+ Object.assign(ai, {waiting:false,honking:false,waitingAtPassingPlace:false,flashingLights:false,isOvertaking:false,avoidingPlayer:false});
830
+ ai.speed = ai.baseSpeed; // Reset to base speed
831
  if(ai.leftHeadlight) ai.leftHeadlight.material.color.setHex(0xFFFFFF);
832
  if(ai.rightHeadlight) ai.rightHeadlight.material.color.setHex(0xFFFFFF);
833
  });
 
994
  function updateAICars(delta) {
995
  carsBehind = [];
996
  aiCars.forEach(ai => {
997
+ const carM=ai.mesh;
998
+
999
+ // NEW: Collision avoidance logic
1000
+ const distToPlayer = playerCar.position.distanceTo(carM.position);
1001
+ let targetSpeed = ai.baseSpeed;
1002
+ ai.avoidingPlayer = false;
1003
+
1004
+ if (ai.isOncoming) {
1005
+ // Oncoming cars should slow down when approaching player head-on
1006
+ if (distToPlayer < ai.reactionDistance &&
1007
+ Math.abs(carM.position.x - playerCar.position.x) < roadWidth * 0.8) {
1008
+ ai.avoidingPlayer = true;
1009
+ const slowdownFactor = Math.max(0.2, distToPlayer / ai.reactionDistance);
1010
+ targetSpeed = ai.baseSpeed * slowdownFactor;
1011
+ }
1012
+ } else {
1013
+ // Cars behind player should slow down when getting too close
1014
+ const zDiff = playerCar.position.z - carM.position.z;
1015
+ if (zDiff > 0 && zDiff < ai.reactionDistance &&
1016
+ Math.abs(carM.position.x - playerCar.position.x) < roadWidth * 0.6) {
1017
+ ai.avoidingPlayer = true;
1018
+ const slowdownFactor = Math.max(0.3, zDiff / ai.reactionDistance);
1019
+ targetSpeed = Math.min(ai.baseSpeed * slowdownFactor, Math.abs(speed) * 0.8);
1020
+ }
1021
+ }
1022
+
1023
+ // Smoothly adjust speed towards target
1024
+ ai.speed += (targetSpeed - ai.speed) * delta * 2;
1025
+
1026
+ let curSpd=ai.waiting||ai.waitingAtPassingPlace?0:ai.speed;
1027
  const moveDist=curSpd*(ai.isOncoming?-1:1)*delta*2.5; carM.position.z+=moveDist;
1028
  const {roadY,roadCurve}=getRoadPropertiesAtZ(carM.position.z);
1029
+
1030
+ // SWITCHED: Updated for right-side driving
1031
+ let tLaneXOff=ai.isOncoming?(-roadWidth/4):(-roadWidth/4);
1032
+ if(ai.isOvertaking)tLaneXOff=ai.isOncoming?(roadWidth/4):(-roadWidth/4);
1033
  const tX=roadCurve+tLaneXOff; carM.position.x+=(tX-carM.position.x)*0.1; carM.position.y=1+roadY;
1034
+
1035
  if(ai.isOncoming){
1036
  const dToP=playerCar.position.distanceTo(carM.position);
1037
  if(dToP<40&&!ai.waitingAtPassingPlace){
 
1056
  if(!ai.isOncoming&&carM.position.z<playerCar.position.z&&carM.position.z>playerCar.position.z-50)carsBehind.push(ai);
1057
  if(Math.abs(carM.position.z-(roadLength/2))>roadLength/2+100){
1058
  const iZ=ai.initialPositionZ; const{roadY:iRY,roadCurve:iRC}=getRoadPropertiesAtZ(iZ);
1059
+ // SWITCHED: Updated for right-side driving
1060
+ const lo=ai.isOncoming?(-roadWidth/4-0.25):(roadWidth/4+0.25);
1061
+ carM.position.set(iRC+lo,1+iRY,iZ);
1062
+ Object.assign(ai,{waiting:false,waitingAtPassingPlace:false,isOvertaking:false,flashingLights:false,avoidingPlayer:false});
1063
+ ai.speed = ai.baseSpeed; // Reset speed when respawning
1064
  }
1065
  });
1066
  updateRearViewMirror();
 
1070
  const pZ=playerCar.position.z,pX=playerCar.position.x; const{roadCurve:pRC}=getRoadPropertiesAtZ(pZ);
1071
  for(const pp of passingPlaces){
1072
  if(Math.abs(pZ-pp.position)<pp.length/2){
1073
+ // SWITCHED: Updated for right-side driving - player should pull to the right
1074
+ if(pp.side===1){if(pX>pRC+roadWidth/4&&Math.abs(speed)<5)return true;}
1075
  }
1076
  }return false;
1077
  }
 
1096
  function checkCollisions() {
1097
  const playerBox = new THREE.Box3().setFromObject(playerCar);
1098
  potholes.forEach(pd=>{if(!pd.hit){const dist=playerCar.position.distanceTo(pd.mesh.position);if(dist<1.5){pd.hit=true;const oSpd=Math.abs(speed);speed*=0.6;decreaseHealth(15,"Hit a pothole!");if(oSpd>20){showMessage("Flat tire!",3);decreaseHealth(25,"Flat Tire!");}}}});
1099
+
1100
+ aiCars.forEach(aiD=>{
1101
+ const aiB=new THREE.Box3().setFromObject(aiD.mesh);
1102
+ if(playerBox.intersectsBox(aiB)){
1103
+ // NEW: Determine collision type and adjust damage accordingly
1104
+ let damage = 35; // Base damage
1105
+ let collisionType = "Collision!";
1106
+
1107
+ // Check if it's a rear collision (player hitting AI from behind or AI hitting player from behind)
1108
+ const playerToAI = aiD.mesh.position.z - playerCar.position.z;
1109
+ const playerSpeed = Math.abs(speed);
1110
+
1111
+ if (Math.abs(playerToAI) > 2) { // Not a side collision
1112
+ if ((playerToAI > 0 && speed > 0) || (playerToAI < 0 && speed < 0)) {
1113
+ // Rear collision - much less damage
1114
+ damage = Math.max(8, Math.floor(damage * 0.3)); // 70% damage reduction
1115
+ collisionType = "Rear collision!";
1116
+ }
1117
+ }
1118
+
1119
+ // Speed-based damage adjustment
1120
+ const speedFactor = Math.max(0.5, playerSpeed / 30);
1121
+ damage = Math.floor(damage * speedFactor);
1122
+
1123
+ decreaseHealth(damage, collisionType);
1124
+ playerCar.position.z-=Math.sign(speed)*2.5;
1125
+ speed*=0.1;
1126
+ aiD.waiting=true;
1127
+ setTimeout(()=>{if(aiD)aiD.waiting=false;},2500);
1128
+ }
1129
+ });
1130
+ }
1131
+
1132
+ function checkLandingBonus(impactForce) {
1133
+ // Award points for successful jumps and landings
1134
+ if (jumpSpeed > 0) {
1135
+ let bonusPoints = 0;
1136
+ if (airTime > 1.0) bonusPoints += 100;
1137
+ if (airTime > 2.0) bonusPoints += 200;
1138
+ if (jumpSpeed > 30) bonusPoints += 150;
1139
+ if (impactForce < 0.5) bonusPoints += 100; // Smooth landing bonus
1140
+
1141
+ if (bonusPoints > 0) {
1142
+ score += bonusPoints;
1143
+ document.getElementById('score').textContent = `Score: ${score}`;
1144
+ showMessage(`Landing bonus: +${bonusPoints}!`, 2);
1145
+ }
1146
+ }
1147
  }
1148
 
1149
  function updateHealthRegen(delta) {