cutechicken commited on
Commit
96cd899
ยท
verified ยท
1 Parent(s): 71a155b

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +184 -159
game.js CHANGED
@@ -43,6 +43,21 @@ class TankPlayer {
43
  this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
44
  this.renderer = new THREE.WebGLRenderer({ antialias: true });
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  // ๋ณ„๋„์˜ ๋ฉ”์„œ๋“œ๋กœ ๋ถ„๋ฆฌ
47
  createExplosionEffect(scene, position) {
48
  // ํญ๋ฐœ ์ค‘์‹ฌ ํ”Œ๋ž˜์‹œ
@@ -170,7 +185,7 @@ class TankPlayer {
170
  this.turretGroup.add(this.turret);
171
  this.body.add(this.turretGroup);
172
 
173
- // ๊ทธ๋ฆผ์ž ์„ค์ •์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€
174
  this.body.traverse((child) => {
175
  if (child.isMesh) {
176
  child.castShadow = true;
@@ -200,57 +215,15 @@ class TankPlayer {
200
  this.shadowPlane.position.y = 0.1;
201
  this.body.add(this.shadowPlane);
202
 
203
- // ๊ฐ„๋‹จํ•œ ์Šคํฐ ์œ„์น˜ ์„ค์ •
204
  const spawnPosition = new THREE.Vector3(
205
- (Math.random() - 0.5) * (MAP_SIZE * 0.8), // MAP_SIZE์˜ 80%๋งŒ ์‚ฌ์šฉ
206
- TANK_HEIGHT, // ๊ณ ์ •๋œ ๋†’์ด ์‚ฌ์šฉ
207
  (Math.random() - 0.5) * (MAP_SIZE * 0.8)
208
  );
209
 
210
  this.body.position.copy(spawnPosition);
211
-
212
- // ํญ๋ฐœ ์ดํŽ™ํŠธ ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€
213
- this.createExplosionEffect = (scene, position) => {
214
- // ํญ๋ฐœ ํŒŒํ‹ฐํด
215
- for (let i = 0; i < 15; i++) {
216
- const size = Math.random() * 0.2 + 0.1;
217
- const geometry = new THREE.SphereGeometry(size);
218
- const material = new THREE.MeshBasicMaterial({
219
- color: Math.random() < 0.5 ? 0xff4500 : 0xff8c00
220
- });
221
- const particle = new THREE.Mesh(geometry, material);
222
- particle.position.copy(position);
223
-
224
- const speed = Math.random() * 0.3 + 0.2;
225
- const angle = Math.random() * Math.PI * 2;
226
- const elevation = Math.random() * Math.PI - Math.PI / 2;
227
-
228
- particle.velocity = new THREE.Vector3(
229
- Math.cos(angle) * Math.cos(elevation) * speed,
230
- Math.sin(elevation) * speed,
231
- Math.sin(angle) * Math.cos(elevation) * speed
232
- );
233
-
234
- particle.gravity = -0.01;
235
- particle.life = Math.random() * 20 + 20;
236
- particle.fadeRate = 1 / particle.life;
237
-
238
- scene.add(particle);
239
- window.gameInstance.particles.push({
240
- mesh: particle,
241
- velocity: particle.velocity,
242
- gravity: particle.gravity,
243
- life: particle.life,
244
- fadeRate: particle.fadeRate
245
- });
246
- }
247
-
248
- // ์ถฉ๋Œ ์‚ฌ์šด๋“œ ์žฌ์ƒ
249
- const explosionSound = new Audio('sounds/explosion.ogg');
250
- explosionSound.volume = 0.3;
251
- explosionSound.play();
252
- };
253
-
254
  scene.add(this.body);
255
  this.isLoaded = true;
256
  this.updateAmmoDisplay();
@@ -580,6 +553,25 @@ class Enemy {
580
  this.isLoaded = false;
581
  this.moveSpeed = type === 'tank' ? ENEMY_MOVE_SPEED : ENEMY_MOVE_SPEED * 0.7;
582
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  createMuzzleFlash() {
584
  if (!this.mesh) return;
585
 
@@ -637,29 +629,29 @@ class Enemy {
637
  }, 500);
638
  }
639
 
640
-
641
  async initialize(loader) {
642
- try {
643
- const modelPath = this.type === 'tank' ? '/models/t90.glb' : '/models/t90.glb';
644
- const result = await loader.loadAsync(modelPath);
645
- this.mesh = result.scene;
646
- this.mesh.position.copy(this.position);
647
- this.mesh.scale.set(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE);
648
-
649
- this.mesh.traverse((child) => {
650
- if (child.isMesh) {
651
- child.castShadow = true;
652
- child.receiveShadow = true;
653
- }
654
- });
655
-
656
- this.scene.add(this.mesh);
657
- this.isLoaded = true;
658
- } catch (error) {
659
- console.error('Error loading enemy model:', error);
660
- this.isLoaded = false;
661
- }
662
  }
 
663
 
664
  update(playerPosition) {
665
  if (!this.mesh || !this.isLoaded) return;
@@ -1718,37 +1710,71 @@ class Game {
1718
  checkCollisions() {
1719
  if (this.isLoading || !this.tank.isLoaded) return;
1720
 
1721
- // ๋ช…์ค‘ ์‚ฌ์šด๋“œ ๋ฐฐ์—ด ์ •์˜
1722
  const hitSounds = [
1723
  'sounds/hit1.ogg', 'sounds/hit2.ogg', 'sounds/hit3.ogg',
1724
  'sounds/hit4.ogg', 'sounds/hit5.ogg', 'sounds/hit6.ogg', 'sounds/hit7.ogg'
1725
  ];
1726
 
1727
- // ํ”ผ๊ฒฉ ์‚ฌ์šด๋“œ ๋ฐฐ์—ด ์ •์˜
1728
  const beatSounds = ['sounds/beat1.ogg', 'sounds/beat2.ogg', 'sounds/beat3.ogg'];
1729
 
1730
  const tankPosition = this.tank.getPosition();
1731
- const tankBoundingBox = new THREE.Box3().setFromObject(this.tank.body);
1732
-
1733
- // ํƒฑํฌ์™€ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ (๊ฐœ์„ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1734
  this.obstacles.forEach(obstacle => {
1735
- if (obstacle.userData.isCollidable) { // ์ถฉ๋Œ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋งŒ ๊ฒ€์‚ฌ
1736
- const obstacleBoundingBox = new THREE.Box3().setFromObject(obstacle);
1737
- if (tankBoundingBox.intersectsBox(obstacleBoundingBox)) {
1738
- this.tank.body.position.copy(this.previousTankPosition);
 
1739
  }
1740
- }
1741
- });
1742
- // ์  ํƒฑํฌ์™€ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ (์ถ”๊ฐ€)
1743
  this.enemies.forEach(enemy => {
1744
  if (!enemy.mesh || !enemy.isLoaded) return;
1745
 
1746
- const enemyBoundingBox = new THREE.Box3().setFromObject(enemy.mesh);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1747
  const enemyPreviousPosition = enemy.mesh.position.clone();
1748
 
1749
  this.obstacles.forEach(obstacle => {
1750
- const obstacleBoundingBox = new THREE.Box3().setFromObject(obstacle);
1751
- if (enemyBoundingBox.intersectsBox(obstacleBoundingBox)) {
1752
  enemy.mesh.position.copy(enemyPreviousPosition);
1753
  }
1754
  });
@@ -1759,9 +1785,8 @@ class Game {
1759
  if (!enemy.mesh || !enemy.isLoaded) return;
1760
 
1761
  enemy.bullets.forEach((bullet, bulletIndex) => {
1762
- const distance = bullet.position.distanceTo(tankPosition);
1763
- if (distance < 1) {
1764
- // ํ”Œ๋ ˆ์ด์–ด ํ”ผ๊ฒฉ ์‚ฌ์šด๋“œ ์žฌ์ƒ
1765
  const randomBeatSound = beatSounds[Math.floor(Math.random() * beatSounds.length)];
1766
  const beatAudio = new Audio(randomBeatSound);
1767
  beatAudio.play();
@@ -1770,102 +1795,102 @@ class Game {
1770
  this.endGame();
1771
  }
1772
  this.scene.remove(bullet);
1773
- enemy.bullets.splice(bulletIndex, 1); // filter ๋Œ€์‹  splice ์‚ฌ์šฉ
1774
 
1775
- this.createExplosion(bullet.position);
1776
  document.getElementById('health').style.width =
1777
  `${(this.tank.health / MAX_HEALTH) * 100}%`;
1778
  }
1779
  });
1780
  });
1781
 
1782
- // ํ”Œ๋ ˆ์ด์–ด ํฌํƒ„
1783
- // ํฌํƒ„๊ณผ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ
1784
- for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
1785
- const bullet = this.tank.bullets[i];
1786
- const bulletBox = new THREE.Box3().setFromObject(bullet);
1787
 
1788
- for (const obstacle of this.obstacles) {
1789
- if (obstacle.userData.isCollidable) { // ์ถฉ๋Œ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋งŒ ๊ฒ€์‚ฌ
1790
- const obstacleBox = new THREE.Box3().setFromObject(obstacle);
1791
- if (bulletBox.intersectsBox(obstacleBox)) {
1792
- // ํญ๋ฐœ ์ดํŽ™ํŠธ ์ƒ์„ฑ
1793
- this.tank.createExplosionEffect(this.scene, bullet.position);
1794
-
1795
- // ํฌํƒ„ ์ œ๊ฑฐ
1796
- this.scene.remove(bullet);
1797
- this.tank.bullets.splice(i, 1);
1798
- break;
1799
  }
1800
  }
1801
  }
1802
- }
1803
 
1804
- // ์  ํƒฑํฌ์™€ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ
1805
- this.enemies.forEach(enemy => {
1806
- if (!enemy.mesh || !enemy.isLoaded) return;
1807
-
1808
- enemy.bullets.forEach((bullet, bulletIndex) => {
1809
- const distance = bullet.position.distanceTo(tankPosition);
1810
- if (distance < 1) {
1811
- // ํ”ผ๊ฒฉ ์‚ฌ์šด๋“œ ์žฌ์ƒ
1812
- const randomBeatSound = beatSounds[Math.floor(Math.random() * beatSounds.length)];
1813
- const beatAudio = new Audio(randomBeatSound);
1814
- beatAudio.play();
1815
-
1816
- if (this.tank.takeDamage(250)) {
1817
- this.endGame();
1818
- }
1819
-
1820
- // ๊ธฐ์กด์˜ createExplosion ๋Œ€์‹  createExplosionEffect ์‚ฌ์šฉ
1821
- this.tank.createExplosionEffect(this.scene, bullet.position);
1822
-
1823
- this.scene.remove(bullet);
1824
- enemy.bullets.splice(bulletIndex, 1);
1825
 
1826
- document.getElementById('health').style.width =
1827
- `${(this.tank.health / MAX_HEALTH) * 100}%`;
1828
- }
1829
- });
1830
- });
 
 
 
 
 
 
 
 
1831
 
 
 
 
 
1832
 
1833
- // ํ”Œ๋ ˆ์ด์–ด ์ด์•Œ๊ณผ ์  ์ถฉ๋Œ ์ฒดํฌ
1834
- for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
1835
- const bullet = this.tank.bullets[i];
1836
- for (let j = this.enemies.length - 1; j >= 0; j--) {
1837
- const enemy = this.enemies[j];
1838
- if (!enemy.mesh || !enemy.isLoaded) continue;
1839
-
1840
- const distance = bullet.position.distanceTo(enemy.mesh.position);
1841
- if (distance < 2) {
1842
- const randomHitSound = hitSounds[Math.floor(Math.random() * hitSounds.length)];
1843
- const hitAudio = new Audio(randomHitSound);
1844
- hitAudio.play();
1845
-
1846
- if (enemy.takeDamage(50)) {
1847
- enemy.destroy();
1848
- this.enemies.splice(j, 1);
1849
- this.score += 100;
1850
- document.getElementById('score').textContent = `Score: ${this.score}`;
1851
  }
1852
-
1853
- // ์—ฌ๊ธฐ๋„ ๋™์ผํ•˜๊ฒŒ ์ˆ˜์ •
1854
- this.tank.createExplosionEffect(this.scene, bullet.position);
1855
-
1856
- this.scene.remove(bullet);
1857
- this.tank.bullets.splice(i, 1);
1858
- break;
1859
  }
1860
  }
1861
- }
1862
 
1863
  // ํ”Œ๋ ˆ์ด์–ด ํƒฑํฌ์™€ ์  ์ „์ฐจ ์ถฉ๋Œ ์ฒดํฌ
1864
  this.enemies.forEach(enemy => {
1865
  if (!enemy.mesh || !enemy.isLoaded) return;
1866
 
1867
- const enemyBoundingBox = new THREE.Box3().setFromObject(enemy.mesh);
1868
- if (tankBoundingBox.intersectsBox(enemyBoundingBox)) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1869
  this.tank.body.position.copy(this.previousTankPosition);
1870
  }
1871
  });
 
43
  this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
44
  this.renderer = new THREE.WebGLRenderer({ antialias: true });
45
  }
46
+ createCollisionBox() {
47
+ // ํƒฑํฌ ๋ชธ์ฒด์— ๋งž๋Š” ์ถฉ๋Œ ๋ฐ•์Šค ์ƒ์„ฑ
48
+ const dimensions = new THREE.Vector3(4, 2, 7); // ํƒฑํฌ์˜ ๋Œ€๋žต์ ์ธ ํฌ๊ธฐ
49
+ const geometry = new THREE.BoxGeometry(dimensions.x, dimensions.y, dimensions.z);
50
+ const material = new THREE.MeshBasicMaterial({
51
+ color: 0xff0000,
52
+ wireframe: true,
53
+ visible: false // ๋””๋ฒ„๊น…์‹œ true๋กœ ๋ณ€๊ฒฝ
54
+ });
55
+
56
+ this.collisionBox = new THREE.Mesh(geometry, material);
57
+ this.body.add(this.collisionBox);
58
+ this.collisionBox.position.set(0, dimensions.y / 2, 0);
59
+ }
60
+
61
  // ๋ณ„๋„์˜ ๋ฉ”์„œ๋“œ๋กœ ๋ถ„๋ฆฌ
62
  createExplosionEffect(scene, position) {
63
  // ํญ๋ฐœ ์ค‘์‹ฌ ํ”Œ๋ž˜์‹œ
 
185
  this.turretGroup.add(this.turret);
186
  this.body.add(this.turretGroup);
187
 
188
+ // ๊ทธ๋ฆผ์ž ์„ค์ •
189
  this.body.traverse((child) => {
190
  if (child.isMesh) {
191
  child.castShadow = true;
 
215
  this.shadowPlane.position.y = 0.1;
216
  this.body.add(this.shadowPlane);
217
 
218
+ // ์Šคํฐ ์œ„์น˜ ์„ค์ •
219
  const spawnPosition = new THREE.Vector3(
220
+ (Math.random() - 0.5) * (MAP_SIZE * 0.8),
221
+ TANK_HEIGHT,
222
  (Math.random() - 0.5) * (MAP_SIZE * 0.8)
223
  );
224
 
225
  this.body.position.copy(spawnPosition);
226
+ this.createCollisionBox();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  scene.add(this.body);
228
  this.isLoaded = true;
229
  this.updateAmmoDisplay();
 
553
  this.isLoaded = false;
554
  this.moveSpeed = type === 'tank' ? ENEMY_MOVE_SPEED : ENEMY_MOVE_SPEED * 0.7;
555
  }
556
+ createCollisionBox() {
557
+ const dimensions = new THREE.Vector3(4, 2, 7);
558
+ const geometry = new THREE.BoxGeometry(dimensions.x, dimensions.y, dimensions.z);
559
+ const material = new THREE.MeshBasicMaterial({
560
+ color: 0xff0000,
561
+ wireframe: true,
562
+ visible: false
563
+ });
564
+
565
+ this.collisionBox = new THREE.Mesh(geometry, material);
566
+ this.mesh.add(this.collisionBox);
567
+ this.collisionBox.position.set(0, dimensions.y / 2, 0);
568
+ }
569
+
570
+ async initialize(loader) {
571
+ await super.initialize(loader);
572
+ this.createCollisionBox();
573
+ }
574
+ }
575
  createMuzzleFlash() {
576
  if (!this.mesh) return;
577
 
 
629
  }, 500);
630
  }
631
 
 
632
  async initialize(loader) {
633
+ try {
634
+ const modelPath = this.type === 'tank' ? '/models/t90.glb' : '/models/t90.glb';
635
+ const result = await loader.loadAsync(modelPath);
636
+ this.mesh = result.scene;
637
+ this.mesh.position.copy(this.position);
638
+ this.mesh.scale.set(ENEMY_SCALE, ENEMY_SCALE, ENEMY_SCALE);
639
+
640
+ this.mesh.traverse((child) => {
641
+ if (child.isMesh) {
642
+ child.castShadow = true;
643
+ child.receiveShadow = true;
644
+ }
645
+ });
646
+
647
+ this.createCollisionBox();
648
+ this.scene.add(this.mesh);
649
+ this.isLoaded = true;
650
+ } catch (error) {
651
+ console.error('Error loading enemy model:', error);
652
+ this.isLoaded = false;
653
  }
654
+ }
655
 
656
  update(playerPosition) {
657
  if (!this.mesh || !this.isLoaded) return;
 
1710
  checkCollisions() {
1711
  if (this.isLoading || !this.tank.isLoaded) return;
1712
 
 
1713
  const hitSounds = [
1714
  'sounds/hit1.ogg', 'sounds/hit2.ogg', 'sounds/hit3.ogg',
1715
  'sounds/hit4.ogg', 'sounds/hit5.ogg', 'sounds/hit6.ogg', 'sounds/hit7.ogg'
1716
  ];
1717
 
 
1718
  const beatSounds = ['sounds/beat1.ogg', 'sounds/beat2.ogg', 'sounds/beat3.ogg'];
1719
 
1720
  const tankPosition = this.tank.getPosition();
1721
+
1722
+ // ์ „์ฐจ ์ถฉ๋Œ ๋ฐ•์Šค ํฌ๊ธฐ ์กฐ์ •
1723
+ const tankBox = new THREE.Box3().setFromObject(this.tank.body);
1724
+ const tankSize = new THREE.Vector3();
1725
+ tankBox.getSize(tankSize);
1726
+
1727
+ // ์ „์ฐจ ์ถฉ๋Œ ๋ฐ•์Šค ํฌ๊ธฐ ์ˆ˜๋™ ์กฐ์ •
1728
+ const customTankBox = new THREE.Box3(
1729
+ new THREE.Vector3(
1730
+ tankPosition.x - tankSize.x * 0.4, // ๋„ˆ๋น„ 20% ๊ฐ์†Œ
1731
+ tankPosition.y - tankSize.y * 0.3, // ๋†’์ด 40% ๊ฐ์†Œ
1732
+ tankPosition.z - tankSize.z * 0.4 // ๊ธธ์ด 20% ๊ฐ์†Œ
1733
+ ),
1734
+ new THREE.Vector3(
1735
+ tankPosition.x + tankSize.x * 0.4,
1736
+ tankPosition.y + tankSize.y * 0.3,
1737
+ tankPosition.z + tankSize.z * 0.4
1738
+ )
1739
+ );
1740
+
1741
+ // ํƒฑํฌ์™€ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ
1742
  this.obstacles.forEach(obstacle => {
1743
+ if (obstacle.userData.isCollidable) {
1744
+ const obstacleBox = new THREE.Box3().setFromObject(obstacle);
1745
+ if (customTankBox.intersectsBox(obstacleBox)) {
1746
+ this.tank.body.position.copy(this.previousTankPosition);
1747
+ }
1748
  }
1749
+ });
1750
+
1751
+ // ์  ํƒฑํฌ์™€ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ
1752
  this.enemies.forEach(enemy => {
1753
  if (!enemy.mesh || !enemy.isLoaded) return;
1754
 
1755
+ const enemyBox = new THREE.Box3().setFromObject(enemy.mesh);
1756
+ const enemySize = new THREE.Vector3();
1757
+ enemyBox.getSize(enemySize);
1758
+
1759
+ // ์  ์ „์ฐจ ์ถฉ๋Œ ๋ฐ•์Šค ํฌ๊ธฐ ์ˆ˜๋™ ์กฐ์ •
1760
+ const customEnemyBox = new THREE.Box3(
1761
+ new THREE.Vector3(
1762
+ enemy.mesh.position.x - enemySize.x * 0.4,
1763
+ enemy.mesh.position.y - enemySize.y * 0.3,
1764
+ enemy.mesh.position.z - enemySize.z * 0.4
1765
+ ),
1766
+ new THREE.Vector3(
1767
+ enemy.mesh.position.x + enemySize.x * 0.4,
1768
+ enemy.mesh.position.y + enemySize.y * 0.3,
1769
+ enemy.mesh.position.z + enemySize.z * 0.4
1770
+ )
1771
+ );
1772
+
1773
  const enemyPreviousPosition = enemy.mesh.position.clone();
1774
 
1775
  this.obstacles.forEach(obstacle => {
1776
+ const obstacleBox = new THREE.Box3().setFromObject(obstacle);
1777
+ if (customEnemyBox.intersectsBox(obstacleBox)) {
1778
  enemy.mesh.position.copy(enemyPreviousPosition);
1779
  }
1780
  });
 
1785
  if (!enemy.mesh || !enemy.isLoaded) return;
1786
 
1787
  enemy.bullets.forEach((bullet, bulletIndex) => {
1788
+ const bulletBox = new THREE.Box3().setFromObject(bullet);
1789
+ if (bulletBox.intersectsBox(customTankBox)) {
 
1790
  const randomBeatSound = beatSounds[Math.floor(Math.random() * beatSounds.length)];
1791
  const beatAudio = new Audio(randomBeatSound);
1792
  beatAudio.play();
 
1795
  this.endGame();
1796
  }
1797
  this.scene.remove(bullet);
1798
+ enemy.bullets.splice(bulletIndex, 1);
1799
 
1800
+ this.tank.createExplosionEffect(this.scene, bullet.position);
1801
  document.getElementById('health').style.width =
1802
  `${(this.tank.health / MAX_HEALTH) * 100}%`;
1803
  }
1804
  });
1805
  });
1806
 
1807
+ // ํ”Œ๋ ˆ์ด์–ด ํฌํƒ„๊ณผ ์žฅ์• ๋ฌผ ์ถฉ๋Œ ์ฒดํฌ
1808
+ for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
1809
+ const bullet = this.tank.bullets[i];
1810
+ const bulletBox = new THREE.Box3().setFromObject(bullet);
 
1811
 
1812
+ for (const obstacle of this.obstacles) {
1813
+ if (obstacle.userData.isCollidable) {
1814
+ const obstacleBox = new THREE.Box3().setFromObject(obstacle);
1815
+ if (bulletBox.intersectsBox(obstacleBox)) {
1816
+ this.tank.createExplosionEffect(this.scene, bullet.position);
1817
+ this.scene.remove(bullet);
1818
+ this.tank.bullets.splice(i, 1);
1819
+ break;
1820
+ }
 
 
1821
  }
1822
  }
1823
  }
 
1824
 
1825
+ // ํ”Œ๋ ˆ์ด์–ด ์ด์•Œ๊ณผ ์  ์ถฉ๋Œ ์ฒดํฌ
1826
+ for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
1827
+ const bullet = this.tank.bullets[i];
1828
+ const bulletBox = new THREE.Box3().setFromObject(bullet);
1829
+
1830
+ for (let j = this.enemies.length - 1; j >= 0; j--) {
1831
+ const enemy = this.enemies[j];
1832
+ if (!enemy.mesh || !enemy.isLoaded) continue;
1833
+
1834
+ const enemyBox = new THREE.Box3().setFromObject(enemy.mesh);
1835
+ const enemySize = new THREE.Vector3();
1836
+ enemyBox.getSize(enemySize);
 
 
 
 
 
 
 
 
 
1837
 
1838
+ // ์  ์ „์ฐจ ์ถฉ๋Œ ๋ฐ•์Šค ์กฐ์ •
1839
+ const customEnemyBox = new THREE.Box3(
1840
+ new THREE.Vector3(
1841
+ enemy.mesh.position.x - enemySize.x * 0.4,
1842
+ enemy.mesh.position.y - enemySize.y * 0.3,
1843
+ enemy.mesh.position.z - enemySize.z * 0.4
1844
+ ),
1845
+ new THREE.Vector3(
1846
+ enemy.mesh.position.x + enemySize.x * 0.4,
1847
+ enemy.mesh.position.y + enemySize.y * 0.3,
1848
+ enemy.mesh.position.z + enemySize.z * 0.4
1849
+ )
1850
+ );
1851
 
1852
+ if (bulletBox.intersectsBox(customEnemyBox)) {
1853
+ const randomHitSound = hitSounds[Math.floor(Math.random() * hitSounds.length)];
1854
+ const hitAudio = new Audio(randomHitSound);
1855
+ hitAudio.play();
1856
 
1857
+ if (enemy.takeDamage(50)) {
1858
+ enemy.destroy();
1859
+ this.enemies.splice(j, 1);
1860
+ this.score += 100;
1861
+ document.getElementById('score').textContent = `Score: ${this.score}`;
1862
+ }
1863
+
1864
+ this.tank.createExplosionEffect(this.scene, bullet.position);
1865
+ this.scene.remove(bullet);
1866
+ this.tank.bullets.splice(i, 1);
1867
+ break;
 
 
 
 
 
 
 
1868
  }
 
 
 
 
 
 
 
1869
  }
1870
  }
 
1871
 
1872
  // ํ”Œ๋ ˆ์ด์–ด ํƒฑํฌ์™€ ์  ์ „์ฐจ ์ถฉ๋Œ ์ฒดํฌ
1873
  this.enemies.forEach(enemy => {
1874
  if (!enemy.mesh || !enemy.isLoaded) return;
1875
 
1876
+ const enemyBox = new THREE.Box3().setFromObject(enemy.mesh);
1877
+ const enemySize = new THREE.Vector3();
1878
+ enemyBox.getSize(enemySize);
1879
+
1880
+ const customEnemyBox = new THREE.Box3(
1881
+ new THREE.Vector3(
1882
+ enemy.mesh.position.x - enemySize.x * 0.4,
1883
+ enemy.mesh.position.y - enemySize.y * 0.3,
1884
+ enemy.mesh.position.z - enemySize.z * 0.4
1885
+ ),
1886
+ new THREE.Vector3(
1887
+ enemy.mesh.position.x + enemySize.x * 0.4,
1888
+ enemy.mesh.position.y + enemySize.y * 0.3,
1889
+ enemy.mesh.position.z + enemySize.z * 0.4
1890
+ )
1891
+ );
1892
+
1893
+ if (customTankBox.intersectsBox(customEnemyBox)) {
1894
  this.tank.body.position.copy(this.previousTankPosition);
1895
  }
1896
  });