Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
@@ -865,58 +865,180 @@ class EnemyFighter {
|
|
865 |
}
|
866 |
}
|
867 |
}
|
868 |
-
shoot() {
|
869 |
-
this.lastShootTime = Date.now();
|
870 |
-
|
871 |
-
// μ§μ λͺ¨μμ νν (100% λ ν¬κ²)
|
872 |
-
const bulletGeometry = new THREE.CylinderGeometry(0.8, 0.8, 12, 8);
|
873 |
-
const bulletMaterial = new THREE.MeshBasicMaterial({
|
874 |
-
color: 0xff0000,
|
875 |
-
emissive: 0xff0000,
|
876 |
-
emissiveIntensity: 1.0
|
877 |
-
});
|
878 |
-
const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
|
879 |
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
888 |
|
889 |
-
|
890 |
-
|
891 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
892 |
|
893 |
-
|
894 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
895 |
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
916 |
}
|
917 |
}
|
918 |
}
|
919 |
-
}
|
920 |
|
921 |
updateBullets(deltaTime) {
|
922 |
for (let i = this.bullets.length - 1; i >= 0; i--) {
|
|
|
865 |
}
|
866 |
}
|
867 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
868 |
|
869 |
+
patrol(deltaTime) {
|
870 |
+
// λͺ©ν μ§μ μ λλ¬νλμ§ νμΈ
|
871 |
+
const distanceToTarget = this.position.distanceTo(this.targetPosition);
|
872 |
+
if (distanceToTarget < 500) {
|
873 |
+
// μλ‘μ΄ λͺ©ν μμ±
|
874 |
+
this.targetPosition = this.generateRandomTarget();
|
875 |
+
}
|
876 |
+
|
877 |
+
// λͺ©νλ₯Ό ν₯ν΄ μ ν
|
878 |
+
const direction = this.targetPosition.clone().sub(this.position).normalize();
|
879 |
+
const targetYaw = Math.atan2(direction.x, direction.z);
|
880 |
+
|
881 |
+
// λΆλλ¬μ΄ μ ν
|
882 |
+
const yawDiff = targetYaw - this.rotation.y;
|
883 |
+
const normalizedYawDiff = ((yawDiff + Math.PI) % (2 * Math.PI)) - Math.PI;
|
884 |
+
|
885 |
+
this.targetRotation.y += normalizedYawDiff * deltaTime * 0.5;
|
886 |
+
|
887 |
+
// κ³ λ μ‘°μ
|
888 |
+
const altitudeDiff = this.targetPosition.y - this.position.y;
|
889 |
+
if (Math.abs(altitudeDiff) > 50) {
|
890 |
+
this.targetRotation.x = Math.max(-0.3, Math.min(0.3, altitudeDiff * 0.0001));
|
891 |
+
} else {
|
892 |
+
this.targetRotation.x = 0;
|
893 |
+
}
|
894 |
+
}
|
895 |
|
896 |
+
combat(playerPosition, deltaTime) {
|
897 |
+
// νλ μ΄μ΄ μμΉ μμΈ‘
|
898 |
+
if (this.playerFighter && this.playerFighter.velocity) {
|
899 |
+
const bulletTravelTime = this.position.distanceTo(playerPosition) / 1200; // νν μλ
|
900 |
+
this.predictedTargetPos = playerPosition.clone().add(
|
901 |
+
this.playerFighter.velocity.clone().multiplyScalar(bulletTravelTime)
|
902 |
+
);
|
903 |
+
} else {
|
904 |
+
this.predictedTargetPos = playerPosition.clone();
|
905 |
+
}
|
906 |
+
|
907 |
+
// μμΈ‘ μμΉλ₯Ό ν₯ν΄ μ‘°μ€
|
908 |
+
const aimDirection = this.predictedTargetPos.clone().sub(this.position).normalize();
|
909 |
+
const targetYaw = Math.atan2(aimDirection.x, aimDirection.z);
|
910 |
+
const targetPitch = Math.asin(-aimDirection.y);
|
911 |
+
|
912 |
+
// λΆλλ¬μ΄ μ‘°μ€
|
913 |
+
const yawDiff = targetYaw - this.rotation.y;
|
914 |
+
const normalizedYawDiff = ((yawDiff + Math.PI) % (2 * Math.PI)) - Math.PI;
|
915 |
+
|
916 |
+
this.targetRotation.y += normalizedYawDiff * deltaTime * 1.0;
|
917 |
+
this.targetRotation.x = THREE.MathUtils.lerp(this.targetRotation.x, targetPitch, deltaTime * 2.0);
|
918 |
+
|
919 |
+
// μ¬κ²© νλ¨
|
920 |
+
const distanceToPlayer = this.position.distanceTo(playerPosition);
|
921 |
+
const aimAccuracy = Math.abs(normalizedYawDiff) + Math.abs(targetPitch - this.rotation.x);
|
922 |
+
|
923 |
+
if (distanceToPlayer < 1500 && aimAccuracy < 0.1) {
|
924 |
+
// μ°λ° μ¬κ²© μμ€ν
|
925 |
+
const now = Date.now();
|
926 |
+
if (now - this.lastBurstTime > 2000) { // 2μ΄λ§λ€ μ°λ°
|
927 |
+
this.burstCount = 0;
|
928 |
+
this.lastBurstTime = now;
|
929 |
+
}
|
930 |
+
|
931 |
+
if (this.burstCount < 5 && now - this.lastShootTime > 200) { // 0.2μ΄ κ°κ²©μΌλ‘ 5λ°
|
932 |
+
this.shoot();
|
933 |
+
this.burstCount++;
|
934 |
+
}
|
935 |
+
}
|
936 |
+
|
937 |
+
// ννΌ κΈ°λ
|
938 |
+
if (distanceToPlayer < 500) {
|
939 |
+
// λ무 κ°κΉμ°λ©΄ κΈμ ν
|
940 |
+
this.targetRotation.z = Math.sin(Date.now() * 0.001) * 0.5;
|
941 |
+
this.targetRotation.y += deltaTime * 2.0 * (Math.random() > 0.5 ? 1 : -1);
|
942 |
+
}
|
943 |
+
}
|
944 |
|
945 |
+
updatePhysics(deltaTime) {
|
946 |
+
if (!this.mesh) return;
|
947 |
+
|
948 |
+
// λΆλλ¬μ΄ νμ μ μ©
|
949 |
+
this.rotation.x = THREE.MathUtils.lerp(this.rotation.x, this.targetRotation.x, deltaTime * 2.0);
|
950 |
+
this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetRotation.y, deltaTime * 1.5);
|
951 |
+
this.rotation.z = THREE.MathUtils.lerp(this.rotation.z, this.targetRotation.z, deltaTime * 3.0);
|
952 |
+
|
953 |
+
// μλ λ²‘ν° κ³μ°
|
954 |
+
const forward = new THREE.Vector3(0, 0, 1);
|
955 |
+
forward.applyEuler(this.rotation);
|
956 |
+
this.velocity = forward.multiplyScalar(this.speed);
|
957 |
+
|
958 |
+
// μμΉ μ
λ°μ΄νΈ
|
959 |
+
this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
|
960 |
+
|
961 |
+
// κ³ λ μ ν
|
962 |
+
if (this.position.y < 500) {
|
963 |
+
this.position.y = 500;
|
964 |
+
this.targetRotation.x = -0.2; // μμΉ
|
965 |
+
} else if (this.position.y > 8000) {
|
966 |
+
this.position.y = 8000;
|
967 |
+
this.targetRotation.x = 0.2; // νκ°
|
968 |
+
}
|
969 |
+
|
970 |
+
// λ§΅ κ²½κ³ μ²λ¦¬
|
971 |
+
const mapLimit = GAME_CONSTANTS.MAP_SIZE / 2;
|
972 |
+
if (Math.abs(this.position.x) > mapLimit * 0.9 || Math.abs(this.position.z) > mapLimit * 0.9) {
|
973 |
+
// λ§΅ μ€μμ ν₯ν΄ νμ
|
974 |
+
const centerDirection = new THREE.Vector3(0, this.position.y, 0).sub(this.position).normalize();
|
975 |
+
this.targetRotation.y = Math.atan2(centerDirection.x, centerDirection.z);
|
976 |
+
}
|
977 |
+
|
978 |
+
// λ©μ μ
λ°μ΄νΈ
|
979 |
+
this.mesh.position.copy(this.position);
|
980 |
+
this.mesh.rotation.x = this.rotation.x;
|
981 |
+
this.mesh.rotation.y = this.rotation.y + Math.PI;
|
982 |
+
this.mesh.rotation.z = this.rotation.z;
|
983 |
+
|
984 |
+
// μλ λ‘€ 볡κ·
|
985 |
+
if (Math.abs(this.targetRotation.z) > 0.01) {
|
986 |
+
this.targetRotation.z *= 0.95;
|
987 |
+
}
|
988 |
+
}
|
989 |
|
990 |
+
shoot() {
|
991 |
+
this.lastShootTime = Date.now();
|
992 |
+
|
993 |
+
// μ§μ λͺ¨μμ νν (100% λ ν¬κ²)
|
994 |
+
const bulletGeometry = new THREE.CylinderGeometry(0.8, 0.8, 12, 8);
|
995 |
+
const bulletMaterial = new THREE.MeshBasicMaterial({
|
996 |
+
color: 0xff0000,
|
997 |
+
emissive: 0xff0000,
|
998 |
+
emissiveIntensity: 1.0
|
999 |
+
});
|
1000 |
+
const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
|
1001 |
+
|
1002 |
+
// κΈ°μ λμμ λ°μ¬ (8 β 12λ‘ μ¦κ°)
|
1003 |
+
const muzzleOffset = new THREE.Vector3(0, 0, 12); // κΈ°μ‘΄ 8μμ 12λ‘ λ³κ²½
|
1004 |
+
muzzleOffset.applyEuler(this.rotation);
|
1005 |
+
bullet.position.copy(this.position).add(muzzleOffset);
|
1006 |
+
|
1007 |
+
// ννμ λ°μ¬ λ°©ν₯μΌλ‘ νμ
|
1008 |
+
bullet.rotation.copy(this.rotation);
|
1009 |
+
bullet.rotateX(Math.PI / 2);
|
1010 |
+
|
1011 |
+
const direction = new THREE.Vector3(0, 0, 1);
|
1012 |
+
direction.applyEuler(this.rotation);
|
1013 |
+
bullet.velocity = direction.multiplyScalar(1200);
|
1014 |
+
|
1015 |
+
this.scene.add(bullet);
|
1016 |
+
this.bullets.push(bullet);
|
1017 |
+
|
1018 |
+
// MGLAUNCH.ogg μ리 μ¬μ - νλ μ΄μ΄κ° 3000m μ΄λ΄μ μμ λλ§
|
1019 |
+
if (this.playerFighter) {
|
1020 |
+
const distanceToPlayer = this.position.distanceTo(this.playerFighter.position);
|
1021 |
+
if (distanceToPlayer < 3000) {
|
1022 |
+
try {
|
1023 |
+
const audio = new Audio('sounds/MGLAUNCH.ogg');
|
1024 |
+
audio.volume = 0.5;
|
1025 |
+
|
1026 |
+
// 거리μ λ°λ₯Έ μλ μ‘°μ (κ±°λ¦¬κ° λ©μλ‘ μκ²)
|
1027 |
+
const volumeMultiplier = 1 - (distanceToPlayer / 3000);
|
1028 |
+
audio.volume = 0.5 * volumeMultiplier;
|
1029 |
+
|
1030 |
+
audio.play().catch(e => console.log('Enemy gunfire sound failed to play'));
|
1031 |
+
|
1032 |
+
// μ¬μ μλ£ μ λ©λͺ¨λ¦¬ μ 리
|
1033 |
+
audio.addEventListener('ended', () => {
|
1034 |
+
audio.remove();
|
1035 |
+
});
|
1036 |
+
} catch (e) {
|
1037 |
+
console.log('Audio error:', e);
|
1038 |
+
}
|
1039 |
}
|
1040 |
}
|
1041 |
}
|
|
|
1042 |
|
1043 |
updateBullets(deltaTime) {
|
1044 |
for (let i = this.bullets.length - 1; i >= 0; i--) {
|