Spaces:
Running
Running
Update index.html
Browse files- index.html +15 -86
index.html
CHANGED
@@ -394,7 +394,7 @@
|
|
394 |
}
|
395 |
|
396 |
// Particle system for explosions
|
397 |
-
function createExplosion(position
|
398 |
const particleCount = 50;
|
399 |
const geometry = new THREE.BufferGeometry();
|
400 |
const positions = new Float32Array(particleCount * 3);
|
@@ -404,7 +404,7 @@
|
|
404 |
positions[i3] = position.x;
|
405 |
positions[i3 + 1] = position.y;
|
406 |
positions[i3 + 2] = position.z;
|
407 |
-
const color =
|
408 |
colors[i3] = color[0];
|
409 |
colors[i3 + 1] = color[1];
|
410 |
colors[i3 + 2] = color[2];
|
@@ -418,7 +418,7 @@
|
|
418 |
opacity: 0.8
|
419 |
});
|
420 |
const particles = new THREE.Points(geometry, material);
|
421 |
-
particles.userData = { lifetime:
|
422 |
for (let i = 0; i < particleCount; i++) {
|
423 |
particles.userData.velocities.push(
|
424 |
new THREE.Vector3(
|
@@ -429,7 +429,6 @@
|
|
429 |
);
|
430 |
}
|
431 |
scene.add(particles);
|
432 |
-
explosions.push(particles);
|
433 |
return particles;
|
434 |
}
|
435 |
|
@@ -451,9 +450,7 @@
|
|
451 |
currentHP: 10 * scaleMultiplier,
|
452 |
width: width,
|
453 |
depth: depth,
|
454 |
-
height: height
|
455 |
-
isFalling: false,
|
456 |
-
fallVelocity: 0
|
457 |
};
|
458 |
return building;
|
459 |
}
|
@@ -773,7 +770,7 @@
|
|
773 |
document.getElementById('skill-turn-speed-meter').style.width = `${(skills.turnSpeed.level / skills.turnSpeed.maxLevel) * 100}%`;
|
774 |
}
|
775 |
|
776 |
-
// Damage handling
|
777 |
function applyDamage(ship, damage, hitPosition) {
|
778 |
if (!ship.userData.active) return;
|
779 |
const direction = hitPosition.clone().sub(ship.position).normalize();
|
@@ -805,7 +802,7 @@
|
|
805 |
if (ship === playerShip) {
|
806 |
updateCharacterSheet();
|
807 |
}
|
808 |
-
checkShipStatus(ship
|
809 |
}
|
810 |
|
811 |
function checkShipStatus(ship, hitPosition) {
|
@@ -850,91 +847,28 @@
|
|
850 |
building.userData.currentHP -= damage;
|
851 |
createExplosion(hitPosition);
|
852 |
if (building.userData.currentHP <= 0) {
|
|
|
853 |
if (building.userData.splitCount < 3) {
|
854 |
const newScale = 0.5;
|
855 |
-
const hitLocal = building.worldToLocal(hitPosition.clone());
|
856 |
-
const width = building.userData.width * newScale;
|
857 |
-
const depth = building.userData.depth * newScale;
|
858 |
-
const height = building.userData.height * newScale;
|
859 |
-
// Determine split direction based on hit position
|
860 |
-
const absX = Math.abs(hitLocal.x);
|
861 |
-
const absZ = Math.abs(hitLocal.z);
|
862 |
-
const isXSplit = absX > absZ;
|
863 |
-
const splitSize = (isXSplit ? building.userData.width : building.userData.depth) / 3;
|
864 |
-
const remainingSize = splitSize * 2 * newScale;
|
865 |
const offsets = [
|
866 |
-
new THREE.Vector3(
|
867 |
-
new THREE.Vector3(
|
868 |
];
|
869 |
offsets.forEach(offset => {
|
870 |
const newBuilding = createBuilding(
|
871 |
building.position.x + offset.x,
|
872 |
building.position.z + offset.z,
|
873 |
-
|
874 |
-
|
875 |
-
height,
|
876 |
newScale,
|
877 |
building.userData.splitCount + 1
|
878 |
);
|
879 |
-
newBuilding.userData.isFalling = true;
|
880 |
-
newBuilding.userData.fallVelocity = 0;
|
881 |
currentTrackGroup.add(newBuilding);
|
882 |
});
|
883 |
-
score += 100;
|
884 |
-
document.getElementById('score').textContent = `Score: ${score}`;
|
885 |
-
}
|
886 |
-
currentTrackGroup.remove(building);
|
887 |
-
} else {
|
888 |
-
// Initiate falling if not already falling
|
889 |
-
if (!building.userData.isFalling) {
|
890 |
-
building.userData.isFalling = true;
|
891 |
-
building.userData.fallVelocity = 0;
|
892 |
-
}
|
893 |
-
}
|
894 |
-
}
|
895 |
-
|
896 |
-
// Update falling buildings
|
897 |
-
function updateFallingBuildings() {
|
898 |
-
if (!currentTrackGroup) return;
|
899 |
-
const buildings = currentTrackGroup.children.filter(c => c.isMesh && c.geometry.type === 'BoxGeometry');
|
900 |
-
for (let i = buildings.length - 1; i >= 0; i--) {
|
901 |
-
const building = buildings[i];
|
902 |
-
if (building.userData.isFalling) {
|
903 |
-
building.userData.fallVelocity += 0.1; // Gravity
|
904 |
-
building.position.y -= building.userData.fallVelocity / 60;
|
905 |
-
if (building.position.y <= building.userData.height * 0.5) {
|
906 |
-
building.position.y = building.userData.height * 0.5;
|
907 |
-
building.userData.currentHP -= 2; // Additional damage on impact
|
908 |
-
createExplosion(building.position);
|
909 |
-
if (building.userData.currentHP <= 0) {
|
910 |
-
if (building.userData.splitCount < 3) {
|
911 |
-
const newScale = 0.5;
|
912 |
-
const width = building.userData.width * newScale;
|
913 |
-
const depth = building.userData.depth * newScale;
|
914 |
-
const height = building.userData.height * newScale;
|
915 |
-
const offsets = [
|
916 |
-
new THREE.Vector3(5 * newScale, 0, 5 * newScale),
|
917 |
-
new THREE.Vector3(-5 * newScale, 0, -5 * newScale)
|
918 |
-
];
|
919 |
-
offsets.forEach(offset => {
|
920 |
-
const newBuilding = createBuilding(
|
921 |
-
building.position.x + offset.x,
|
922 |
-
building.position.z + offset.z,
|
923 |
-
width,
|
924 |
-
depth,
|
925 |
-
height,
|
926 |
-
newScale,
|
927 |
-
building.userData.splitCount + 1
|
928 |
-
);
|
929 |
-
currentTrackGroup.add(newBuilding);
|
930 |
-
});
|
931 |
-
score += 100;
|
932 |
-
document.getElementById('score').textContent = `Score: ${score}`;
|
933 |
-
}
|
934 |
-
currentTrackGroup.remove(building);
|
935 |
-
}
|
936 |
-
}
|
937 |
}
|
|
|
|
|
938 |
}
|
939 |
}
|
940 |
|
@@ -1052,7 +986,6 @@
|
|
1052 |
ship.position.add(direction.multiplyScalar(0.5));
|
1053 |
ship.userData.speed *= 0.8;
|
1054 |
applyDamage(ship, 2, ship.position);
|
1055 |
-
createExplosion(ship.position, true); // Collision particles
|
1056 |
}
|
1057 |
}
|
1058 |
});
|
@@ -1069,7 +1002,6 @@
|
|
1069 |
if (distance < 5) {
|
1070 |
const direction = shipPos.clone().sub(columnPos).normalize();
|
1071 |
ship.position.add(direction.multiplyScalar(0.2));
|
1072 |
-
createExplosion(ship.position, true); // Collision particles
|
1073 |
}
|
1074 |
}
|
1075 |
});
|
@@ -1094,7 +1026,7 @@
|
|
1094 |
positions[j3 + 2] += explosion.userData.velocities[j].z;
|
1095 |
}
|
1096 |
explosion.geometry.attributes.position.needsUpdate = true;
|
1097 |
-
explosion.material.opacity = explosion.userData.lifetime /
|
1098 |
}
|
1099 |
}
|
1100 |
|
@@ -1124,10 +1056,8 @@
|
|
1124 |
if (currentTrackGroup) scene.remove(currentTrackGroup);
|
1125 |
pickups.forEach(p => scene.remove(p));
|
1126 |
missiles.forEach(m => scene.remove(m));
|
1127 |
-
explosions.forEach(e => scene.remove(e));
|
1128 |
pickups.length = 0;
|
1129 |
missiles.length = 0;
|
1130 |
-
explosions.length = 0;
|
1131 |
const { trackGroup, waypoints: newWaypoints, startPosition } = generateTrack(trackConfigs[trackName]);
|
1132 |
currentTrackGroup = trackGroup;
|
1133 |
waypoints = newWaypoints;
|
@@ -1195,7 +1125,6 @@
|
|
1195 |
updateAI();
|
1196 |
updateMissiles();
|
1197 |
updateExplosions();
|
1198 |
-
updateFallingBuildings();
|
1199 |
raceTime += 1 / 60;
|
1200 |
document.getElementById('time').textContent = `Time: ${raceTime.toFixed(2)}`;
|
1201 |
if (aiShips.every(s => !s.userData.active) && playerData.active) {
|
|
|
394 |
}
|
395 |
|
396 |
// Particle system for explosions
|
397 |
+
function createExplosion(position) {
|
398 |
const particleCount = 50;
|
399 |
const geometry = new THREE.BufferGeometry();
|
400 |
const positions = new Float32Array(particleCount * 3);
|
|
|
404 |
positions[i3] = position.x;
|
405 |
positions[i3 + 1] = position.y;
|
406 |
positions[i3 + 2] = position.z;
|
407 |
+
const color = Math.random() > 0.5 ? [1, 1, 0] : [1, 0, 0];
|
408 |
colors[i3] = color[0];
|
409 |
colors[i3 + 1] = color[1];
|
410 |
colors[i3 + 2] = color[2];
|
|
|
418 |
opacity: 0.8
|
419 |
});
|
420 |
const particles = new THREE.Points(geometry, material);
|
421 |
+
particles.userData = { lifetime: 60, velocities: [] };
|
422 |
for (let i = 0; i < particleCount; i++) {
|
423 |
particles.userData.velocities.push(
|
424 |
new THREE.Vector3(
|
|
|
429 |
);
|
430 |
}
|
431 |
scene.add(particles);
|
|
|
432 |
return particles;
|
433 |
}
|
434 |
|
|
|
450 |
currentHP: 10 * scaleMultiplier,
|
451 |
width: width,
|
452 |
depth: depth,
|
453 |
+
height: height
|
|
|
|
|
454 |
};
|
455 |
return building;
|
456 |
}
|
|
|
770 |
document.getElementById('skill-turn-speed-meter').style.width = `${(skills.turnSpeed.level / skills.turnSpeed.maxLevel) * 100}%`;
|
771 |
}
|
772 |
|
773 |
+
// Damage handling
|
774 |
function applyDamage(ship, damage, hitPosition) {
|
775 |
if (!ship.userData.active) return;
|
776 |
const direction = hitPosition.clone().sub(ship.position).normalize();
|
|
|
802 |
if (ship === playerShip) {
|
803 |
updateCharacterSheet();
|
804 |
}
|
805 |
+
checkShipStatus(ship);
|
806 |
}
|
807 |
|
808 |
function checkShipStatus(ship, hitPosition) {
|
|
|
847 |
building.userData.currentHP -= damage;
|
848 |
createExplosion(hitPosition);
|
849 |
if (building.userData.currentHP <= 0) {
|
850 |
+
currentTrackGroup.remove(building);
|
851 |
if (building.userData.splitCount < 3) {
|
852 |
const newScale = 0.5;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
853 |
const offsets = [
|
854 |
+
new THREE.Vector3(5, 0, 5),
|
855 |
+
new THREE.Vector3(-5, 0, -5)
|
856 |
];
|
857 |
offsets.forEach(offset => {
|
858 |
const newBuilding = createBuilding(
|
859 |
building.position.x + offset.x,
|
860 |
building.position.z + offset.z,
|
861 |
+
building.userData.width,
|
862 |
+
building.userData.depth,
|
863 |
+
building.userData.height,
|
864 |
newScale,
|
865 |
building.userData.splitCount + 1
|
866 |
);
|
|
|
|
|
867 |
currentTrackGroup.add(newBuilding);
|
868 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
869 |
}
|
870 |
+
score += 100;
|
871 |
+
document.getElementById('score').textContent = `Score: ${score}`;
|
872 |
}
|
873 |
}
|
874 |
|
|
|
986 |
ship.position.add(direction.multiplyScalar(0.5));
|
987 |
ship.userData.speed *= 0.8;
|
988 |
applyDamage(ship, 2, ship.position);
|
|
|
989 |
}
|
990 |
}
|
991 |
});
|
|
|
1002 |
if (distance < 5) {
|
1003 |
const direction = shipPos.clone().sub(columnPos).normalize();
|
1004 |
ship.position.add(direction.multiplyScalar(0.2));
|
|
|
1005 |
}
|
1006 |
}
|
1007 |
});
|
|
|
1026 |
positions[j3 + 2] += explosion.userData.velocities[j].z;
|
1027 |
}
|
1028 |
explosion.geometry.attributes.position.needsUpdate = true;
|
1029 |
+
explosion.material.opacity = explosion.userData.lifetime / 60;
|
1030 |
}
|
1031 |
}
|
1032 |
|
|
|
1056 |
if (currentTrackGroup) scene.remove(currentTrackGroup);
|
1057 |
pickups.forEach(p => scene.remove(p));
|
1058 |
missiles.forEach(m => scene.remove(m));
|
|
|
1059 |
pickups.length = 0;
|
1060 |
missiles.length = 0;
|
|
|
1061 |
const { trackGroup, waypoints: newWaypoints, startPosition } = generateTrack(trackConfigs[trackName]);
|
1062 |
currentTrackGroup = trackGroup;
|
1063 |
waypoints = newWaypoints;
|
|
|
1125 |
updateAI();
|
1126 |
updateMissiles();
|
1127 |
updateExplosions();
|
|
|
1128 |
raceTime += 1 / 60;
|
1129 |
document.getElementById('time').textContent = `Time: ${raceTime.toFixed(2)}`;
|
1130 |
if (aiShips.every(s => !s.userData.active) && playerData.active) {
|