Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
@@ -1492,29 +1492,165 @@ class EnemyFighter {
|
|
1492 |
}
|
1493 |
|
1494 |
destroy() {
|
1495 |
-
|
1496 |
-
|
1497 |
-
|
1498 |
-
|
1499 |
-
|
1500 |
-
|
1501 |
-
|
1502 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1503 |
} else {
|
1504 |
-
|
1505 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1506 |
|
1507 |
-
//
|
1508 |
-
|
1509 |
-
this.mesh = null;
|
1510 |
-
|
1511 |
-
// 남은 탄환들 제거
|
1512 |
-
this.bullets.forEach(bullet => this.scene.remove(bullet));
|
1513 |
-
this.bullets = [];
|
1514 |
|
1515 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1516 |
}
|
1517 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1518 |
}
|
1519 |
|
1520 |
// 메인 게임 클래스
|
|
|
1492 |
}
|
1493 |
|
1494 |
destroy() {
|
1495 |
+
console.log('EnemyFighter destroy() called');
|
1496 |
+
|
1497 |
+
if (this.isDestroyed) {
|
1498 |
+
console.log('Already destroyed, skipping');
|
1499 |
+
return;
|
1500 |
+
}
|
1501 |
+
|
1502 |
+
// 파괴 상태 설정
|
1503 |
+
this.isDestroyed = true;
|
1504 |
+
|
1505 |
+
// 메시가 있는지 확인하고 제거
|
1506 |
+
if (this.mesh) {
|
1507 |
+
console.log('Removing enemy mesh from scene');
|
1508 |
+
|
1509 |
+
// 메시가 그룹인 경우 모든 자식 요소도 제거
|
1510 |
+
if (this.mesh.children && this.mesh.children.length > 0) {
|
1511 |
+
while (this.mesh.children.length > 0) {
|
1512 |
+
const child = this.mesh.children[0];
|
1513 |
+
this.mesh.remove(child);
|
1514 |
+
|
1515 |
+
// 자식 요소의 geometry와 material도 정리
|
1516 |
+
if (child.geometry) child.geometry.dispose();
|
1517 |
+
if (child.material) {
|
1518 |
+
if (Array.isArray(child.material)) {
|
1519 |
+
child.material.forEach(mat => mat.dispose());
|
1520 |
+
} else {
|
1521 |
+
child.material.dispose();
|
1522 |
+
}
|
1523 |
+
}
|
1524 |
+
}
|
1525 |
+
}
|
1526 |
+
|
1527 |
+
// 메시 자체의 geometry와 material 정리
|
1528 |
+
if (this.mesh.geometry) this.mesh.geometry.dispose();
|
1529 |
+
if (this.mesh.material) {
|
1530 |
+
if (Array.isArray(this.mesh.material)) {
|
1531 |
+
this.mesh.material.forEach(mat => mat.dispose());
|
1532 |
} else {
|
1533 |
+
this.mesh.material.dispose();
|
1534 |
}
|
1535 |
+
}
|
1536 |
+
|
1537 |
+
// 씬에서 메시 제거
|
1538 |
+
this.scene.remove(this.mesh);
|
1539 |
+
|
1540 |
+
// 메시가 실제로 제거되었는지 확인
|
1541 |
+
if (this.mesh.parent) {
|
1542 |
+
console.log('Mesh still has parent, forcing removal');
|
1543 |
+
this.mesh.parent.remove(this.mesh);
|
1544 |
+
}
|
1545 |
+
|
1546 |
+
// 메시 참조 제거
|
1547 |
+
this.mesh = null;
|
1548 |
+
}
|
1549 |
+
|
1550 |
+
// 남은 탄환들 제거
|
1551 |
+
console.log(`Removing ${this.bullets.length} enemy bullets`);
|
1552 |
+
this.bullets.forEach(bullet => {
|
1553 |
+
// 탄환의 geometry와 material도 정리
|
1554 |
+
if (bullet.geometry) bullet.geometry.dispose();
|
1555 |
+
if (bullet.material) bullet.material.dispose();
|
1556 |
+
|
1557 |
+
this.scene.remove(bullet);
|
1558 |
+
|
1559 |
+
// 탄환이 실제로 제거되었는지 확인
|
1560 |
+
if (bullet.parent) {
|
1561 |
+
bullet.parent.remove(bullet);
|
1562 |
+
}
|
1563 |
+
});
|
1564 |
+
this.bullets = [];
|
1565 |
+
|
1566 |
+
this.isLoaded = false;
|
1567 |
+
console.log('EnemyFighter destroyed successfully');
|
1568 |
+
}
|
1569 |
+
|
1570 |
+
// Game 클래스의 checkCollisions 메서드도 약간 수정
|
1571 |
+
checkCollisions() {
|
1572 |
+
// 플레이어 탄환 vs 적기 충돌
|
1573 |
+
for (let i = this.fighter.bullets.length - 1; i >= 0; i--) {
|
1574 |
+
const bullet = this.fighter.bullets[i];
|
1575 |
+
|
1576 |
+
for (let j = this.enemies.length - 1; j >= 0; j--) {
|
1577 |
+
const enemy = this.enemies[j];
|
1578 |
|
1579 |
+
// 이미 파괴된 적은 건너뛰기
|
1580 |
+
if (!enemy.mesh || !enemy.isLoaded || enemy.isDestroyed) continue;
|
|
|
|
|
|
|
|
|
|
|
1581 |
|
1582 |
+
const distance = bullet.position.distanceTo(enemy.position);
|
1583 |
+
if (distance < 90) {
|
1584 |
+
console.log(`Hit detected! Distance: ${distance}, Enemy health: ${enemy.health}`);
|
1585 |
+
|
1586 |
+
// 히트 표시 추가
|
1587 |
+
this.showHitMarker(enemy.position);
|
1588 |
+
// 피격 이펙트 추가
|
1589 |
+
this.createHitEffect(enemy.position);
|
1590 |
+
|
1591 |
+
// 탄환 제거
|
1592 |
+
this.scene.remove(bullet);
|
1593 |
+
this.fighter.bullets.splice(i, 1);
|
1594 |
+
|
1595 |
+
// 적기에 데미지 입히기
|
1596 |
+
const isDestroyed = enemy.takeDamage(GAME_CONSTANTS.BULLET_DAMAGE);
|
1597 |
+
console.log(`Enemy damaged. New health: ${enemy.health}, Destroyed: ${isDestroyed}`);
|
1598 |
+
|
1599 |
+
if (isDestroyed) {
|
1600 |
+
console.log('Enemy destroyed! Creating explosion effect...');
|
1601 |
+
|
1602 |
+
// 폭발 효과 생성 - 위치를 복사해서 전달
|
1603 |
+
const explosionPosition = enemy.position.clone();
|
1604 |
+
console.log('Explosion position:', explosionPosition);
|
1605 |
+
|
1606 |
+
// 폭발 효과 즉시 생성
|
1607 |
+
this.createExplosionEffect(explosionPosition);
|
1608 |
+
|
1609 |
+
// 적기 메시 제거 (destroy 호출 전에 명시적으로 제거)
|
1610 |
+
if (enemy.mesh && enemy.mesh.parent) {
|
1611 |
+
console.log('Explicitly removing enemy mesh before destroy');
|
1612 |
+
enemy.mesh.parent.remove(enemy.mesh);
|
1613 |
+
}
|
1614 |
+
|
1615 |
+
// 적기 제거
|
1616 |
+
enemy.destroy();
|
1617 |
+
|
1618 |
+
// 배열에서 제거
|
1619 |
+
this.enemies.splice(j, 1);
|
1620 |
+
this.score += 100;
|
1621 |
+
|
1622 |
+
console.log(`Enemy removed. Remaining enemies: ${this.enemies.length}`);
|
1623 |
+
}
|
1624 |
+
break;
|
1625 |
+
}
|
1626 |
}
|
1627 |
}
|
1628 |
+
|
1629 |
+
// 적 탄환 vs 플레이어 충돌
|
1630 |
+
this.enemies.forEach(enemy => {
|
1631 |
+
// 파괴된 적은 처리하지 않음
|
1632 |
+
if (enemy.isDestroyed) return;
|
1633 |
+
|
1634 |
+
for (let index = enemy.bullets.length - 1; index >= 0; index--) {
|
1635 |
+
const bullet = enemy.bullets[index];
|
1636 |
+
const distance = bullet.position.distanceTo(this.fighter.position);
|
1637 |
+
if (distance < 100) {
|
1638 |
+
// 플레이어 피격 이펙트
|
1639 |
+
this.createHitEffect(this.fighter.position);
|
1640 |
+
|
1641 |
+
// 탄환 제거
|
1642 |
+
this.scene.remove(bullet);
|
1643 |
+
enemy.bullets.splice(index, 1);
|
1644 |
+
|
1645 |
+
if (this.fighter.takeDamage(GAME_CONSTANTS.BULLET_DAMAGE)) {
|
1646 |
+
// 플레이어 파괴 시 폭발 효과 추가
|
1647 |
+
this.createExplosionEffect(this.fighter.position);
|
1648 |
+
|
1649 |
+
this.endGame(false);
|
1650 |
+
}
|
1651 |
+
}
|
1652 |
+
}
|
1653 |
+
});
|
1654 |
}
|
1655 |
|
1656 |
// 메인 게임 클래스
|