Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -1506,44 +1506,44 @@ class EnemyFighter {
|
|
| 1506 |
if (this.mesh) {
|
| 1507 |
console.log('Removing enemy mesh from scene');
|
| 1508 |
|
| 1509 |
-
//
|
| 1510 |
-
|
| 1511 |
-
|
| 1512 |
-
|
| 1513 |
-
this.mesh.remove(child);
|
| 1514 |
|
| 1515 |
-
//
|
| 1516 |
-
if (child.geometry)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1517 |
if (child.material) {
|
| 1518 |
if (Array.isArray(child.material)) {
|
| 1519 |
-
child.material.forEach(mat =>
|
|
|
|
|
|
|
| 1520 |
} else {
|
| 1521 |
-
child.material.dispose();
|
| 1522 |
}
|
| 1523 |
}
|
| 1524 |
}
|
| 1525 |
-
}
|
| 1526 |
|
| 1527 |
-
// ๋ฉ์
|
| 1528 |
-
if (this.
|
| 1529 |
-
|
| 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 |
|
|
@@ -1567,6 +1567,161 @@ class EnemyFighter {
|
|
| 1567 |
console.log('EnemyFighter destroyed successfully');
|
| 1568 |
}
|
| 1569 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1570 |
// Game ํด๋์ค์ checkCollisions ๋ฉ์๋๋ ์ฝ๊ฐ ์์
|
| 1571 |
checkCollisions() {
|
| 1572 |
// ํ๋ ์ด์ด ํํ vs ์ ๊ธฐ ์ถฉ๋
|
|
|
|
| 1506 |
if (this.mesh) {
|
| 1507 |
console.log('Removing enemy mesh from scene');
|
| 1508 |
|
| 1509 |
+
// GLB ๋ชจ๋ธ์ ๋ณต์กํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฏ๋ก ์ ์ฒด ๊ณ์ธต๊ตฌ์กฐ๋ฅผ ์ํํ๋ฉฐ ์ ๊ฑฐ
|
| 1510 |
+
this.mesh.traverse((child) => {
|
| 1511 |
+
if (child.isMesh) {
|
| 1512 |
+
console.log('Disposing mesh:', child.name || 'unnamed');
|
|
|
|
| 1513 |
|
| 1514 |
+
// geometry ์ ๊ฑฐ
|
| 1515 |
+
if (child.geometry) {
|
| 1516 |
+
child.geometry.dispose();
|
| 1517 |
+
}
|
| 1518 |
+
|
| 1519 |
+
// material ์ ๊ฑฐ
|
| 1520 |
if (child.material) {
|
| 1521 |
if (Array.isArray(child.material)) {
|
| 1522 |
+
child.material.forEach(mat => {
|
| 1523 |
+
if (mat.dispose) mat.dispose();
|
| 1524 |
+
});
|
| 1525 |
} else {
|
| 1526 |
+
if (child.material.dispose) child.material.dispose();
|
| 1527 |
}
|
| 1528 |
}
|
| 1529 |
}
|
| 1530 |
+
});
|
| 1531 |
|
| 1532 |
+
// ์ฌ์์ ๋ฉ์ ์ ๊ฑฐ - ์ฌ๋ฌ ๋ฐฉ๋ฒ ์๋
|
| 1533 |
+
if (this.scene) {
|
| 1534 |
+
this.scene.remove(this.mesh);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1535 |
}
|
| 1536 |
|
| 1537 |
+
// parent๊ฐ ์๋ค๋ฉด parent์์๋ ์ ๊ฑฐ
|
|
|
|
|
|
|
|
|
|
| 1538 |
if (this.mesh.parent) {
|
| 1539 |
+
console.log('Mesh still has parent, forcing removal from parent');
|
| 1540 |
this.mesh.parent.remove(this.mesh);
|
| 1541 |
}
|
| 1542 |
|
| 1543 |
+
// ๋ฉ์๋ฅผ ๋นํ์ฑํ
|
| 1544 |
+
this.mesh.visible = false;
|
| 1545 |
+
|
| 1546 |
+
// ๋ฉ์ ์ฐธ์กฐ ์์ ํ ์ ๊ฑฐ
|
| 1547 |
this.mesh = null;
|
| 1548 |
}
|
| 1549 |
|
|
|
|
| 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 |
+
// ์ ๊ธฐ ๋ฉ์๋ฅผ ๋จผ์ ์จ๊ธฐ๊ธฐ
|
| 1610 |
+
if (enemy.mesh) {
|
| 1611 |
+
enemy.mesh.visible = false;
|
| 1612 |
+
}
|
| 1613 |
+
|
| 1614 |
+
// ์ ๊ธฐ ์ ๊ฑฐ
|
| 1615 |
+
enemy.destroy();
|
| 1616 |
+
|
| 1617 |
+
// ๋ฐฐ์ด์์ ์ ๊ฑฐ
|
| 1618 |
+
this.enemies.splice(j, 1);
|
| 1619 |
+
this.score += 100;
|
| 1620 |
+
|
| 1621 |
+
console.log(`Enemy removed. Remaining enemies: ${this.enemies.length}`);
|
| 1622 |
+
}
|
| 1623 |
+
break;
|
| 1624 |
+
}
|
| 1625 |
+
}
|
| 1626 |
+
}
|
| 1627 |
+
|
| 1628 |
+
// ์ ํํ vs ํ๋ ์ด์ด ์ถฉ๋
|
| 1629 |
+
this.enemies.forEach(enemy => {
|
| 1630 |
+
// ํ๊ดด๋ ์ ์ ์ฒ๋ฆฌํ์ง ์์
|
| 1631 |
+
if (enemy.isDestroyed) return;
|
| 1632 |
+
|
| 1633 |
+
for (let index = enemy.bullets.length - 1; index >= 0; index--) {
|
| 1634 |
+
const bullet = enemy.bullets[index];
|
| 1635 |
+
const distance = bullet.position.distanceTo(this.fighter.position);
|
| 1636 |
+
if (distance < 100) {
|
| 1637 |
+
// ํ๋ ์ด์ด ํผ๊ฒฉ ์ดํํธ
|
| 1638 |
+
this.createHitEffect(this.fighter.position);
|
| 1639 |
+
|
| 1640 |
+
// ํํ ์ ๊ฑฐ
|
| 1641 |
+
this.scene.remove(bullet);
|
| 1642 |
+
enemy.bullets.splice(index, 1);
|
| 1643 |
+
|
| 1644 |
+
if (this.fighter.takeDamage(GAME_CONSTANTS.BULLET_DAMAGE)) {
|
| 1645 |
+
// ํ๋ ์ด์ด ํ๊ดด ์ ํญ๋ฐ ํจ๊ณผ ์ถ๊ฐ
|
| 1646 |
+
this.createExplosionEffect(this.fighter.position);
|
| 1647 |
+
|
| 1648 |
+
this.endGame(false);
|
| 1649 |
+
}
|
| 1650 |
+
}
|
| 1651 |
+
}
|
| 1652 |
+
});
|
| 1653 |
+
}
|
| 1654 |
+
|
| 1655 |
+
// EnemyFighter์ update ๋ฉ์๋์๋ ์ถ๊ฐ ๋ณดํธ ์ฅ์น
|
| 1656 |
+
update(playerPosition, deltaTime) {
|
| 1657 |
+
// ํ๊ดด๋์๊ฑฐ๋ ๋ฉ์๊ฐ ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ํ์ง ์์
|
| 1658 |
+
if (!this.mesh || !this.isLoaded || this.isDestroyed || !this.mesh.visible) return;
|
| 1659 |
+
|
| 1660 |
+
// ... ๋๋จธ์ง update ๋ก์ง
|
| 1661 |
+
|
| 1662 |
+
// ํํผ ํ์ด๋จธ ์
๋ฐ์ดํธ
|
| 1663 |
+
if (this.temporaryEvadeMode && this.evadeTimer > 0) {
|
| 1664 |
+
this.evadeTimer -= deltaTime;
|
| 1665 |
+
if (this.evadeTimer <= 0) {
|
| 1666 |
+
this.temporaryEvadeMode = false;
|
| 1667 |
+
}
|
| 1668 |
+
}
|
| 1669 |
+
|
| 1670 |
+
const distanceToPlayer = this.position.distanceTo(playerPosition);
|
| 1671 |
+
|
| 1672 |
+
// 100m ์ด๋ด๋ฉด ์ฆ์ ํํด ๋ชจ๋ ํ์ฑํ
|
| 1673 |
+
if (distanceToPlayer < 100) {
|
| 1674 |
+
this.isRetreating = true;
|
| 1675 |
+
this.aiState = 'retreat';
|
| 1676 |
+
console.log(`Enemy retreating! Distance: ${distanceToPlayer.toFixed(1)}m`);
|
| 1677 |
+
}
|
| 1678 |
+
|
| 1679 |
+
// 250m ์ด์ ๋จ์ด์ง๋ฉด ํํด ๋ชจ๋ ํด์
|
| 1680 |
+
if (this.isRetreating && distanceToPlayer >= this.retreatTargetDistance) {
|
| 1681 |
+
this.isRetreating = false;
|
| 1682 |
+
console.log(`Enemy retreat complete. Distance: ${distanceToPlayer.toFixed(1)}m`);
|
| 1683 |
+
}
|
| 1684 |
+
|
| 1685 |
+
// ์ํ ๊ฒฐ์ - ํํด๊ฐ ์ต์ฐ์
|
| 1686 |
+
if (this.isRetreating) {
|
| 1687 |
+
this.aiState = 'retreat';
|
| 1688 |
+
} else if (this.temporaryEvadeMode) {
|
| 1689 |
+
this.aiState = 'evade';
|
| 1690 |
+
} else if (distanceToPlayer <= 3000) {
|
| 1691 |
+
this.aiState = 'combat';
|
| 1692 |
+
} else {
|
| 1693 |
+
this.aiState = 'patrol';
|
| 1694 |
+
}
|
| 1695 |
+
|
| 1696 |
+
// ์ถฉ๋ ํํผ ๊ณ์ฐ (ํํด ์ค์ด ์๋ ๋๋ง)
|
| 1697 |
+
if (!this.isRetreating) {
|
| 1698 |
+
this.calculateAvoidance();
|
| 1699 |
+
this.checkCollisionPrediction(deltaTime);
|
| 1700 |
+
}
|
| 1701 |
+
|
| 1702 |
+
// AI ํ๋ ์คํ
|
| 1703 |
+
switch (this.aiState) {
|
| 1704 |
+
case 'patrol':
|
| 1705 |
+
this.executePatrol(deltaTime);
|
| 1706 |
+
break;
|
| 1707 |
+
case 'combat':
|
| 1708 |
+
this.executeCombat(playerPosition, deltaTime);
|
| 1709 |
+
break;
|
| 1710 |
+
case 'evade':
|
| 1711 |
+
this.executeEmergencyEvade(deltaTime);
|
| 1712 |
+
break;
|
| 1713 |
+
case 'retreat':
|
| 1714 |
+
this.executeRetreat(playerPosition, deltaTime);
|
| 1715 |
+
break;
|
| 1716 |
+
}
|
| 1717 |
+
|
| 1718 |
+
// ๋ฌผ๋ฆฌ ์
๋ฐ์ดํธ
|
| 1719 |
+
this.updatePhysics(deltaTime);
|
| 1720 |
+
|
| 1721 |
+
// ํํ ์
๋ฐ์ดํธ
|
| 1722 |
+
this.updateBullets(deltaTime);
|
| 1723 |
+
}
|
| 1724 |
+
|
| 1725 |
// Game ํด๋์ค์ checkCollisions ๋ฉ์๋๋ ์ฝ๊ฐ ์์
|
| 1726 |
checkCollisions() {
|
| 1727 |
// ํ๋ ์ด์ด ํํ vs ์ ๊ธฐ ์ถฉ๋
|