cutechicken commited on
Commit
a23a84b
Β·
verified Β·
1 Parent(s): ab5cbc8

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +85 -37
game.js CHANGED
@@ -588,8 +588,8 @@ class Fighter {
588
 
589
  this.ammo--;
590
 
591
- // 직선 λͺ¨μ–‘μ˜ νƒ„ν™˜ (50% 더 크게)
592
- const bulletGeometry = new THREE.CylinderGeometry(0.75, 0.75, 12, 8); // λ°˜μ§€λ¦„ 0.5β†’0.75, 길이 8β†’12
593
  const bulletMaterial = new THREE.MeshBasicMaterial({
594
  color: 0xffff00,
595
  emissive: 0xffff00,
@@ -691,7 +691,7 @@ class EnemyFighter {
691
  this.velocity = new THREE.Vector3(0, 0, 120);
692
  this.rotation = new THREE.Euler(0, 0, 0);
693
  this.health = GAME_CONSTANTS.MAX_HEALTH; // 체λ ₯ 1000
694
- this.speed = 386; // 750kt in m/s (750 * 0.514444)
695
  this.bullets = [];
696
  this.lastShootTime = 0;
697
 
@@ -710,6 +710,12 @@ class EnemyFighter {
710
  // λ‹€λ₯Έ μ κΈ°λ“€κ³Όμ˜ 좩돌 νšŒν”Ό
711
  this.nearbyEnemies = [];
712
  this.separationRadius = 300; // μ΅œμ†Œ 거리 300m
 
 
 
 
 
 
713
  }
714
 
715
  generateRandomTarget() {
@@ -776,29 +782,74 @@ class EnemyFighter {
776
  const currentTime = Date.now();
777
  const distanceToPlayer = this.position.distanceTo(playerPosition);
778
 
779
- // ν”Œλ ˆμ΄μ–΄ 감지 및 곡격
780
- let shouldAttack = false;
781
  if (distanceToPlayer < 3000) {
 
 
 
782
  // ν”Œλ ˆμ΄μ–΄κ°€ μ‹œμ•Όκ° 내에 μžˆλŠ”μ§€ 확인
783
  const toPlayer = playerPosition.clone().sub(this.position).normalize();
784
  const forward = new THREE.Vector3(0, 0, 1);
785
  forward.applyEuler(this.rotation);
786
  const angle = forward.dot(toPlayer);
787
 
788
- if (angle > 0.5) { // 120도 μ‹œμ•Όκ°
789
- shouldAttack = true;
790
- if (distanceToPlayer < 2000 && currentTime - this.lastShootTime > 800) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
  this.shoot();
 
792
  }
793
  }
 
 
 
794
  }
795
 
796
- // λͺ©ν‘œ 지점 도달 λ˜λŠ” 일정 μ‹œκ°„λ§ˆλ‹€ μƒˆλ‘œμš΄ λͺ©ν‘œ μ„€μ •
797
- if (this.position.distanceTo(this.targetPosition) < 500 ||
798
- currentTime - this.lastDirectionChange > 15000) { // 15μ΄ˆλ§ˆλ‹€ λ°©ν–₯ λ³€κ²½
799
- this.targetPosition = this.generateRandomTarget();
800
- this.lastDirectionChange = currentTime;
801
- this.isTurning = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
802
  }
803
 
804
  // λͺ©ν‘œ λ°©ν–₯ 계산
@@ -810,45 +861,42 @@ class EnemyFighter {
810
  while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
811
  while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
812
 
 
 
 
813
  // 큰 각도 차이가 있으면 μ›ν˜• μ„ νšŒ
814
- if (Math.abs(angleDiff) > Math.PI / 6) { // 30도 이상
815
  this.isTurning = true;
816
  this.turnDirection = angleDiff > 0 ? 1 : -1;
817
  }
818
 
819
  // μ„ νšŒ 쀑일 λ•Œ
820
  if (this.isTurning) {
821
- // μ›ν˜• μ„ νšŒ κ΅¬ν˜„
822
- const turnRate = (this.speed / this.turnRadius) * this.turnDirection;
823
  this.targetRotation.y += turnRate * deltaTime;
824
- this.targetRotation.z = this.turnDirection * 0.5; // μ„ νšŒ μ‹œ λ‘€
825
 
826
  // λͺ©ν‘œ 각도에 κ·Όμ ‘ν•˜λ©΄ μ„ νšŒ μ’…λ£Œ
827
  const newAngleDiff = targetAngle - this.targetRotation.y;
828
- if (Math.abs(newAngleDiff) < Math.PI / 12) { // 15도 이내
829
  this.isTurning = false;
830
  }
831
  } else {
832
- // 직진 λΉ„ν–‰
833
- this.targetRotation.y = THREE.MathUtils.lerp(this.targetRotation.y, targetAngle, deltaTime * 0.5);
 
834
  this.targetRotation.z = THREE.MathUtils.lerp(this.targetRotation.z, 0, deltaTime * 2);
835
  }
836
 
837
- // 고도 쑰절
838
- const altitudeDiff = this.targetPosition.y - this.position.y;
839
- if (Math.abs(altitudeDiff) > 100) {
840
- this.targetRotation.x = Math.max(-0.3, Math.min(0.3, altitudeDiff * 0.0001));
841
- } else {
842
- this.targetRotation.x = 0;
843
- }
844
-
845
  // λ‹€λ₯Έ μ κΈ°μ™€μ˜ 좩돌 νšŒν”Ό
846
  this.avoidOtherEnemies(deltaTime);
847
 
848
- // λΆ€λ“œλŸ¬μš΄ νšŒμ „ 적용
849
- this.rotation.x = THREE.MathUtils.lerp(this.rotation.x, this.targetRotation.x, deltaTime * 2.0);
850
- this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetRotation.y, deltaTime * 2.0);
851
- this.rotation.z = THREE.MathUtils.lerp(this.rotation.z, this.targetRotation.z, deltaTime * 2.5);
 
852
 
853
  // 속도 벑터 계산
854
  const forward = new THREE.Vector3(0, 0, 1);
@@ -928,8 +976,8 @@ class EnemyFighter {
928
  shoot() {
929
  this.lastShootTime = Date.now();
930
 
931
- // 직선 λͺ¨μ–‘μ˜ νƒ„ν™˜ (50% 더 크게)
932
- const bulletGeometry = new THREE.CylinderGeometry(0.6, 0.6, 9, 8); // λ°˜μ§€λ¦„ 0.4β†’0.6, 길이 6β†’9
933
  const bulletMaterial = new THREE.MeshBasicMaterial({
934
  color: 0xff0000,
935
  emissive: 0xff0000,
@@ -1762,7 +1810,7 @@ class Game {
1762
  if (!enemy.mesh || !enemy.isLoaded) continue;
1763
 
1764
  const distance = bullet.position.distanceTo(enemy.position);
1765
- if (distance < 60) { // 35μ—μ„œ 60으둜 λŒ€ν­ 증가 (λͺ…쀑 νŒμ • ν™•λŒ€)
1766
  this.scene.remove(bullet);
1767
  this.fighter.bullets.splice(i, 1);
1768
 
@@ -1784,7 +1832,7 @@ class Game {
1784
  this.enemies.forEach(enemy => {
1785
  enemy.bullets.forEach((bullet, index) => {
1786
  const distance = bullet.position.distanceTo(this.fighter.position);
1787
- if (distance < 65) { // 40μ—μ„œ 65둜 λŒ€ν­ 증가 (λͺ…쀑 νŒμ • ν™•λŒ€)
1788
  this.scene.remove(bullet);
1789
  enemy.bullets.splice(index, 1);
1790
 
 
588
 
589
  this.ammo--;
590
 
591
+ // 직선 λͺ¨μ–‘μ˜ νƒ„ν™˜ (100% 더 크게)
592
+ const bulletGeometry = new THREE.CylinderGeometry(1.0, 1.0, 16, 8); // λ°˜μ§€λ¦„ 0.75β†’1.0, 길이 12β†’16
593
  const bulletMaterial = new THREE.MeshBasicMaterial({
594
  color: 0xffff00,
595
  emissive: 0xffff00,
 
691
  this.velocity = new THREE.Vector3(0, 0, 120);
692
  this.rotation = new THREE.Euler(0, 0, 0);
693
  this.health = GAME_CONSTANTS.MAX_HEALTH; // 체λ ₯ 1000
694
+ this.speed = 514; // 1000kt in m/s (1000 * 0.514444)
695
  this.bullets = [];
696
  this.lastShootTime = 0;
697
 
 
710
  // λ‹€λ₯Έ μ κΈ°λ“€κ³Όμ˜ 좩돌 νšŒν”Ό
711
  this.nearbyEnemies = [];
712
  this.separationRadius = 300; // μ΅œμ†Œ 거리 300m
713
+
714
+ // μ „νˆ¬ κ΄€λ ¨ λ³€μˆ˜
715
+ this.isEngaged = false; // μ „νˆ¬ 쀑 μƒνƒœ
716
+ this.burstCount = 0; // ν˜„μž¬ μ—°λ°œ 수
717
+ this.lastBurstTime = 0; // λ§ˆμ§€λ§‰ μ—°λ°œ μ‹œμž‘ μ‹œκ°„
718
+ this.predictedTargetPos = new THREE.Vector3(); // 예츑 사격 μœ„μΉ˜
719
  }
720
 
721
  generateRandomTarget() {
 
782
  const currentTime = Date.now();
783
  const distanceToPlayer = this.position.distanceTo(playerPosition);
784
 
785
+ // ν”Œλ ˆμ΄μ–΄ 감지 및 μ „νˆ¬ μƒνƒœ μ „ν™˜
 
786
  if (distanceToPlayer < 3000) {
787
+ this.isEngaged = true;
788
+ this.aiState = 'combat';
789
+
790
  // ν”Œλ ˆμ΄μ–΄κ°€ μ‹œμ•Όκ° 내에 μžˆλŠ”μ§€ 확인
791
  const toPlayer = playerPosition.clone().sub(this.position).normalize();
792
  const forward = new THREE.Vector3(0, 0, 1);
793
  forward.applyEuler(this.rotation);
794
  const angle = forward.dot(toPlayer);
795
 
796
+ // 예츑 사격을 μœ„ν•œ ν”Œλ ˆμ΄μ–΄ 속도 계산
797
+ if (this.playerFighter) {
798
+ const bulletSpeed = 1200; // νƒ„ν™˜ 속도
799
+ const timeToHit = distanceToPlayer / bulletSpeed;
800
+
801
+ // ν”Œλ ˆμ΄μ–΄μ˜ μ˜ˆμƒ μœ„μΉ˜ 계산
802
+ this.predictedTargetPos = playerPosition.clone().add(
803
+ this.playerFighter.velocity.clone().multiplyScalar(timeToHit)
804
+ );
805
+ }
806
+
807
+ // 사격 쑰건: μ‹œμ•Όκ° 내에 있고 거리가 2000m 이내
808
+ if (angle > 0.7 && distanceToPlayer < 2000) { // μ‹œμ•Όκ°μ„ μ’ν˜€μ„œ 정확도 ν–₯상
809
+ // μ—°λ°œ 사격 μ‹œμŠ€ν…œ
810
+ const timeSinceLastBurst = currentTime - this.lastBurstTime;
811
+
812
+ // 2μ΄ˆλ§ˆλ‹€ μƒˆλ‘œμš΄ μ—°λ°œ μ‹œμž‘
813
+ if (timeSinceLastBurst >= 2000) {
814
+ this.burstCount = 0;
815
+ this.lastBurstTime = currentTime;
816
+ }
817
+
818
+ // 10발 μ—°λ°œ (0.1초 간격)
819
+ if (this.burstCount < 10 && currentTime - this.lastShootTime >= 100) {
820
  this.shoot();
821
+ this.burstCount++;
822
  }
823
  }
824
+ } else {
825
+ this.isEngaged = false;
826
+ this.aiState = 'patrol';
827
  }
828
 
829
+ // μ „νˆ¬ 쀑일 λ•Œ ν”Œλ ˆμ΄μ–΄ 좔적
830
+ if (this.isEngaged && this.playerFighter) {
831
+ // ν”Œλ ˆμ΄μ–΄μ˜ 기동 νŒ¨ν„΄ λͺ¨λ°©
832
+ const playerVelocity = this.playerFighter.velocity.clone().normalize();
833
+ const playerRoll = this.playerFighter.rotation.z;
834
+ const playerPitch = this.playerFighter.rotation.x;
835
+
836
+ // 예츑된 μœ„μΉ˜λ‘œ ν–₯ν•˜λ„λ‘ μ„€μ •
837
+ this.targetPosition = this.predictedTargetPos.clone();
838
+
839
+ // ν”Œλ ˆμ΄μ–΄μ™€ λΉ„μŠ·ν•œ λ‘€ 적용 (μ•½κ°„μ˜ μ§€μ—°μœΌλ‘œ)
840
+ this.targetRotation.z = playerRoll * 0.7;
841
+
842
+ // 고도 차이에 λ”°λ₯Έ ν”ΌμΉ˜ 쑰절 (더 곡격적으둜)
843
+ const altitudeDiff = this.targetPosition.y - this.position.y;
844
+ this.targetRotation.x = Math.max(-0.5, Math.min(0.5, altitudeDiff * 0.0003));
845
+ } else {
846
+ // 순찰 λͺ¨λ“œ
847
+ if (this.position.distanceTo(this.targetPosition) < 500 ||
848
+ currentTime - this.lastDirectionChange > 15000) {
849
+ this.targetPosition = this.generateRandomTarget();
850
+ this.lastDirectionChange = currentTime;
851
+ this.isTurning = false;
852
+ }
853
  }
854
 
855
  // λͺ©ν‘œ λ°©ν–₯ 계산
 
861
  while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
862
  while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
863
 
864
+ // μ „νˆ¬ μ€‘μ—λŠ” 더 λΉ λ₯Έ μ„ νšŒ
865
+ const turnRateMultiplier = this.isEngaged ? 2.0 : 1.0;
866
+
867
  // 큰 각도 차이가 있으면 μ›ν˜• μ„ νšŒ
868
+ if (Math.abs(angleDiff) > Math.PI / 6) {
869
  this.isTurning = true;
870
  this.turnDirection = angleDiff > 0 ? 1 : -1;
871
  }
872
 
873
  // μ„ νšŒ 쀑일 λ•Œ
874
  if (this.isTurning) {
875
+ // μ›ν˜• μ„ νšŒ κ΅¬ν˜„ (μ „νˆ¬ μ€‘μ—λŠ” 더 λΉ λ₯΄κ²Œ)
876
+ const turnRate = (this.speed / this.turnRadius) * this.turnDirection * turnRateMultiplier;
877
  this.targetRotation.y += turnRate * deltaTime;
878
+ this.targetRotation.z = this.turnDirection * 0.5 * (this.isEngaged ? 1.5 : 1); // μ „νˆ¬ 쀑 더 큰 λ‘€
879
 
880
  // λͺ©ν‘œ 각도에 κ·Όμ ‘ν•˜λ©΄ μ„ νšŒ μ’…λ£Œ
881
  const newAngleDiff = targetAngle - this.targetRotation.y;
882
+ if (Math.abs(newAngleDiff) < Math.PI / 12) {
883
  this.isTurning = false;
884
  }
885
  } else {
886
+ // 직진 λΉ„ν–‰ (μ „νˆ¬ μ€‘μ—λŠ” 더 λΉ λ₯Έ λ°˜μ‘)
887
+ const lerpSpeed = this.isEngaged ? 1.0 : 0.5;
888
+ this.targetRotation.y = THREE.MathUtils.lerp(this.targetRotation.y, targetAngle, deltaTime * lerpSpeed);
889
  this.targetRotation.z = THREE.MathUtils.lerp(this.targetRotation.z, 0, deltaTime * 2);
890
  }
891
 
 
 
 
 
 
 
 
 
892
  // λ‹€λ₯Έ μ κΈ°μ™€μ˜ 좩돌 νšŒν”Ό
893
  this.avoidOtherEnemies(deltaTime);
894
 
895
+ // λΆ€λ“œλŸ¬μš΄ νšŒμ „ 적용 (μ „νˆ¬ μ€‘μ—λŠ” 더 λΉ λ₯΄κ²Œ)
896
+ const rotationSpeed = this.isEngaged ? 3.0 : 2.0;
897
+ this.rotation.x = THREE.MathUtils.lerp(this.rotation.x, this.targetRotation.x, deltaTime * rotationSpeed);
898
+ this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetRotation.y, deltaTime * rotationSpeed);
899
+ this.rotation.z = THREE.MathUtils.lerp(this.rotation.z, this.targetRotation.z, deltaTime * rotationSpeed * 1.25);
900
 
901
  // 속도 벑터 계산
902
  const forward = new THREE.Vector3(0, 0, 1);
 
976
  shoot() {
977
  this.lastShootTime = Date.now();
978
 
979
+ // 직선 λͺ¨μ–‘μ˜ νƒ„ν™˜ (100% 더 크게)
980
+ const bulletGeometry = new THREE.CylinderGeometry(0.8, 0.8, 12, 8); // λ°˜μ§€λ¦„ 0.6β†’0.8, 길이 9β†’12
981
  const bulletMaterial = new THREE.MeshBasicMaterial({
982
  color: 0xff0000,
983
  emissive: 0xff0000,
 
1810
  if (!enemy.mesh || !enemy.isLoaded) continue;
1811
 
1812
  const distance = bullet.position.distanceTo(enemy.position);
1813
+ if (distance < 90) { // 60μ—μ„œ 90으둜 증가 (100% ν™•λŒ€)
1814
  this.scene.remove(bullet);
1815
  this.fighter.bullets.splice(i, 1);
1816
 
 
1832
  this.enemies.forEach(enemy => {
1833
  enemy.bullets.forEach((bullet, index) => {
1834
  const distance = bullet.position.distanceTo(this.fighter.position);
1835
+ if (distance < 100) { // 65μ—μ„œ 100으둜 증가 (100% ν™•λŒ€)
1836
  this.scene.remove(bullet);
1837
  enemy.bullets.splice(index, 1);
1838