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);
|