Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -815,10 +815,6 @@ class EnemyFighter {
|
|
| 815 |
this.temporaryEvadeMode = false;
|
| 816 |
this.evadeTimer = 0;
|
| 817 |
|
| 818 |
-
// νν΄ μμ€ν
|
| 819 |
-
this.isRetreating = false;
|
| 820 |
-
this.retreatTargetDistance = 250; // λͺ©ν νν΄ κ±°λ¦¬
|
| 821 |
-
|
| 822 |
// μΆ©λ μμΈ‘
|
| 823 |
this.predictedPosition = new THREE.Vector3();
|
| 824 |
|
|
@@ -899,25 +895,6 @@ class EnemyFighter {
|
|
| 899 |
|
| 900 |
const distanceToPlayer = this.position.distanceTo(playerPosition);
|
| 901 |
|
| 902 |
-
// 100m μ΄λ΄λ©΄ μ¦μ νν΄ λͺ¨λ νμ±ν
|
| 903 |
-
if (distanceToPlayer < 100) {
|
| 904 |
-
this.isRetreating = true;
|
| 905 |
-
this.aiState = 'retreat';
|
| 906 |
-
// νν΄ μμ μ λ‘κ·Έ
|
| 907 |
-
console.log(`Enemy retreating! Distance: ${distanceToPlayer.toFixed(1)}m`);
|
| 908 |
-
}
|
| 909 |
-
|
| 910 |
-
// 250m μ΄μ λ¨μ΄μ§λ©΄ νν΄ λͺ¨λ ν΄μ
|
| 911 |
-
if (this.isRetreating && distanceToPlayer >= this.retreatTargetDistance) {
|
| 912 |
-
this.isRetreating = false;
|
| 913 |
-
console.log(`Enemy retreat complete. Distance: ${distanceToPlayer.toFixed(1)}m`);
|
| 914 |
-
}
|
| 915 |
-
|
| 916 |
-
// μν κ²°μ - νν΄κ° μ΅μ°μ
|
| 917 |
-
if (this.isRetreating) {
|
| 918 |
-
this.aiState = 'retreat';
|
| 919 |
-
// νν΄ μ€μλ λ€λ₯Έ μνλ‘ λ³κ²½ λΆκ°
|
| 920 |
-
} else if (this.temporaryEvadeMode) {
|
| 921 |
this.aiState = 'evade';
|
| 922 |
} else if (distanceToPlayer <= 3000) {
|
| 923 |
this.aiState = 'combat';
|
|
@@ -925,11 +902,9 @@ class EnemyFighter {
|
|
| 925 |
this.aiState = 'patrol';
|
| 926 |
}
|
| 927 |
|
| 928 |
-
// μΆ©λ ννΌ κ³μ°
|
| 929 |
-
|
| 930 |
-
|
| 931 |
-
this.checkCollisionPrediction(deltaTime);
|
| 932 |
-
}
|
| 933 |
|
| 934 |
// AI νλ μ€ν
|
| 935 |
switch (this.aiState) {
|
|
@@ -942,9 +917,6 @@ class EnemyFighter {
|
|
| 942 |
case 'evade':
|
| 943 |
this.executeEmergencyEvade(deltaTime);
|
| 944 |
break;
|
| 945 |
-
case 'retreat':
|
| 946 |
-
this.executeRetreat(playerPosition, deltaTime);
|
| 947 |
-
break;
|
| 948 |
}
|
| 949 |
|
| 950 |
// 물리 μ
λ°μ΄νΈ
|
|
@@ -954,56 +926,6 @@ class EnemyFighter {
|
|
| 954 |
this.updateBullets(deltaTime);
|
| 955 |
}
|
| 956 |
|
| 957 |
-
// μλ‘μ΄ λ©μλ: νν΄ μ€ν
|
| 958 |
-
executeRetreat(playerPosition, deltaTime) {
|
| 959 |
-
// νλ μ΄μ΄λ‘λΆν° λ©μ΄μ§λ λ°©ν₯ κ³μ°
|
| 960 |
-
const retreatDirection = this.position.clone().sub(playerPosition).normalize();
|
| 961 |
-
|
| 962 |
-
// μν λ°©ν₯ κ°μ‘° (μμ§ μ΄λ κ°μ)
|
| 963 |
-
retreatDirection.y *= 0.3;
|
| 964 |
-
retreatDirection.normalize();
|
| 965 |
-
|
| 966 |
-
// λͺ©ν μμΉ μ€μ (νμ¬ μμΉμμ νλ μ΄μ΄ λ°λ λ°©ν₯μΌλ‘ 500m)
|
| 967 |
-
const targetPosition = this.position.clone().add(retreatDirection.multiplyScalar(500));
|
| 968 |
-
|
| 969 |
-
// νν΄ μ€μλ μ΅λ μλ
|
| 970 |
-
this.speed = this.maxSpeed;
|
| 971 |
-
|
| 972 |
-
// λ§€μ° λΉ λ₯Έ νμ μΌλ‘ μ¦μ νν΄ λ°©ν₯μ ν₯νλλ‘
|
| 973 |
-
const targetYaw = Math.atan2(retreatDirection.x, retreatDirection.z);
|
| 974 |
-
const targetPitch = Math.asin(-retreatDirection.y);
|
| 975 |
-
|
| 976 |
-
// κΈ΄κΈ νμ μλ (3λ°° λΉ λ₯΄κ²)
|
| 977 |
-
const emergencyTurnSpeed = this.turnSpeed * 3.0;
|
| 978 |
-
const maxTurnRate = emergencyTurnSpeed * deltaTime;
|
| 979 |
-
|
| 980 |
-
// Yaw νμ (μ¦μ νμ )
|
| 981 |
-
const yawDiff = this.normalizeAngle(targetYaw - this.rotation.y);
|
| 982 |
-
if (Math.abs(yawDiff) > maxTurnRate) {
|
| 983 |
-
this.rotation.y += Math.sign(yawDiff) * maxTurnRate;
|
| 984 |
-
} else {
|
| 985 |
-
this.rotation.y = targetYaw;
|
| 986 |
-
}
|
| 987 |
-
|
| 988 |
-
// Pitch νμ (μ νμ μ΄μ§λ§ λΉ λ₯΄κ²)
|
| 989 |
-
const pitchDiff = targetPitch - this.rotation.x;
|
| 990 |
-
if (Math.abs(pitchDiff) > maxTurnRate * 0.7) {
|
| 991 |
-
this.rotation.x += Math.sign(pitchDiff) * maxTurnRate * 0.7;
|
| 992 |
-
} else {
|
| 993 |
-
this.rotation.x = targetPitch;
|
| 994 |
-
}
|
| 995 |
-
|
| 996 |
-
// νν΄ μ€ κΈμ νλ₯Ό μν λ‘€
|
| 997 |
-
this.rotation.z = Math.sign(yawDiff) * Math.min(Math.abs(yawDiff), Math.PI / 4);
|
| 998 |
-
|
| 999 |
-
// νν΄ μ€μλ λ°μ¬ κΈμ§
|
| 1000 |
-
this.canShoot = false;
|
| 1001 |
-
this.burstCounter = 0;
|
| 1002 |
-
|
| 1003 |
-
// μΆ©λ ννΌ λ²‘ν° μ΄κΈ°ν (νν΄κ° μ°μ )
|
| 1004 |
-
this.avoidanceVector.set(0, 0, 0);
|
| 1005 |
-
}
|
| 1006 |
-
|
| 1007 |
executePatrol(deltaTime) {
|
| 1008 |
// λͺ©ν μ§μ κΉμ§μ 거리 νμΈ
|
| 1009 |
if (!this.targetPosition || this.position.distanceTo(this.targetPosition) < 500) {
|
|
@@ -1023,13 +945,6 @@ class EnemyFighter {
|
|
| 1023 |
executeCombat(playerPosition, deltaTime) {
|
| 1024 |
const distance = this.position.distanceTo(playerPosition);
|
| 1025 |
|
| 1026 |
-
// 100m λ―Έλ§μ΄λ©΄ μ¦μ νν΄λ‘ μ ν (μ΄μ€ 체ν¬)
|
| 1027 |
-
if (distance < 100) {
|
| 1028 |
-
this.isRetreating = true;
|
| 1029 |
-
this.aiState = 'retreat';
|
| 1030 |
-
console.log(`Combat -> Retreat triggered! Distance: ${distance.toFixed(1)}m`);
|
| 1031 |
-
return; // μ¦μ 리ν΄νμ¬ μ ν¬ λ‘μ§ μ€ν λ°©μ§
|
| 1032 |
-
}
|
| 1033 |
|
| 1034 |
// νλ μ΄μ΄λ₯Ό ν₯ν΄ νμ
|
| 1035 |
this.smoothTurnToTarget(playerPosition, deltaTime);
|
|
@@ -1043,8 +958,7 @@ class EnemyFighter {
|
|
| 1043 |
const isStraightFlying = isPitchLevel && isRollLevel;
|
| 1044 |
|
| 1045 |
// μ§μ§ λΉν μ€μ΄κ³ μ νν μ‘°μ€ μμλ§ λ°μ¬ κ°λ₯
|
| 1046 |
-
|
| 1047 |
-
this.canShoot = isStraightFlying && aimAccuracy < 0.15 && distance > 200;
|
| 1048 |
|
| 1049 |
// λ°μ¬ 쑰건 μΆ©μ‘± μ λ°μ¬
|
| 1050 |
if (this.canShoot) {
|
|
@@ -1148,46 +1062,7 @@ class EnemyFighter {
|
|
| 1148 |
}
|
| 1149 |
|
| 1150 |
smoothTurnToTarget(targetPos, deltaTime, isEmergency = false) {
|
| 1151 |
-
|
| 1152 |
-
if (this.isRetreating) {
|
| 1153 |
-
// νκ² λ°©ν₯ κ³μ°
|
| 1154 |
-
const direction = targetPos.clone().sub(this.position);
|
| 1155 |
-
direction.y *= 0.5;
|
| 1156 |
-
direction.normalize();
|
| 1157 |
-
|
| 1158 |
-
// λͺ©ν νμ κ³μ°
|
| 1159 |
-
const targetYaw = Math.atan2(direction.x, direction.z);
|
| 1160 |
-
const targetPitch = Math.asin(-direction.y);
|
| 1161 |
-
|
| 1162 |
-
// νν΄ μ€μλ λ§€μ° λΉ λ₯Έ νμ
|
| 1163 |
-
const turnSpeed = this.turnSpeed * 3.0;
|
| 1164 |
-
const maxTurnRate = turnSpeed * deltaTime;
|
| 1165 |
-
|
| 1166 |
-
// Yaw νμ
|
| 1167 |
-
const yawDiff = this.normalizeAngle(targetYaw - this.rotation.y);
|
| 1168 |
-
if (Math.abs(yawDiff) > maxTurnRate) {
|
| 1169 |
-
this.rotation.y += Math.sign(yawDiff) * maxTurnRate;
|
| 1170 |
-
} else {
|
| 1171 |
-
this.rotation.y = targetYaw;
|
| 1172 |
-
}
|
| 1173 |
-
|
| 1174 |
-
// Pitch νμ
|
| 1175 |
-
const maxPitchRate = maxTurnRate * 0.7;
|
| 1176 |
-
if (Math.abs(targetPitch - this.rotation.x) > maxPitchRate) {
|
| 1177 |
-
this.rotation.x += Math.sign(targetPitch - this.rotation.x) * maxPitchRate;
|
| 1178 |
-
} else {
|
| 1179 |
-
this.rotation.x = targetPitch;
|
| 1180 |
-
}
|
| 1181 |
-
|
| 1182 |
-
// Pitch μ ν
|
| 1183 |
-
const maxPitchAngle = Math.PI * 40 / 180;
|
| 1184 |
-
this.rotation.x = THREE.MathUtils.clamp(this.rotation.x, -maxPitchAngle, maxPitchAngle);
|
| 1185 |
-
|
| 1186 |
-
// νν΄ μ€ κΈμ νλ₯Ό μν λ‘€
|
| 1187 |
-
this.rotation.z = Math.sign(yawDiff) * Math.min(Math.abs(yawDiff), Math.PI / 3);
|
| 1188 |
-
|
| 1189 |
-
return; // νν΄ μ€μ΄λ©΄ μ¬κΈ°μ μ’
λ£
|
| 1190 |
-
}
|
| 1191 |
|
| 1192 |
// κΈ°μ‘΄ λ‘μ§ (νν΄κ° μλ λ)
|
| 1193 |
const direction = targetPos.clone().sub(this.position);
|
|
|
|
| 815 |
this.temporaryEvadeMode = false;
|
| 816 |
this.evadeTimer = 0;
|
| 817 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 818 |
// μΆ©λ μμΈ‘
|
| 819 |
this.predictedPosition = new THREE.Vector3();
|
| 820 |
|
|
|
|
| 895 |
|
| 896 |
const distanceToPlayer = this.position.distanceTo(playerPosition);
|
| 897 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 898 |
this.aiState = 'evade';
|
| 899 |
} else if (distanceToPlayer <= 3000) {
|
| 900 |
this.aiState = 'combat';
|
|
|
|
| 902 |
this.aiState = 'patrol';
|
| 903 |
}
|
| 904 |
|
| 905 |
+
// μΆ©λ ννΌ κ³μ°
|
| 906 |
+
this.calculateAvoidance();
|
| 907 |
+
this.checkCollisionPrediction(deltaTime);
|
|
|
|
|
|
|
| 908 |
|
| 909 |
// AI νλ μ€ν
|
| 910 |
switch (this.aiState) {
|
|
|
|
| 917 |
case 'evade':
|
| 918 |
this.executeEmergencyEvade(deltaTime);
|
| 919 |
break;
|
|
|
|
|
|
|
|
|
|
| 920 |
}
|
| 921 |
|
| 922 |
// 물리 μ
λ°μ΄νΈ
|
|
|
|
| 926 |
this.updateBullets(deltaTime);
|
| 927 |
}
|
| 928 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 929 |
executePatrol(deltaTime) {
|
| 930 |
// λͺ©ν μ§μ κΉμ§μ 거리 νμΈ
|
| 931 |
if (!this.targetPosition || this.position.distanceTo(this.targetPosition) < 500) {
|
|
|
|
| 945 |
executeCombat(playerPosition, deltaTime) {
|
| 946 |
const distance = this.position.distanceTo(playerPosition);
|
| 947 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 948 |
|
| 949 |
// νλ μ΄μ΄λ₯Ό ν₯ν΄ νμ
|
| 950 |
this.smoothTurnToTarget(playerPosition, deltaTime);
|
|
|
|
| 958 |
const isStraightFlying = isPitchLevel && isRollLevel;
|
| 959 |
|
| 960 |
// μ§μ§ λΉν μ€μ΄κ³ μ νν μ‘°μ€ μμλ§ λ°μ¬ κ°λ₯
|
| 961 |
+
this.canShoot = isStraightFlying && aimAccuracy < 0.15;
|
|
|
|
| 962 |
|
| 963 |
// λ°μ¬ 쑰건 μΆ©μ‘± μ λ°μ¬
|
| 964 |
if (this.canShoot) {
|
|
|
|
| 1062 |
}
|
| 1063 |
|
| 1064 |
smoothTurnToTarget(targetPos, deltaTime, isEmergency = false) {
|
| 1065 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1066 |
|
| 1067 |
// κΈ°μ‘΄ λ‘μ§ (νν΄κ° μλ λ)
|
| 1068 |
const direction = targetPos.clone().sub(this.position);
|