cutechicken commited on
Commit
a1365cd
·
verified ·
1 Parent(s): dd3a438

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +55 -10
game.js CHANGED
@@ -809,7 +809,7 @@ class EnemyFighter {
809
  this.maxSpeed = 386; // 750kt in m/s
810
 
811
  // AI 상태
812
- this.aiState = 'patrol'; // patrol, combat, evade
813
  this.targetPosition = null;
814
  this.playerFighter = null;
815
 
@@ -817,6 +817,10 @@ class EnemyFighter {
817
  this.temporaryEvadeMode = false;
818
  this.evadeTimer = 0;
819
 
 
 
 
 
820
  // 충돌 예측
821
  this.predictedPosition = new THREE.Vector3();
822
 
@@ -897,8 +901,21 @@ class EnemyFighter {
897
 
898
  const distanceToPlayer = this.position.distanceTo(playerPosition);
899
 
900
- // 상태 결정 - 일시적 회피 모드가 우선
901
- if (this.temporaryEvadeMode) {
 
 
 
 
 
 
 
 
 
 
 
 
 
902
  this.aiState = 'evade';
903
  } else if (distanceToPlayer <= 3000) {
904
  this.aiState = 'combat';
@@ -923,6 +940,9 @@ class EnemyFighter {
923
  case 'evade':
924
  this.executeEmergencyEvade(deltaTime);
925
  break;
 
 
 
926
  }
927
 
928
  // 물리 업데이트
@@ -932,6 +952,24 @@ class EnemyFighter {
932
  this.updateBullets(deltaTime);
933
  }
934
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
935
  executePatrol(deltaTime) {
936
  // 목표 지점까지의 거리 확인
937
  if (!this.targetPosition || this.position.distanceTo(this.targetPosition) < 500) {
@@ -949,6 +987,14 @@ class EnemyFighter {
949
  }
950
 
951
  executeCombat(playerPosition, deltaTime) {
 
 
 
 
 
 
 
 
952
  // 플레이어를 향해 회전
953
  this.smoothTurnToTarget(playerPosition, deltaTime);
954
 
@@ -961,7 +1007,7 @@ class EnemyFighter {
961
  const isStraightFlying = isPitchLevel && isRollLevel;
962
 
963
  // 직진 비행 중이고 정확한 조준 시에만 발사 가능
964
- this.canShoot = isStraightFlying && aimAccuracy < 0.15;
965
 
966
  // 발사 조건 충족 시 발사
967
  if (this.canShoot) {
@@ -972,7 +1018,6 @@ class EnemyFighter {
972
  }
973
 
974
  // 거리에 따라 자유롭게 기동 결정
975
- const distance = this.position.distanceTo(playerPosition);
976
  if (distance < 500) {
977
  // 너무 가까우면 회피 기동
978
  this.selectEvadeTarget();
@@ -1059,15 +1104,15 @@ class EnemyFighter {
1059
  this.speed = this.maxSpeed;
1060
  }
1061
 
1062
- smoothTurnToTarget(targetPos, deltaTime) {
1063
  // 타겟 방향 계산
1064
  const direction = targetPos.clone().sub(this.position);
1065
  direction.y *= 0.5; // 수직 이동을 덜 제한적으로
1066
  direction.normalize();
1067
 
1068
  // 충돌 회피 벡터 적용 (회피가 우선)
1069
- if (this.avoidanceVector.length() > 0) {
1070
- // 회피 모드에서는 회피 벡터의 영향을 크게
1071
  const avoidanceStrength = this.temporaryEvadeMode ? 1.0 : 0.5;
1072
  direction.add(this.avoidanceVector.multiplyScalar(avoidanceStrength));
1073
  direction.normalize();
@@ -1078,7 +1123,7 @@ class EnemyFighter {
1078
  const targetPitch = Math.asin(-direction.y);
1079
 
1080
  // 부드러운 회전 (최대 회전 속도 제한)
1081
- const turnSpeed = this.temporaryEvadeMode ? this.turnSpeed * 1.5 : this.turnSpeed;
1082
  const maxTurnRate = turnSpeed * deltaTime;
1083
 
1084
  // Yaw 회전
@@ -1102,7 +1147,7 @@ class EnemyFighter {
1102
  this.rotation.x = THREE.MathUtils.clamp(this.rotation.x, -maxPitchAngle, maxPitchAngle);
1103
 
1104
  // 롤 자동 계산 (선회 시)
1105
- if (!this.temporaryEvadeMode) {
1106
  this.rotation.z = -yawDiff * 0.5; // 선회 방향으로 기울기
1107
  this.rotation.z = THREE.MathUtils.clamp(this.rotation.z, -Math.PI / 4, Math.PI / 4);
1108
  }
 
809
  this.maxSpeed = 386; // 750kt in m/s
810
 
811
  // AI 상태
812
+ this.aiState = 'patrol'; // patrol, combat, evade, retreat
813
  this.targetPosition = null;
814
  this.playerFighter = null;
815
 
 
817
  this.temporaryEvadeMode = false;
818
  this.evadeTimer = 0;
819
 
820
+ // 후퇴 시스템
821
+ this.isRetreating = false;
822
+ this.retreatTargetDistance = 250; // 목표 후퇴 거리
823
+
824
  // 충돌 예측
825
  this.predictedPosition = new THREE.Vector3();
826
 
 
901
 
902
  const distanceToPlayer = this.position.distanceTo(playerPosition);
903
 
904
+ // 100m 이내면 즉시 후퇴 모드 활성화
905
+ if (distanceToPlayer < 100) {
906
+ this.isRetreating = true;
907
+ this.aiState = 'retreat';
908
+ }
909
+
910
+ // 250m 이상 떨어지면 후퇴 모드 해제
911
+ if (this.isRetreating && distanceToPlayer >= this.retreatTargetDistance) {
912
+ this.isRetreating = false;
913
+ }
914
+
915
+ // 상태 결정 - 후퇴가 최우선
916
+ if (this.isRetreating) {
917
+ this.aiState = 'retreat';
918
+ } else if (this.temporaryEvadeMode) {
919
  this.aiState = 'evade';
920
  } else if (distanceToPlayer <= 3000) {
921
  this.aiState = 'combat';
 
940
  case 'evade':
941
  this.executeEmergencyEvade(deltaTime);
942
  break;
943
+ case 'retreat':
944
+ this.executeRetreat(playerPosition, deltaTime);
945
+ break;
946
  }
947
 
948
  // 물리 업데이트
 
952
  this.updateBullets(deltaTime);
953
  }
954
 
955
+ // 새로운 메서드: 후퇴 실행
956
+ executeRetreat(playerPosition, deltaTime) {
957
+ // 플레이어로부터 멀어지는 방향 계산
958
+ const retreatDirection = this.position.clone().sub(playerPosition).normalize();
959
+
960
+ // 목표 위치 설정 (현재 위치에서 플레이어 반대 방향으로)
961
+ const targetPosition = this.position.clone().add(retreatDirection.multiplyScalar(200));
962
+
963
+ // 후퇴 중에는 최대 속도
964
+ this.speed = this.maxSpeed;
965
+
966
+ // 빠른 회전으로 후퇴
967
+ this.smoothTurnToTarget(targetPosition, deltaTime, true); // true는 긴급 회전
968
+
969
+ // 후퇴 중에는 발사 금지
970
+ this.canShoot = false;
971
+ }
972
+
973
  executePatrol(deltaTime) {
974
  // 목표 지점까지의 거리 확인
975
  if (!this.targetPosition || this.position.distanceTo(this.targetPosition) < 500) {
 
987
  }
988
 
989
  executeCombat(playerPosition, deltaTime) {
990
+ const distance = this.position.distanceTo(playerPosition);
991
+
992
+ // 100m 미만이면 즉시 후퇴 (이중 체크)
993
+ if (distance < 100) {
994
+ this.isRetreating = true;
995
+ return;
996
+ }
997
+
998
  // 플레이어를 향해 회전
999
  this.smoothTurnToTarget(playerPosition, deltaTime);
1000
 
 
1007
  const isStraightFlying = isPitchLevel && isRollLevel;
1008
 
1009
  // 직진 비행 중이고 정확한 조준 시에만 발사 가능
1010
+ this.canShoot = isStraightFlying && aimAccuracy < 0.15 && distance > 150; // 150m 이상에서만 발사
1011
 
1012
  // 발사 조건 충족 시 발사
1013
  if (this.canShoot) {
 
1018
  }
1019
 
1020
  // 거리에 따라 자유롭게 기동 결정
 
1021
  if (distance < 500) {
1022
  // 너무 가까우면 회피 기동
1023
  this.selectEvadeTarget();
 
1104
  this.speed = this.maxSpeed;
1105
  }
1106
 
1107
+ smoothTurnToTarget(targetPos, deltaTime, isEmergency = false) {
1108
  // 타겟 방향 계산
1109
  const direction = targetPos.clone().sub(this.position);
1110
  direction.y *= 0.5; // 수직 이동을 덜 제한적으로
1111
  direction.normalize();
1112
 
1113
  // 충돌 회피 벡터 적용 (회피가 우선)
1114
+ if (this.avoidanceVector.length() > 0 && !this.isRetreating) {
1115
+ // 후퇴 중이 아닐 때만 회피 벡터 적용
1116
  const avoidanceStrength = this.temporaryEvadeMode ? 1.0 : 0.5;
1117
  direction.add(this.avoidanceVector.multiplyScalar(avoidanceStrength));
1118
  direction.normalize();
 
1123
  const targetPitch = Math.asin(-direction.y);
1124
 
1125
  // 부드러운 회전 (최대 회전 속도 제한)
1126
+ const turnSpeed = isEmergency ? this.turnSpeed * 2.0 : (this.temporaryEvadeMode ? this.turnSpeed * 1.5 : this.turnSpeed);
1127
  const maxTurnRate = turnSpeed * deltaTime;
1128
 
1129
  // Yaw 회전
 
1147
  this.rotation.x = THREE.MathUtils.clamp(this.rotation.x, -maxPitchAngle, maxPitchAngle);
1148
 
1149
  // 롤 자동 계산 (선회 시)
1150
+ if (!this.temporaryEvadeMode && !this.isRetreating) {
1151
  this.rotation.z = -yawDiff * 0.5; // 선회 방향으로 기울기
1152
  this.rotation.z = THREE.MathUtils.clamp(this.rotation.z, -Math.PI / 4, Math.PI / 4);
1153
  }