cutechicken commited on
Commit
26bd7d5
โ€ข
1 Parent(s): 521a889

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +162 -143
game.js CHANGED
@@ -572,31 +572,67 @@ class Enemy {
572
  constructor(scene, position, type = 'tank') {
573
  this.scene = scene;
574
  this.position = position;
575
- this.mesh = null;
 
 
576
  this.type = type;
577
  this.health = type === 'tank' ? 100 : 200;
578
  this.lastAttackTime = 0;
579
  this.bullets = [];
580
  this.isLoaded = false;
581
  this.moveSpeed = type === 'tank' ? ENEMY_MOVE_SPEED : ENEMY_MOVE_SPEED * 0.7;
 
 
 
 
582
  }
583
 
584
  async initialize(loader) {
585
  try {
586
- const modelPath = this.type === 'tank' ? '/models/enemy1.glb' : '/models/enemy4.glb';
587
- const result = await loader.loadAsync(modelPath);
588
- this.mesh = result.scene;
589
- this.mesh.position.copy(this.position);
590
- this.mesh.scale.set(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE);
 
 
 
 
 
 
 
 
 
 
 
591
 
592
- this.mesh.traverse((child) => {
 
593
  if (child.isMesh) {
594
  child.castShadow = true;
595
  child.receiveShadow = true;
596
  }
597
  });
598
 
599
- this.scene.add(this.mesh);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  this.isLoaded = true;
601
  } catch (error) {
602
  console.error('Error loading enemy model:', error);
@@ -605,38 +641,76 @@ class Enemy {
605
  }
606
 
607
  update(playerPosition) {
608
- if (!this.mesh || !this.isLoaded) return;
609
 
610
- const direction = new THREE.Vector3()
611
- .subVectors(playerPosition, this.mesh.position)
612
- .normalize();
613
-
614
- const distanceToPlayer = this.mesh.position.distanceTo(playerPosition);
615
- const minDistance = 50;
616
-
617
- // ์ด์ „ ์œ„์น˜ ์ €์žฅ
618
- const previousPosition = this.mesh.position.clone();
619
-
620
- if (distanceToPlayer > minDistance) {
621
- const moveVector = direction.multiplyScalar(this.moveSpeed);
622
- const newPosition = this.mesh.position.clone().add(moveVector);
623
-
624
- // ์ง€ํ˜• ๋†’์ด ๊ฐ€์ ธ์˜ค๊ธฐ
625
- const heightAtNewPos = window.gameInstance.getHeightAtPosition(
626
- newPosition.x,
627
- newPosition.z
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
  );
629
- newPosition.y = heightAtNewPos + TANK_HEIGHT;
630
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
631
  // ์ž„์‹œ๋กœ ์œ„์น˜ ์ด๋™ํ•˜์—ฌ ์ถฉ๋Œ ์ฒดํฌ
632
- const originalPosition = this.mesh.position.clone();
633
- this.mesh.position.copy(newPosition);
634
 
635
- // ์žฅ์• ๋ฌผ๊ณผ ์ถฉ๋Œ ์ฒดํฌ
636
- const enemyBox = new THREE.Box3().setFromObject(this.mesh);
637
  let hasCollision = false;
638
 
639
- // ๋ชจ๋“  ์žฅ์• ๋ฌผ์— ๋Œ€ํ•ด ์ถฉ๋Œ ๊ฒ€์‚ฌ
640
  for (const obstacle of window.gameInstance.obstacles) {
641
  const obstacleBox = new THREE.Box3().setFromObject(obstacle);
642
  if (enemyBox.intersectsBox(obstacleBox)) {
@@ -645,127 +719,34 @@ class Enemy {
645
  }
646
  }
647
 
648
- // ๋‹ค๋ฅธ ์  ํƒฑํฌ์™€์˜ ์ถฉ๋Œ ๊ฒ€์‚ฌ
649
- if (!hasCollision) {
650
- for (const otherEnemy of window.gameInstance.enemies) {
651
- if (otherEnemy !== this && otherEnemy.mesh) {
652
- const otherEnemyBox = new THREE.Box3().setFromObject(otherEnemy.mesh);
653
- if (enemyBox.intersectsBox(otherEnemyBox)) {
654
- hasCollision = true;
655
- break;
656
- }
657
  }
658
  }
659
  }
660
 
661
- // ๋งต ๊ฒฝ๊ณ„ ์ฒดํฌ
662
  const mapBoundary = MAP_SIZE / 2;
663
  if (Math.abs(newPosition.x) > mapBoundary ||
664
  Math.abs(newPosition.z) > mapBoundary) {
665
  hasCollision = true;
666
  }
667
 
668
- // ์ถฉ๋Œ์ด ์žˆ์œผ๋ฉด ์ด์ „ ์œ„์น˜๋กœ ๋ณต๊ท€, ์—†์œผ๋ฉด ์ƒˆ ์œ„์น˜ ์œ ์ง€
669
  if (hasCollision) {
670
- this.mesh.position.copy(previousPosition);
671
-
672
- // ์ถฉ๋Œ ์‹œ ์šฐํšŒ ๊ฒฝ๋กœ ์‹œ๋„
673
- const alternateDirections = [
674
- new THREE.Vector3(-direction.z, 0, direction.x), // ์™ผ์ชฝ์œผ๋กœ 90๋„
675
- new THREE.Vector3(direction.z, 0, -direction.x), // ์˜ค๋ฅธ์ชฝ์œผ๋กœ 90๋„
676
- new THREE.Vector3(-direction.x, 0, -direction.z) // 180๋„ ํšŒ์ „
677
- ];
678
-
679
- for (const altDirection of alternateDirections) {
680
- const altMoveVector = altDirection.multiplyScalar(this.moveSpeed);
681
- const altNewPosition = previousPosition.clone().add(altMoveVector);
682
-
683
- this.mesh.position.copy(altNewPosition);
684
- const altEnemyBox = new THREE.Box3().setFromObject(this.mesh);
685
-
686
- let altHasCollision = false;
687
-
688
- // ์ƒˆ๋กœ์šด ๋ฐฉํ–ฅ์— ๋Œ€ํ•œ ์ถฉ๋Œ ๊ฒ€์‚ฌ
689
- for (const obstacle of window.gameInstance.obstacles) {
690
- const obstacleBox = new THREE.Box3().setFromObject(obstacle);
691
- if (altEnemyBox.intersectsBox(obstacleBox)) {
692
- altHasCollision = true;
693
- break;
694
- }
695
- }
696
-
697
- if (!altHasCollision) {
698
- // ์šฐํšŒ ๊ฒฝ๋กœ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฉด ๊ทธ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™
699
- break;
700
- } else {
701
- // ์šฐํšŒ๋„ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉด ์ด์ „ ์œ„์น˜๋กœ ๋ณต๊ท€
702
- this.mesh.position.copy(previousPosition);
703
- }
704
- }
705
- }
706
-
707
- // ์ง€ํ˜•์— ๋”ฐ๋ฅธ ๊ธฐ์šธ๊ธฐ ์กฐ์ •
708
- const forwardVector = new THREE.Vector3(0, 0, 1).applyQuaternion(this.mesh.quaternion);
709
- const rightVector = new THREE.Vector3(1, 0, 0).applyQuaternion(this.mesh.quaternion);
710
-
711
- const frontHeight = window.gameInstance.getHeightAtPosition(
712
- this.mesh.position.x + forwardVector.x,
713
- this.mesh.position.z + forwardVector.z
714
- );
715
- const backHeight = window.gameInstance.getHeightAtPosition(
716
- this.mesh.position.x - forwardVector.x,
717
- this.mesh.position.z - forwardVector.z
718
- );
719
- const rightHeight = window.gameInstance.getHeightAtPosition(
720
- this.mesh.position.x + rightVector.x,
721
- this.mesh.position.z + rightVector.z
722
- );
723
- const leftHeight = window.gameInstance.getHeightAtPosition(
724
- this.mesh.position.x - rightVector.x,
725
- this.mesh.position.z - rightVector.z
726
- );
727
-
728
- const pitch = Math.atan2(frontHeight - backHeight, 2);
729
- const roll = Math.atan2(rightHeight - leftHeight, 2);
730
-
731
- // ํ˜„์žฌ ํšŒ์ „ ์œ ์ง€ํ•˜๋ฉด์„œ ๊ธฐ์šธ๊ธฐ๋งŒ ์ ์šฉ
732
- const currentRotation = this.mesh.rotation.y;
733
- this.mesh.rotation.set(pitch, currentRotation, roll);
734
- }
735
-
736
- // ํ”Œ๋ ˆ์ด์–ด๋ฅผ ํ–ฅํ•ด ํฌํƒ‘ ํšŒ์ „
737
- this.mesh.lookAt(playerPosition);
738
-
739
- // ์ด์•Œ ์—…๋ฐ์ดํŠธ
740
- if (this.bullets) {
741
- for (let i = this.bullets.length - 1; i >= 0; i--) {
742
- const bullet = this.bullets[i];
743
- bullet.position.add(bullet.velocity);
744
-
745
- // ์ด์•Œ์ด ๋งต ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๊ฑฐ๋‚˜ ์žฅ์• ๋ฌผ๊ณผ ์ถฉ๋Œํ•˜๋ฉด ์ œ๊ฑฐ
746
- if (Math.abs(bullet.position.x) > MAP_SIZE / 2 ||
747
- Math.abs(bullet.position.z) > MAP_SIZE / 2) {
748
- this.scene.remove(bullet);
749
- this.bullets.splice(i, 1);
750
- continue;
751
- }
752
-
753
- // ์ด์•Œ๊ณผ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ
754
- const bulletBox = new THREE.Box3().setFromObject(bullet);
755
- for (const obstacle of window.gameInstance.obstacles) {
756
- const obstacleBox = new THREE.Box3().setFromObject(obstacle);
757
- if (bulletBox.intersectsBox(obstacleBox)) {
758
- this.scene.remove(bullet);
759
- this.bullets.splice(i, 1);
760
- break;
761
- }
762
- }
763
  }
764
  }
765
- }
766
-
767
 
768
  shoot(playerPosition) {
 
 
 
769
  const currentTime = Date.now();
770
  const attackInterval = this.type === 'tank' ?
771
  ENEMY_CONFIG.ATTACK_INTERVAL :
@@ -773,16 +754,28 @@ class Enemy {
773
 
774
  if (currentTime - this.lastAttackTime < attackInterval) return;
775
 
 
776
  const bulletGeometry = new THREE.SphereGeometry(this.type === 'tank' ? 0.2 : 0.3);
777
  const bulletMaterial = new THREE.MeshBasicMaterial({
778
  color: this.type === 'tank' ? 0xff0000 : 0xff6600
779
  });
780
  const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
781
 
782
- bullet.position.copy(this.mesh.position);
 
 
 
 
 
 
 
 
 
 
 
783
 
784
  const direction = new THREE.Vector3()
785
- .subVectors(playerPosition, this.mesh.position)
786
  .normalize();
787
 
788
  const bulletSpeed = this.type === 'tank' ?
@@ -796,14 +789,40 @@ class Enemy {
796
  this.lastAttackTime = currentTime;
797
  }
798
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
  takeDamage(damage) {
800
  this.health -= damage;
801
  return this.health <= 0;
802
  }
803
 
804
  destroy() {
805
- if (this.mesh) {
806
- this.scene.remove(this.mesh);
807
  this.bullets.forEach(bullet => this.scene.remove(bullet));
808
  this.bullets = [];
809
  this.isLoaded = false;
 
572
  constructor(scene, position, type = 'tank') {
573
  this.scene = scene;
574
  this.position = position;
575
+ this.body = null;
576
+ this.turret = null;
577
+ this.turretGroup = new THREE.Group();
578
  this.type = type;
579
  this.health = type === 'tank' ? 100 : 200;
580
  this.lastAttackTime = 0;
581
  this.bullets = [];
582
  this.isLoaded = false;
583
  this.moveSpeed = type === 'tank' ? ENEMY_MOVE_SPEED : ENEMY_MOVE_SPEED * 0.7;
584
+ this.turnSpeed = 0.03;
585
+ this.targetRotation = 0;
586
+ this.turretRotation = 0;
587
+ this.canShoot = false; // ํฌํƒ‘์ด ์ •๋ ฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ”Œ๋ž˜๊ทธ
588
  }
589
 
590
  async initialize(loader) {
591
  try {
592
+ // ๋ชธ์ฒด ๋กœ๋“œ
593
+ const bodyResult = await loader.loadAsync('/models/t90Body.glb');
594
+ this.body = bodyResult.scene;
595
+
596
+ // ํฌํƒ‘ ๋กœ๋“œ
597
+ const turretResult = await loader.loadAsync('/models/t90Turret.glb');
598
+ this.turret = turretResult.scene;
599
+
600
+ // ํฌํƒ‘ ๊ทธ๋ฃน ์„ค์ •
601
+ this.turretGroup.position.y = 0.2; // ํฌํƒ‘ ๋†’์ด ์กฐ์ •
602
+ this.turretGroup.add(this.turret);
603
+ this.body.add(this.turretGroup);
604
+
605
+ // ์œ„์น˜์™€ ์Šค์ผ€์ผ ์„ค์ •
606
+ this.body.position.copy(this.position);
607
+ this.body.scale.set(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE);
608
 
609
+ // ๊ทธ๋ฆผ์ž ์„ค์ •
610
+ this.body.traverse((child) => {
611
  if (child.isMesh) {
612
  child.castShadow = true;
613
  child.receiveShadow = true;
614
  }
615
  });
616
 
617
+ this.turret.traverse((child) => {
618
+ if (child.isMesh) {
619
+ child.castShadow = true;
620
+ child.receiveShadow = true;
621
+ }
622
+ });
623
+
624
+ // ๊ทธ๋ฆผ์ž ํ‰๋ฉด ์ถ”๊ฐ€
625
+ const shadowPlaneGeometry = new THREE.PlaneGeometry(8, 8);
626
+ const shadowPlaneMaterial = new THREE.ShadowMaterial({
627
+ opacity: 0.3
628
+ });
629
+ this.shadowPlane = new THREE.Mesh(shadowPlaneGeometry, shadowPlaneMaterial);
630
+ this.shadowPlane.receiveShadow = true;
631
+ this.shadowPlane.rotation.x = -Math.PI / 2;
632
+ this.shadowPlane.position.y = 0.1;
633
+ this.body.add(this.shadowPlane);
634
+
635
+ this.scene.add(this.body);
636
  this.isLoaded = true;
637
  } catch (error) {
638
  console.error('Error loading enemy model:', error);
 
641
  }
642
 
643
  update(playerPosition) {
644
+ if (!this.body || !this.isLoaded) return;
645
 
646
+ const direction = new THREE.Vector3()
647
+ .subVectors(playerPosition, this.body.position)
648
+ .normalize();
649
+
650
+ const distanceToPlayer = this.body.position.distanceTo(playerPosition);
651
+ const minDistance = 50;
652
+
653
+ // ์ด์ „ ์œ„์น˜ ์ €์žฅ
654
+ const previousPosition = this.body.position.clone();
655
+
656
+ if (distanceToPlayer > minDistance) {
657
+ // ๋ชฉํ‘œ ํšŒ์ „ ๊ฐ๋„ ๊ณ„์‚ฐ
658
+ this.targetRotation = Math.atan2(direction.x, direction.z);
659
+
660
+ // ๋ถ€๋“œ๋Ÿฌ์šด ํšŒ์ „
661
+ let rotationDiff = this.targetRotation - this.body.rotation.y;
662
+ while (rotationDiff > Math.PI) rotationDiff -= Math.PI * 2;
663
+ while (rotationDiff < -Math.PI) rotationDiff += Math.PI * 2;
664
+
665
+ this.body.rotation.y += Math.sign(rotationDiff) * Math.min(Math.abs(rotationDiff), this.turnSpeed);
666
+
667
+ // ์ „์ง„ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™
668
+ const moveVector = new THREE.Vector3(0, 0, this.moveSpeed);
669
+ moveVector.applyEuler(this.body.rotation);
670
+ const newPosition = this.body.position.clone().add(moveVector);
671
+
672
+ // ์ง€ํ˜• ๋†’์ด ๊ฐ€์ ธ์˜ค๊ธฐ
673
+ const heightAtNewPos = window.gameInstance.getHeightAtPosition(
674
+ newPosition.x,
675
+ newPosition.z
676
+ );
677
+ newPosition.y = heightAtNewPos + TANK_HEIGHT;
678
+
679
+ // ์ถฉ๋Œ ๊ฒ€์‚ฌ ๋ฐ ์ด๋™ ์ฒ˜๋ฆฌ
680
+ this.handleCollisions(newPosition, previousPosition);
681
+ }
682
+
683
+ // ํฌํƒ‘ ํšŒ์ „ - ํ”Œ๋ ˆ์ด์–ด๋ฅผ ํ–ฅํ•ด
684
+ const turretTargetRotation = Math.atan2(
685
+ playerPosition.x - this.body.position.x,
686
+ playerPosition.z - this.body.position.z
687
  );
 
688
 
689
+ // ์›”๋“œ ์ขŒํ‘œ์—์„œ์˜ ํฌํƒ‘ ํšŒ์ „์„ ๋กœ์ปฌ ํšŒ์ „์œผ๋กœ ๋ณ€ํ™˜
690
+ const localTurretRotation = turretTargetRotation - this.body.rotation.y;
691
+
692
+ // ํฌํƒ‘ ํšŒ์ „ ๋ณด๊ฐ„
693
+ let turretRotationDiff = localTurretRotation - this.turretGroup.rotation.y;
694
+ while (turretRotationDiff > Math.PI) turretRotationDiff -= Math.PI * 2;
695
+ while (turretRotationDiff < -Math.PI) turretRotationDiff += Math.PI * 2;
696
+
697
+ this.turretGroup.rotation.y += Math.sign(turretRotationDiff) * Math.min(Math.abs(turretRotationDiff), this.turnSpeed);
698
+
699
+ // ํฌํƒ‘์ด ํ”Œ๋ ˆ์ด์–ด๋ฅผ ํ–ฅํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธ
700
+ this.canShoot = Math.abs(turretRotationDiff) < 0.1;
701
+
702
+ // ์ด์•Œ ์—…๋ฐ์ดํŠธ ๋กœ์ง
703
+ this.updateBullets();
704
+ }
705
+
706
+ handleCollisions(newPosition, previousPosition) {
707
  // ์ž„์‹œ๋กœ ์œ„์น˜ ์ด๋™ํ•˜์—ฌ ์ถฉ๋Œ ์ฒดํฌ
708
+ this.body.position.copy(newPosition);
 
709
 
710
+ const enemyBox = new THREE.Box3().setFromObject(this.body);
 
711
  let hasCollision = false;
712
 
713
+ // ์žฅ์• ๋ฌผ ์ถฉ๋Œ ๊ฒ€์‚ฌ
714
  for (const obstacle of window.gameInstance.obstacles) {
715
  const obstacleBox = new THREE.Box3().setFromObject(obstacle);
716
  if (enemyBox.intersectsBox(obstacleBox)) {
 
719
  }
720
  }
721
 
722
+ // ๋‹ค๋ฅธ ์ ๊ณผ์˜ ์ถฉ๋Œ ๊ฒ€์‚ฌ
723
+ for (const otherEnemy of window.gameInstance.enemies) {
724
+ if (otherEnemy !== this && otherEnemy.body) {
725
+ const otherEnemyBox = new THREE.Box3().setFromObject(otherEnemy.body);
726
+ if (enemyBox.intersectsBox(otherEnemyBox)) {
727
+ hasCollision = true;
728
+ break;
 
 
729
  }
730
  }
731
  }
732
 
733
+ // ๋งต ๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ
734
  const mapBoundary = MAP_SIZE / 2;
735
  if (Math.abs(newPosition.x) > mapBoundary ||
736
  Math.abs(newPosition.z) > mapBoundary) {
737
  hasCollision = true;
738
  }
739
 
740
+ // ์ถฉ๋Œ์ด ์žˆ์œผ๋ฉด ์ด์ „ ์œ„์น˜๋กœ ๋ณต๊ท€
741
  if (hasCollision) {
742
+ this.body.position.copy(previousPosition);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
743
  }
744
  }
 
 
745
 
746
  shoot(playerPosition) {
747
+ // ํฌํƒ‘์ด ์ •๋ ฌ๋˜์ง€ ์•Š์•˜์œผ๋ฉด ๋ฐœ์‚ฌํ•˜์ง€ ์•Š์Œ
748
+ if (!this.canShoot) return;
749
+
750
  const currentTime = Date.now();
751
  const attackInterval = this.type === 'tank' ?
752
  ENEMY_CONFIG.ATTACK_INTERVAL :
 
754
 
755
  if (currentTime - this.lastAttackTime < attackInterval) return;
756
 
757
+ // ํฌํƒ„ ์ƒ์„ฑ
758
  const bulletGeometry = new THREE.SphereGeometry(this.type === 'tank' ? 0.2 : 0.3);
759
  const bulletMaterial = new THREE.MeshBasicMaterial({
760
  color: this.type === 'tank' ? 0xff0000 : 0xff6600
761
  });
762
  const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
763
 
764
+ // ํฌํƒ‘ ๋์—์„œ ํฌํƒ„์ด ๋ฐœ์‚ฌ๋˜๋„๋ก ์œ„์น˜ ์กฐ์ •
765
+ const muzzleOffset = new THREE.Vector3(0, 0.5, 4);
766
+ const muzzlePosition = new THREE.Vector3();
767
+ const turretWorldQuaternion = new THREE.Quaternion();
768
+
769
+ this.turret.getWorldPosition(muzzlePosition);
770
+ this.turret.getWorldQuaternion(turretWorldQuaternion);
771
+
772
+ muzzleOffset.applyQuaternion(turretWorldQuaternion);
773
+ muzzlePosition.add(muzzleOffset);
774
+
775
+ bullet.position.copy(muzzlePosition);
776
 
777
  const direction = new THREE.Vector3()
778
+ .subVectors(playerPosition, muzzlePosition)
779
  .normalize();
780
 
781
  const bulletSpeed = this.type === 'tank' ?
 
789
  this.lastAttackTime = currentTime;
790
  }
791
 
792
+ updateBullets() {
793
+ for (let i = this.bullets.length - 1; i >= 0; i--) {
794
+ const bullet = this.bullets[i];
795
+ bullet.position.add(bullet.velocity);
796
+
797
+ // ๋งต ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๊ฑฐ๋‚˜ ์žฅ์• ๋ฌผ๊ณผ ์ถฉ๋Œํ•˜๋ฉด ์ œ๊ฑฐ
798
+ if (Math.abs(bullet.position.x) > MAP_SIZE / 2 ||
799
+ Math.abs(bullet.position.z) > MAP_SIZE / 2) {
800
+ this.scene.remove(bullet);
801
+ this.bullets.splice(i, 1);
802
+ continue;
803
+ }
804
+
805
+ // ์žฅ์• ๋ฌผ๊ณผ ์ถฉ๋Œ ์ฒดํฌ
806
+ const bulletBox = new THREE.Box3().setFromObject(bullet);
807
+ for (const obstacle of window.gameInstance.obstacles) {
808
+ const obstacleBox = new THREE.Box3().setFromObject(obstacle);
809
+ if (bulletBox.intersectsBox(obstacleBox)) {
810
+ this.scene.remove(bullet);
811
+ this.bullets.splice(i, 1);
812
+ break;
813
+ }
814
+ }
815
+ }
816
+ }
817
+
818
  takeDamage(damage) {
819
  this.health -= damage;
820
  return this.health <= 0;
821
  }
822
 
823
  destroy() {
824
+ if (this.body) {
825
+ this.scene.remove(this.body);
826
  this.bullets.forEach(bullet => this.scene.remove(bullet));
827
  this.bullets = [];
828
  this.isLoaded = false;