Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
@@ -795,167 +795,6 @@ class EnemyFighter {
|
|
795 |
}
|
796 |
|
797 |
update(playerPosition, deltaTime) {
|
798 |
-
if (!this.mesh || !this.isLoaded) return;
|
799 |
-
|
800 |
-
const currentTime = Date.now();
|
801 |
-
const distanceToPlayer = this.position.distanceTo(playerPosition);
|
802 |
-
|
803 |
-
// νλ μ΄μ΄ κ°μ§ λ° μ ν¬ μν μ ν
|
804 |
-
if (distanceToPlayer < 3000) {
|
805 |
-
this.isEngaged = true;
|
806 |
-
this.aiState = 'combat';
|
807 |
-
|
808 |
-
// νλ μ΄μ΄κ° μμΌκ° λ΄μ μλμ§ νμΈ
|
809 |
-
const toPlayer = playerPosition.clone().sub(this.position).normalize();
|
810 |
-
const forward = new THREE.Vector3(0, 0, 1);
|
811 |
-
forward.applyEuler(this.rotation);
|
812 |
-
const angle = forward.dot(toPlayer);
|
813 |
-
|
814 |
-
// μμΈ‘ μ¬κ²©μ μν νλ μ΄μ΄ μλ κ³μ°
|
815 |
-
if (this.playerFighter) {
|
816 |
-
const bulletSpeed = 1200; // νν μλ
|
817 |
-
const timeToHit = distanceToPlayer / bulletSpeed;
|
818 |
-
|
819 |
-
// νλ μ΄μ΄μ μμ μμΉ κ³μ°
|
820 |
-
this.predictedTargetPos = playerPosition.clone().add(
|
821 |
-
this.playerFighter.velocity.clone().multiplyScalar(timeToHit)
|
822 |
-
);
|
823 |
-
}
|
824 |
-
|
825 |
-
// μ¬κ²© 쑰건: μμΌκ° λ΄μ μκ³ κ±°λ¦¬κ° 2000m μ΄λ΄
|
826 |
-
if (angle > 0.7 && distanceToPlayer < 2000) { // μμΌκ°μ μ’νμ μ νλ ν₯μ
|
827 |
-
// μ°λ° μ¬κ²© μμ€ν
|
828 |
-
const timeSinceLastBurst = currentTime - this.lastBurstTime;
|
829 |
-
|
830 |
-
// 2μ΄λ§λ€ μλ‘μ΄ μ°λ° μμ
|
831 |
-
if (timeSinceLastBurst >= 2000) {
|
832 |
-
this.burstCount = 0;
|
833 |
-
this.lastBurstTime = currentTime;
|
834 |
-
}
|
835 |
-
|
836 |
-
// 10λ° μ°λ° (0.1μ΄ κ°κ²©)
|
837 |
-
if (this.burstCount < 10 && currentTime - this.lastShootTime >= 100) {
|
838 |
-
this.shoot();
|
839 |
-
this.burstCount++;
|
840 |
-
}
|
841 |
-
}
|
842 |
-
} else {
|
843 |
-
this.isEngaged = false;
|
844 |
-
this.aiState = 'patrol';
|
845 |
-
}
|
846 |
-
|
847 |
-
// μ ν¬ μ€μΌ λ νλ μ΄μ΄ μΆμ
|
848 |
-
if (this.isEngaged && this.playerFighter) {
|
849 |
-
// νλ μ΄μ΄μ κΈ°λ ν¨ν΄ λͺ¨λ°©
|
850 |
-
const playerVelocity = this.playerFighter.velocity.clone().normalize();
|
851 |
-
const playerRoll = this.playerFighter.rotation.z;
|
852 |
-
const playerPitch = this.playerFighter.rotation.x;
|
853 |
-
|
854 |
-
// μμΈ‘λ μμΉλ‘ ν₯νλλ‘ μ€μ
|
855 |
-
this.targetPosition = this.predictedTargetPos.clone();
|
856 |
-
|
857 |
-
// νλ μ΄μ΄μ λΉμ·ν λ‘€ μ μ© (μ½κ°μ μ§μ°μΌλ‘)
|
858 |
-
this.targetRotation.z = playerRoll * 0.7;
|
859 |
-
|
860 |
-
// κ³ λ μ°¨μ΄μ λ°λ₯Έ νΌμΉ μ‘°μ (λ λΆλλ½κ³ κΈΈκ²)
|
861 |
-
const altitudeDiff = this.targetPosition.y - this.position.y;
|
862 |
-
|
863 |
-
// νΌμΉ λ³νλ₯Ό λ λΆλλ½κ² (κΈ°μ‘΄ 0.0003 β 0.00015λ‘ 50% κ°μ)
|
864 |
-
this.targetRotation.x = Math.max(-0.3, Math.min(0.3, altitudeDiff * 0.00015));
|
865 |
-
} else {
|
866 |
-
// μμ°° λͺ¨λ
|
867 |
-
if (this.position.distanceTo(this.targetPosition) < 500 ||
|
868 |
-
currentTime - this.lastDirectionChange > 15000) {
|
869 |
-
this.targetPosition = this.generateRandomTarget();
|
870 |
-
this.lastDirectionChange = currentTime;
|
871 |
-
this.isTurning = false;
|
872 |
-
}
|
873 |
-
}
|
874 |
-
|
875 |
-
// λͺ©ν λ°©ν₯ κ³μ°
|
876 |
-
const toTarget = this.targetPosition.clone().sub(this.position);
|
877 |
-
const targetAngle = Math.atan2(toTarget.x, toTarget.z);
|
878 |
-
let angleDiff = targetAngle - this.rotation.y;
|
879 |
-
|
880 |
-
// κ°λ μ°¨μ΄λ₯Ό -PI ~ PI λ²μλ‘ μ κ·ν
|
881 |
-
while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
|
882 |
-
while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
|
883 |
-
|
884 |
-
// μ ν¬ μ€μλ λ λΉ λ₯Έ μ ν
|
885 |
-
const turnRateMultiplier = this.isEngaged ? 2.0 : 1.0;
|
886 |
-
|
887 |
-
// ν° κ°λ μ°¨μ΄κ° μμΌλ©΄ μν μ ν
|
888 |
-
if (Math.abs(angleDiff) > Math.PI / 6) {
|
889 |
-
this.isTurning = true;
|
890 |
-
this.turnDirection = angleDiff > 0 ? 1 : -1;
|
891 |
-
}
|
892 |
-
|
893 |
-
// μ ν μ€μΌ λ
|
894 |
-
if (this.isTurning) {
|
895 |
-
// μν μ ν ꡬν (μ ν¬ μ€μλ λ λΉ λ₯΄κ²)
|
896 |
-
const turnRate = (this.speed / this.turnRadius) * this.turnDirection * turnRateMultiplier;
|
897 |
-
this.targetRotation.y += turnRate * deltaTime;
|
898 |
-
this.targetRotation.z = this.turnDirection * 0.5 * (this.isEngaged ? 1.5 : 1); // μ ν¬ μ€ λ ν° λ‘€
|
899 |
-
|
900 |
-
// λͺ©ν κ°λμ κ·Όμ νλ©΄ μ ν μ’
λ£
|
901 |
-
const newAngleDiff = targetAngle - this.targetRotation.y;
|
902 |
-
if (Math.abs(newAngleDiff) < Math.PI / 12) {
|
903 |
-
this.isTurning = false;
|
904 |
-
}
|
905 |
-
} else {
|
906 |
-
// μ§μ§ λΉοΏ½οΏ½οΏ½ (μ ν¬ μ€μλ λ λΉ λ₯Έ λ°μ)
|
907 |
-
const lerpSpeed = this.isEngaged ? 1.0 : 0.5;
|
908 |
-
this.targetRotation.y = THREE.MathUtils.lerp(this.targetRotation.y, targetAngle, deltaTime * lerpSpeed);
|
909 |
-
this.targetRotation.z = THREE.MathUtils.lerp(this.targetRotation.z, 0, deltaTime * 2);
|
910 |
-
}
|
911 |
-
|
912 |
-
// λ€λ₯Έ μ κΈ°μμ μΆ©λ ννΌ
|
913 |
-
this.avoidOtherEnemies(deltaTime);
|
914 |
-
|
915 |
-
// λΆλλ¬μ΄ νμ μ μ© (μ ν¬ μ€μλ λ λΉ λ₯΄κ²)
|
916 |
-
const rotationSpeed = this.isEngaged ? 3.0 : 2.0;
|
917 |
-
this.rotation.x = THREE.MathUtils.lerp(this.rotation.x, this.targetRotation.x, deltaTime * rotationSpeed * 0.5); // xμΆ(νΌμΉ) νμ λ§ 50% λ리κ²
|
918 |
-
this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetRotation.y, deltaTime * rotationSpeed);
|
919 |
-
this.rotation.z = THREE.MathUtils.lerp(this.rotation.z, this.targetRotation.z, deltaTime * rotationSpeed * 1.25);
|
920 |
-
|
921 |
-
// μλ λ²‘ν° κ³μ°
|
922 |
-
const forward = new THREE.Vector3(0, 0, 1);
|
923 |
-
forward.applyEuler(this.rotation);
|
924 |
-
this.velocity = forward.multiplyScalar(this.speed);
|
925 |
-
|
926 |
-
// μμΉ μ
λ°μ΄νΈ
|
927 |
-
this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
|
928 |
-
|
929 |
-
// κ³ λ μ ν
|
930 |
-
if (this.position.y < 500) {
|
931 |
-
this.position.y = 500;
|
932 |
-
this.targetRotation.x = -0.2; // μμΉ
|
933 |
-
}
|
934 |
-
if (this.position.y > GAME_CONSTANTS.MAX_ALTITUDE - 500) {
|
935 |
-
this.position.y = GAME_CONSTANTS.MAX_ALTITUDE - 500;
|
936 |
-
this.targetRotation.x = 0.2; // νκ°
|
937 |
-
}
|
938 |
-
|
939 |
-
// λ§΅ κ²½κ³ μ²λ¦¬
|
940 |
-
const mapLimit = GAME_CONSTANTS.MAP_SIZE / 2;
|
941 |
-
if (Math.abs(this.position.x) > mapLimit * 0.9 || Math.abs(this.position.z) > mapLimit * 0.9) {
|
942 |
-
// λ§΅ κ²½κ³μ κ°κΉμμ§λ©΄ μ€μμΌλ‘ ν₯νλ μ λͺ©ν μ€μ
|
943 |
-
this.targetPosition = new THREE.Vector3(
|
944 |
-
(Math.random() - 0.5) * mapLimit * 0.5,
|
945 |
-
1000 + Math.random() * 3000,
|
946 |
-
(Math.random() - 0.5) * mapLimit * 0.5
|
947 |
-
);
|
948 |
-
this.lastDirectionChange = currentTime;
|
949 |
-
}
|
950 |
-
|
951 |
-
// λ©μ μ
λ°μ΄νΈ
|
952 |
-
this.mesh.position.copy(this.position);
|
953 |
-
this.mesh.rotation.x = this.rotation.x;
|
954 |
-
this.mesh.rotation.y = this.rotation.y + 3 * Math.PI / 2;
|
955 |
-
this.mesh.rotation.z = this.rotation.z;
|
956 |
-
|
957 |
-
this.updateBullets(deltaTime);
|
958 |
-
}
|
959 |
|
960 |
avoidOtherEnemies(deltaTime) {
|
961 |
if (!this.nearbyEnemies) return;
|
|
|
795 |
}
|
796 |
|
797 |
update(playerPosition, deltaTime) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
798 |
|
799 |
avoidOtherEnemies(deltaTime) {
|
800 |
if (!this.nearbyEnemies) return;
|