Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -32,69 +32,91 @@ class TankPlayer {
|
|
| 32 |
this.turretGroup = new THREE.Group();
|
| 33 |
this.health = MAX_HEALTH;
|
| 34 |
this.isLoaded = false;
|
| 35 |
-
this.ammo = 1;
|
| 36 |
-
this.maxAmmo = 1;
|
| 37 |
-
this.isReloading = false;
|
| 38 |
-
this.reloadTime = 3000;
|
| 39 |
this.lastShootTime = 0;
|
| 40 |
this.bullets = [];
|
| 41 |
this.obstacles = [];
|
| 42 |
this.scene = new THREE.Scene();
|
| 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 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
transparent: true,
|
| 53 |
-
opacity: 1
|
| 54 |
-
});
|
| 55 |
-
const flash = new THREE.Mesh(flashGeometry, flashMaterial);
|
| 56 |
-
flash.position.copy(position);
|
| 57 |
-
scene.add(flash);
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
//
|
| 65 |
-
const
|
| 66 |
-
const
|
| 67 |
-
color:
|
| 68 |
transparent: true,
|
| 69 |
opacity: 1
|
| 70 |
});
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
const elevation = Math.random() * Math.PI - Math.PI / 2;
|
| 79 |
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
mesh: particle,
|
| 93 |
-
velocity: particle.velocity,
|
| 94 |
-
gravity: particle.gravity,
|
| 95 |
-
life: particle.life,
|
| 96 |
-
fadeRate: particle.fadeRate
|
| 97 |
-
});
|
| 98 |
}
|
| 99 |
|
| 100 |
// νλ° λ§ μ΄ννΈ
|
|
@@ -1491,6 +1513,11 @@ class Game {
|
|
| 1491 |
this.enemyLabels = new Map(); // μ λΌλ²¨μ μΆμ νκΈ° μν Map μΆκ°
|
| 1492 |
this.raycaster = new THREE.Raycaster();
|
| 1493 |
this.crosshair = document.getElementById('crosshair');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1494 |
document.getElementById('gameContainer').appendChild(this.renderer.domElement);
|
| 1495 |
|
| 1496 |
|
|
@@ -2600,49 +2627,59 @@ updateCrosshair() {
|
|
| 2600 |
}
|
| 2601 |
|
| 2602 |
animate() {
|
| 2603 |
-
|
| 2604 |
-
|
| 2605 |
-
|
| 2606 |
-
|
| 2607 |
-
|
| 2608 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2609 |
|
| 2610 |
-
|
| 2611 |
-
|
|
|
|
| 2612 |
if (!this.isStarted) {
|
| 2613 |
this.renderer.render(this.scene, this.camera);
|
|
|
|
|
|
|
| 2614 |
return;
|
| 2615 |
}
|
| 2616 |
|
| 2617 |
-
|
| 2618 |
-
|
| 2619 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2620 |
|
| 2621 |
-
|
| 2622 |
-
|
| 2623 |
-
this.tank.update(this.mouse.x, this.mouse.y, this.scene);
|
| 2624 |
-
|
| 2625 |
-
const tankPosition = this.tank.getPosition();
|
| 2626 |
-
this.enemies.forEach(enemy => {
|
| 2627 |
-
enemy.update(tankPosition);
|
| 2628 |
-
|
| 2629 |
-
if (enemy.isLoaded && enemy.mesh.position.distanceTo(tankPosition) < ENEMY_CONFIG.ATTACK_RANGE) {
|
| 2630 |
-
enemy.shoot(tankPosition);
|
| 2631 |
-
}
|
| 2632 |
-
});
|
| 2633 |
-
this.updateEnemyLabels(); // μ λΌλ²¨ μ
λ°μ΄νΈ μΆκ°
|
| 2634 |
-
this.updateParticles();
|
| 2635 |
-
this.checkCollisions();
|
| 2636 |
-
this.updateUI();
|
| 2637 |
-
this.updateRadar(); // λ μ΄λ μ
λ°μ΄νΈ μΆκ°
|
| 2638 |
-
// ν¬λ‘μ€ν€μ΄ μ
λ°μ΄νΈ μΆκ°
|
| 2639 |
-
this.updateCrosshair();
|
| 2640 |
-
}
|
| 2641 |
-
|
| 2642 |
-
this.renderer.render(this.scene, this.camera);
|
| 2643 |
-
}
|
| 2644 |
-
}
|
| 2645 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2646 |
// Start game
|
| 2647 |
window.startGame = function() {
|
| 2648 |
document.getElementById('startScreen').style.display = 'none';
|
|
|
|
| 32 |
this.turretGroup = new THREE.Group();
|
| 33 |
this.health = MAX_HEALTH;
|
| 34 |
this.isLoaded = false;
|
| 35 |
+
this.ammo = 1;
|
| 36 |
+
this.maxAmmo = 1;
|
| 37 |
+
this.isReloading = false;
|
| 38 |
+
this.reloadTime = 3000;
|
| 39 |
this.lastShootTime = 0;
|
| 40 |
this.bullets = [];
|
| 41 |
this.obstacles = [];
|
| 42 |
this.scene = new THREE.Scene();
|
| 43 |
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
| 44 |
this.renderer = new THREE.WebGLRenderer({ antialias: true });
|
| 45 |
+
|
| 46 |
+
// FPS μ νμ μν μμ± μΆκ°
|
| 47 |
+
this.fps = 60;
|
| 48 |
+
this.frameInterval = 1000 / this.fps;
|
| 49 |
+
this.lastFrameTime = performance.now();
|
| 50 |
+
this.deltaTime = 0;
|
| 51 |
+
|
| 52 |
+
// λ λλ¬ FPS μ ν μ€μ
|
| 53 |
+
this.renderer.setAnimationLoop(null); // κΈ°λ³Έ μ λλ©μ΄μ
루ν λΉνμ±ν
|
| 54 |
}
|
| 55 |
+
|
| 56 |
createExplosionEffect(scene, position) {
|
| 57 |
+
// νμ¬ μκ° νμΈ
|
| 58 |
+
const currentTime = performance.now();
|
| 59 |
+
this.deltaTime += currentTime - this.lastFrameTime;
|
| 60 |
+
this.lastFrameTime = currentTime;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
+
// FPS μ ν 체ν¬
|
| 63 |
+
if (this.deltaTime < this.frameInterval) {
|
| 64 |
+
return;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
// νλ° μ€μ¬ νλμ
|
| 68 |
+
const flashGeometry = new THREE.SphereGeometry(3);
|
| 69 |
+
const flashMaterial = new THREE.MeshBasicMaterial({
|
| 70 |
+
color: 0xffff00,
|
| 71 |
transparent: true,
|
| 72 |
opacity: 1
|
| 73 |
});
|
| 74 |
+
const flash = new THREE.Mesh(flashGeometry, flashMaterial);
|
| 75 |
+
flash.position.copy(position);
|
| 76 |
+
scene.add(flash);
|
| 77 |
+
|
| 78 |
+
// νλ° νν°ν΄ (FPSμ λ§μΆ° μ
λ°μ΄νΈ)
|
| 79 |
+
const particleCount = Math.floor(30 * (this.deltaTime / this.frameInterval));
|
| 80 |
+
for (let i = 0; i < particleCount; i++) {
|
| 81 |
+
const size = Math.random() * 0.5 + 0.3;
|
| 82 |
+
const geometry = new THREE.SphereGeometry(size);
|
| 83 |
+
|
| 84 |
+
const colors = [0xff4500, 0xff8c00, 0xff0000, 0xffd700];
|
| 85 |
+
const material = new THREE.MeshBasicMaterial({
|
| 86 |
+
color: colors[Math.floor(Math.random() * colors.length)],
|
| 87 |
+
transparent: true,
|
| 88 |
+
opacity: 1
|
| 89 |
+
});
|
| 90 |
+
|
| 91 |
+
const particle = new THREE.Mesh(geometry, material);
|
| 92 |
+
particle.position.copy(position);
|
| 93 |
|
| 94 |
+
const speed = Math.random() * 0.5 + 0.3;
|
| 95 |
+
const angle = Math.random() * Math.PI * 2;
|
| 96 |
+
const elevation = Math.random() * Math.PI - Math.PI / 2;
|
|
|
|
| 97 |
|
| 98 |
+
particle.velocity = new THREE.Vector3(
|
| 99 |
+
Math.cos(angle) * Math.cos(elevation) * speed,
|
| 100 |
+
Math.sin(elevation) * speed,
|
| 101 |
+
Math.sin(angle) * Math.cos(elevation) * speed
|
| 102 |
+
);
|
| 103 |
|
| 104 |
+
particle.gravity = -0.015;
|
| 105 |
+
particle.life = Math.random() * 30 + 30;
|
| 106 |
+
particle.fadeRate = 0.97;
|
| 107 |
+
|
| 108 |
+
scene.add(particle);
|
| 109 |
+
window.gameInstance.particles.push({
|
| 110 |
+
mesh: particle,
|
| 111 |
+
velocity: particle.velocity,
|
| 112 |
+
gravity: particle.gravity,
|
| 113 |
+
life: particle.life,
|
| 114 |
+
fadeRate: particle.fadeRate
|
| 115 |
+
});
|
| 116 |
+
}
|
| 117 |
|
| 118 |
+
// deltaTime 리μ
|
| 119 |
+
this.deltaTime = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
}
|
| 121 |
|
| 122 |
// νλ° λ§ μ΄ννΈ
|
|
|
|
| 1513 |
this.enemyLabels = new Map(); // μ λΌλ²¨μ μΆμ νκΈ° μν Map μΆκ°
|
| 1514 |
this.raycaster = new THREE.Raycaster();
|
| 1515 |
this.crosshair = document.getElementById('crosshair');
|
| 1516 |
+
// FPS κ΄λ ¨ μμ± μΆκ°
|
| 1517 |
+
this.fps = 60;
|
| 1518 |
+
this.frameInterval = 1000 / this.fps;
|
| 1519 |
+
this.lastFrameTime = performance.now();
|
| 1520 |
+
this.deltaTime = 0;
|
| 1521 |
document.getElementById('gameContainer').appendChild(this.renderer.domElement);
|
| 1522 |
|
| 1523 |
|
|
|
|
| 2627 |
}
|
| 2628 |
|
| 2629 |
animate() {
|
| 2630 |
+
if (this.isGameOver) {
|
| 2631 |
+
if (this.animationFrameId) {
|
| 2632 |
+
cancelAnimationFrame(this.animationFrameId);
|
| 2633 |
+
}
|
| 2634 |
+
return;
|
| 2635 |
+
}
|
| 2636 |
+
|
| 2637 |
+
const currentTime = performance.now();
|
| 2638 |
+
this.deltaTime += currentTime - this.lastFrameTime;
|
| 2639 |
+
this.lastFrameTime = currentTime;
|
| 2640 |
|
| 2641 |
+
// FPS μ νμ μν νλ μ μ€ν΅
|
| 2642 |
+
if (this.deltaTime >= this.frameInterval) {
|
| 2643 |
+
// κ²μμ΄ μμλμ§ μμμΌλ©΄ λ λλ§λ§ μν
|
| 2644 |
if (!this.isStarted) {
|
| 2645 |
this.renderer.render(this.scene, this.camera);
|
| 2646 |
+
this.deltaTime = Math.min(this.deltaTime - this.frameInterval, this.frameInterval);
|
| 2647 |
+
this.animationFrameId = requestAnimationFrame(() => this.animate());
|
| 2648 |
return;
|
| 2649 |
}
|
| 2650 |
|
| 2651 |
+
// νλ μ μ
λ°μ΄νΈ
|
| 2652 |
+
if (!this.isLoading) {
|
| 2653 |
+
this.handleMovement();
|
| 2654 |
+
this.tank.update(this.mouse.x, this.mouse.y, this.scene);
|
| 2655 |
+
|
| 2656 |
+
const tankPosition = this.tank.getPosition();
|
| 2657 |
+
this.enemies.forEach(enemy => {
|
| 2658 |
+
enemy.update(tankPosition);
|
| 2659 |
+
|
| 2660 |
+
if (enemy.isLoaded && enemy.mesh.position.distanceTo(tankPosition) < ENEMY_CONFIG.ATTACK_RANGE) {
|
| 2661 |
+
enemy.shoot(tankPosition);
|
| 2662 |
+
}
|
| 2663 |
+
});
|
| 2664 |
+
|
| 2665 |
+
this.updateEnemyLabels();
|
| 2666 |
+
this.updateParticles();
|
| 2667 |
+
this.checkCollisions();
|
| 2668 |
+
this.updateUI();
|
| 2669 |
+
this.updateRadar();
|
| 2670 |
+
this.updateCrosshair();
|
| 2671 |
+
}
|
| 2672 |
|
| 2673 |
+
// λ λλ§
|
| 2674 |
+
this.renderer.render(this.scene, this.camera);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2675 |
|
| 2676 |
+
// deltaTime 리μ
(λ¨μ μκ° μ μ§)
|
| 2677 |
+
this.deltaTime = Math.min(this.deltaTime - this.frameInterval, this.frameInterval);
|
| 2678 |
+
}
|
| 2679 |
+
|
| 2680 |
+
// λ€μ νλ μ μμ²
|
| 2681 |
+
this.animationFrameId = requestAnimationFrame(() => this.animate());
|
| 2682 |
+
}
|
| 2683 |
// Start game
|
| 2684 |
window.startGame = function() {
|
| 2685 |
document.getElementById('startScreen').style.display = 'none';
|