Spaces:
Running
Running
cutechicken
commited on
Commit
โข
57a9965
1
Parent(s):
75e71ec
Update game.js
Browse files
game.js
CHANGED
@@ -327,8 +327,50 @@ class Game {
|
|
327 |
// ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์
|
328 |
this.setupEventListeners();
|
329 |
this.initialize();
|
|
|
330 |
}
|
331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
async initialize() {
|
333 |
try {
|
334 |
// ์กฐ๋ช
์ค์
|
@@ -587,22 +629,30 @@ createBuildings() {
|
|
587 |
}
|
588 |
}
|
589 |
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
600 |
}
|
601 |
-
|
602 |
-
};
|
603 |
|
604 |
-
spawnEnemy
|
605 |
-
}
|
|
|
|
|
|
|
606 |
|
607 |
getValidEnemySpawnPosition() {
|
608 |
const margin = 20;
|
@@ -666,41 +716,47 @@ createBuildings() {
|
|
666 |
}
|
667 |
|
668 |
checkCollisions() {
|
669 |
-
|
670 |
|
671 |
-
|
|
|
672 |
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
enemy.bullets.forEach(bullet => {
|
677 |
-
const distance = bullet.position.distanceTo(tankPosition);
|
678 |
-
if (distance < 1) {
|
679 |
-
if (this.tank.takeDamage(10)) {
|
680 |
-
this.endGame();
|
681 |
-
}
|
682 |
-
this.scene.remove(bullet);
|
683 |
-
enemy.bullets = enemy.bullets.filter(b => b !== bullet);
|
684 |
-
|
685 |
-
this.createExplosion(bullet.position);
|
686 |
-
document.getElementById('health').style.width =
|
687 |
-
`${(this.tank.health / MAX_HEALTH) * 100}%`;
|
688 |
-
}
|
689 |
-
});
|
690 |
-
});
|
691 |
|
692 |
-
|
693 |
-
|
694 |
-
const
|
695 |
-
|
696 |
-
|
697 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
698 |
}
|
699 |
}
|
700 |
-
|
701 |
-
this.previousTankPosition = this.tank.body.position.clone();
|
702 |
}
|
703 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
704 |
endGame() {
|
705 |
this.isGameOver = true;
|
706 |
const gameOverDiv = document.createElement('div');
|
@@ -728,36 +784,46 @@ createBuildings() {
|
|
728 |
}
|
729 |
|
730 |
animate() {
|
731 |
-
|
732 |
|
733 |
-
|
734 |
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
|
744 |
-
|
745 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
746 |
|
747 |
-
const
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
|
|
761 |
|
762 |
updateUI() {
|
763 |
const healthBar = document.getElementById('health');
|
|
|
327 |
// ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์
|
328 |
this.setupEventListeners();
|
329 |
this.initialize();
|
330 |
+
this.disposedObjects = new Set(); // ์ ๊ฑฐ๋ ๊ฐ์ฒด ์ถ์
|
331 |
}
|
332 |
|
333 |
+
// ๋ฆฌ์์ค ์ ๋ฆฌ๋ฅผ ์ํ ๋ฉ์๋ ์ถ๊ฐ
|
334 |
+
dispose(object) {
|
335 |
+
if (this.disposedObjects.has(object)) return;
|
336 |
+
|
337 |
+
if (object.geometry) object.geometry.dispose();
|
338 |
+
if (object.material) {
|
339 |
+
if (Array.isArray(object.material)) {
|
340 |
+
object.material.forEach(material => material.dispose());
|
341 |
+
} else {
|
342 |
+
object.material.dispose();
|
343 |
+
}
|
344 |
+
}
|
345 |
+
if (object.parent) object.parent.remove(object);
|
346 |
+
this.disposedObjects.add(object);
|
347 |
+
}
|
348 |
+
// ์ด์ ์ ๊ฑฐ ์ ๋ฆฌ์์ค ์ ๋ฆฌ
|
349 |
+
cleanupBullets() {
|
350 |
+
// ํ๋ ์ด์ด ์ด์ ์ ๋ฆฌ
|
351 |
+
for (let i = this.tank.bullets.length - 1; i >= 0; i--) {
|
352 |
+
const bullet = this.tank.bullets[i];
|
353 |
+
if (Math.abs(bullet.position.x) > MAP_SIZE/2 ||
|
354 |
+
Math.abs(bullet.position.z) > MAP_SIZE/2) {
|
355 |
+
this.dispose(bullet);
|
356 |
+
this.tank.bullets.splice(i, 1);
|
357 |
+
}
|
358 |
+
}
|
359 |
+
// ์ ์ด์ ์ ๋ฆฌ
|
360 |
+
this.enemies.forEach(enemy => {
|
361 |
+
for (let i = enemy.bullets.length - 1; i >= 0; i--) {
|
362 |
+
const bullet = enemy.bullets[i];
|
363 |
+
if (Math.abs(bullet.position.x) > MAP_SIZE/2 ||
|
364 |
+
Math.abs(bullet.position.z) > MAP_SIZE/2) {
|
365 |
+
this.dispose(bullet);
|
366 |
+
enemy.bullets.splice(i, 1);
|
367 |
+
}
|
368 |
+
}
|
369 |
+
});
|
370 |
+
}
|
371 |
+
}
|
372 |
+
|
373 |
+
|
374 |
async initialize() {
|
375 |
try {
|
376 |
// ์กฐ๋ช
์ค์
|
|
|
629 |
}
|
630 |
}
|
631 |
|
632 |
+
spawnEnemies() {
|
633 |
+
let spawnTimeout;
|
634 |
+
|
635 |
+
const spawnEnemy = () => {
|
636 |
+
if (this.isGameOver) {
|
637 |
+
clearTimeout(spawnTimeout);
|
638 |
+
return;
|
639 |
+
}
|
640 |
+
|
641 |
+
if (this.enemies.length < ENEMY_COUNT_MAX) {
|
642 |
+
const position = this.getValidEnemySpawnPosition();
|
643 |
+
if (position) {
|
644 |
+
const type = Math.random() < 0.7 ? 'tank' : 'heavy';
|
645 |
+
const enemy = new Enemy(this.scene, position, type);
|
646 |
+
enemy.initialize(this.loader).catch(console.error);
|
647 |
+
this.enemies.push(enemy);
|
648 |
}
|
649 |
+
}
|
|
|
650 |
|
651 |
+
spawnTimeout = setTimeout(spawnEnemy, 3000);
|
652 |
+
};
|
653 |
+
|
654 |
+
spawnEnemy();
|
655 |
+
}
|
656 |
|
657 |
getValidEnemySpawnPosition() {
|
658 |
const margin = 20;
|
|
|
716 |
}
|
717 |
|
718 |
checkCollisions() {
|
719 |
+
if (this.isLoading || !this.tank.isLoaded) return;
|
720 |
|
721 |
+
const tankPosition = this.tank.getPosition();
|
722 |
+
const tankBoundingBox = new THREE.Box3().setFromObject(this.tank.body);
|
723 |
|
724 |
+
// ์ ์ด์๊ณผ์ ์ถฉ๋ ๊ฒ์ฌ๋ฅผ ์ต์ ํ
|
725 |
+
for (const enemy of this.enemies) {
|
726 |
+
if (!enemy.mesh || !enemy.isLoaded) continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
727 |
|
728 |
+
for (let i = enemy.bullets.length - 1; i >= 0; i--) {
|
729 |
+
const bullet = enemy.bullets[i];
|
730 |
+
const distance = bullet.position.distanceTo(tankPosition);
|
731 |
+
|
732 |
+
if (distance > 50) continue; // ๋จผ ๏ฟฝ๏ฟฝ์์ ๊ฒ์ฌ ์คํต
|
733 |
+
|
734 |
+
if (distance < 1) {
|
735 |
+
if (this.tank.takeDamage(10)) {
|
736 |
+
this.endGame();
|
737 |
+
return;
|
738 |
+
}
|
739 |
+
this.dispose(bullet);
|
740 |
+
enemy.bullets.splice(i, 1);
|
741 |
+
this.createExplosion(bullet.position);
|
742 |
+
document.getElementById('health').style.width =
|
743 |
+
`${(this.tank.health / MAX_HEALTH) * 100}%`;
|
744 |
}
|
745 |
}
|
|
|
|
|
746 |
}
|
747 |
|
748 |
+
// ๊ฑด๋ฌผ๊ณผ์ ์ถฉ๋ ๊ฒ์ฌ ์ต์ ํ
|
749 |
+
for (const building of this.buildings) {
|
750 |
+
const buildingBox = new THREE.Box3().setFromObject(building);
|
751 |
+
if (tankBoundingBox.intersectsBox(buildingBox)) {
|
752 |
+
this.tank.body.position.copy(this.previousTankPosition);
|
753 |
+
break;
|
754 |
+
}
|
755 |
+
}
|
756 |
+
|
757 |
+
this.previousTankPosition = this.tank.body.position.clone();
|
758 |
+
}
|
759 |
+
|
760 |
endGame() {
|
761 |
this.isGameOver = true;
|
762 |
const gameOverDiv = document.createElement('div');
|
|
|
784 |
}
|
785 |
|
786 |
animate() {
|
787 |
+
if (this.isGameOver) return;
|
788 |
|
789 |
+
requestAnimationFrame(() => this.animate());
|
790 |
|
791 |
+
const currentTime = performance.now();
|
792 |
+
const deltaTime = (currentTime - this.lastTime) / 1000;
|
793 |
+
this.lastTime = currentTime;
|
794 |
|
795 |
+
if (this.isLoading) {
|
796 |
+
this.renderer.render(this.scene, this.camera);
|
797 |
+
return;
|
798 |
+
}
|
799 |
|
800 |
+
// ํ๋ ์ ์ ํ (60fps)
|
801 |
+
if (deltaTime < 1/60) return;
|
802 |
+
|
803 |
+
this.handleMovement();
|
804 |
+
this.tank.update(this.mouse.x, this.mouse.y);
|
805 |
+
|
806 |
+
const tankPosition = this.tank.getPosition();
|
807 |
+
|
808 |
+
// ํ๋ฉด์ ๋ณด์ด๋ ์ ๋ง ์
๋ฐ์ดํธ
|
809 |
+
this.enemies.forEach(enemy => {
|
810 |
+
if (!enemy.mesh || !enemy.isLoaded) return;
|
811 |
|
812 |
+
const distance = enemy.mesh.position.distanceTo(tankPosition);
|
813 |
+
if (distance > 200) return; // ๋จผ ์ ์ ์
๋ฐ์ดํธ ์คํต
|
814 |
+
|
815 |
+
enemy.update(tankPosition);
|
816 |
+
if (distance < ENEMY_CONFIG.ATTACK_RANGE) {
|
817 |
+
enemy.shoot(tankPosition);
|
818 |
+
}
|
819 |
+
});
|
820 |
|
821 |
+
this.updateParticles();
|
822 |
+
this.checkCollisions();
|
823 |
+
this.cleanupBullets();
|
824 |
+
this.updateUI();
|
825 |
+
this.renderer.render(this.scene, this.camera);
|
826 |
+
}
|
827 |
|
828 |
updateUI() {
|
829 |
const healthBar = document.getElementById('health');
|