Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -1338,6 +1338,242 @@ update(deltaTime, playerPosition) {
|
|
| 1338 |
}
|
| 1339 |
}
|
| 1340 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1341 |
// ์ ์ ํฌ๊ธฐ ํด๋์ค - ์์ ํ ์ฌ์ค๊ณ
|
| 1342 |
class EnemyFighter {
|
| 1343 |
constructor(scene, position) {
|
|
@@ -1953,6 +2189,8 @@ class Game {
|
|
| 1953 |
|
| 1954 |
this.keys = { w: false, a: false, s: false, d: false, f: false, r: false };
|
| 1955 |
this.isStarted = false;
|
|
|
|
|
|
|
| 1956 |
|
| 1957 |
this.setupScene();
|
| 1958 |
this.setupEventListeners();
|
|
@@ -2977,6 +3215,33 @@ class Game {
|
|
| 2977 |
console.log('Impact sound error:', e);
|
| 2978 |
}
|
| 2979 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2980 |
|
| 2981 |
checkCollisions() {
|
| 2982 |
// ํ๋ ์ด์ด์ ์ ๊ธฐ์ ์ง์ ์ถฉ๋ ์ฒดํฌ (์ต์ฐ์ )
|
|
@@ -3670,5 +3935,5 @@ window.addEventListener('gameReady', () => {
|
|
| 3670 |
|
| 3671 |
document.addEventListener('DOMContentLoaded', () => {
|
| 3672 |
console.log('์ ํฌ๊ธฐ ์๋ฎฌ๋ ์ดํฐ ์ด๊ธฐํ ์ค...');
|
| 3673 |
-
|
| 3674 |
});
|
|
|
|
| 1338 |
}
|
| 1339 |
}
|
| 1340 |
|
| 1341 |
+
// ์ ๊ธฐ์ฉ AIM-9 ๋ฏธ์ฌ์ผ ํด๋์ค (์ฌ๊ธฐ์ ์ถ๊ฐ!)
|
| 1342 |
+
class EnemyAIM9Missile {
|
| 1343 |
+
constructor(scene, position, target, rotation) {
|
| 1344 |
+
this.scene = scene;
|
| 1345 |
+
this.position = position.clone();
|
| 1346 |
+
this.target = target;
|
| 1347 |
+
this.rotation = rotation.clone();
|
| 1348 |
+
this.speed = 1028.8; // 2000kt๋ฅผ m/s๋ก ๋ณํ
|
| 1349 |
+
this.mesh = null;
|
| 1350 |
+
this.isLoaded = false;
|
| 1351 |
+
this.lifeTime = 20; // 20์ด
|
| 1352 |
+
this.turnRate = 4.0; // ํ์ ์จ
|
| 1353 |
+
this.startPosition = position.clone();
|
| 1354 |
+
|
| 1355 |
+
// ์ถ๋ ฅ ์ฐ๊ธฐ ํํฐํด
|
| 1356 |
+
this.smokeTrail = [];
|
| 1357 |
+
this.smokeEmitTime = 0;
|
| 1358 |
+
|
| 1359 |
+
// ๋ฏธ์ฌ์ผ ๋ฐ์ฌ ๋ฐฉํฅ ์ค์
|
| 1360 |
+
const quaternion = new THREE.Quaternion();
|
| 1361 |
+
const pitchQuat = new THREE.Quaternion();
|
| 1362 |
+
const yawQuat = new THREE.Quaternion();
|
| 1363 |
+
const rollQuat = new THREE.Quaternion();
|
| 1364 |
+
|
| 1365 |
+
pitchQuat.setFromAxisAngle(new THREE.Vector3(1, 0, 0), this.rotation.x);
|
| 1366 |
+
yawQuat.setFromAxisAngle(new THREE.Vector3(0, 1, 0), this.rotation.y);
|
| 1367 |
+
rollQuat.setFromAxisAngle(new THREE.Vector3(0, 0, 1), this.rotation.z);
|
| 1368 |
+
|
| 1369 |
+
quaternion.multiply(rollQuat);
|
| 1370 |
+
quaternion.multiply(pitchQuat);
|
| 1371 |
+
quaternion.multiply(yawQuat);
|
| 1372 |
+
|
| 1373 |
+
const initialDirection = new THREE.Vector3(0, 0, 1);
|
| 1374 |
+
initialDirection.applyQuaternion(quaternion);
|
| 1375 |
+
this.velocity = initialDirection.multiplyScalar(this.speed);
|
| 1376 |
+
|
| 1377 |
+
this.createMissile();
|
| 1378 |
+
}
|
| 1379 |
+
|
| 1380 |
+
createMissile() {
|
| 1381 |
+
// ํด๋ฐฑ ๋ฏธ์ฌ์ผ ๋ชจ๋ธ
|
| 1382 |
+
const group = new THREE.Group();
|
| 1383 |
+
|
| 1384 |
+
// ๋ฏธ์ฌ์ผ ๋ณธ์ฒด
|
| 1385 |
+
const bodyGeometry = new THREE.CylinderGeometry(0.3, 0.4, 4, 8);
|
| 1386 |
+
const bodyMaterial = new THREE.MeshLambertMaterial({ color: 0x808080 });
|
| 1387 |
+
const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
|
| 1388 |
+
body.rotation.x = Math.PI / 2;
|
| 1389 |
+
group.add(body);
|
| 1390 |
+
|
| 1391 |
+
// ํ๋
|
| 1392 |
+
const noseGeometry = new THREE.ConeGeometry(0.3, 1, 8);
|
| 1393 |
+
const noseMaterial = new THREE.MeshLambertMaterial({ color: 0x404040 });
|
| 1394 |
+
const nose = new THREE.Mesh(noseGeometry, noseMaterial);
|
| 1395 |
+
nose.position.z = 2.5;
|
| 1396 |
+
nose.rotation.x = -Math.PI / 2;
|
| 1397 |
+
group.add(nose);
|
| 1398 |
+
|
| 1399 |
+
// ๋ ๊ฐ
|
| 1400 |
+
const finGeometry = new THREE.BoxGeometry(2, 0.1, 0.5);
|
| 1401 |
+
const finMaterial = new THREE.MeshLambertMaterial({ color: 0x606060 });
|
| 1402 |
+
|
| 1403 |
+
for (let i = 0; i < 4; i++) {
|
| 1404 |
+
const fin = new THREE.Mesh(finGeometry, finMaterial);
|
| 1405 |
+
fin.position.z = -1.5;
|
| 1406 |
+
fin.rotation.z = (Math.PI / 2) * i;
|
| 1407 |
+
group.add(fin);
|
| 1408 |
+
}
|
| 1409 |
+
|
| 1410 |
+
// ๋ถ๊ฝ ํจ๊ณผ
|
| 1411 |
+
const flameGeometry = new THREE.ConeGeometry(0.4, 1.5, 8);
|
| 1412 |
+
const flameMaterial = new THREE.MeshBasicMaterial({
|
| 1413 |
+
color: 0xff4400,
|
| 1414 |
+
transparent: true,
|
| 1415 |
+
opacity: 0.8
|
| 1416 |
+
});
|
| 1417 |
+
const flame = new THREE.Mesh(flameGeometry, flameMaterial);
|
| 1418 |
+
flame.position.z = -2.5;
|
| 1419 |
+
flame.rotation.x = Math.PI / 2;
|
| 1420 |
+
group.add(flame);
|
| 1421 |
+
|
| 1422 |
+
this.mesh = group;
|
| 1423 |
+
this.mesh.scale.set(2.25, 2.25, 2.25);
|
| 1424 |
+
this.mesh.position.copy(this.position);
|
| 1425 |
+
this.scene.add(this.mesh);
|
| 1426 |
+
this.isLoaded = true;
|
| 1427 |
+
}
|
| 1428 |
+
|
| 1429 |
+
update(deltaTime, enemyPosition) {
|
| 1430 |
+
if (!this.mesh || !this.target || !this.target.position) {
|
| 1431 |
+
this.destroy();
|
| 1432 |
+
return 'expired';
|
| 1433 |
+
}
|
| 1434 |
+
|
| 1435 |
+
this.lifeTime -= deltaTime;
|
| 1436 |
+
if (this.lifeTime <= 0) {
|
| 1437 |
+
this.destroy();
|
| 1438 |
+
return 'expired';
|
| 1439 |
+
}
|
| 1440 |
+
|
| 1441 |
+
// ํ๊ฒ ์ถ์
|
| 1442 |
+
const toTarget = this.target.position.clone().sub(this.position);
|
| 1443 |
+
const distance = toTarget.length();
|
| 1444 |
+
|
| 1445 |
+
// ๋ช
์ค ์ฒดํฌ
|
| 1446 |
+
if (distance < 50) {
|
| 1447 |
+
// ๋ช
์ค!
|
| 1448 |
+
console.log('Enemy AIM-9 missile hit player!');
|
| 1449 |
+
this.onHit();
|
| 1450 |
+
return 'hit';
|
| 1451 |
+
}
|
| 1452 |
+
|
| 1453 |
+
// ์ถ์ ์๊ณ ๋ฆฌ์ฆ
|
| 1454 |
+
toTarget.normalize();
|
| 1455 |
+
|
| 1456 |
+
// ํ์ฌ ๋ฐฉํฅ
|
| 1457 |
+
const currentDirection = this.velocity.clone().normalize();
|
| 1458 |
+
|
| 1459 |
+
// ์๋ก์ด ๋ฐฉํฅ์ผ๋ก ๋ถ๋๋ฝ๊ฒ ์ ํ
|
| 1460 |
+
const turnSpeed = this.turnRate * deltaTime;
|
| 1461 |
+
const newDirection = currentDirection.lerp(toTarget, turnSpeed);
|
| 1462 |
+
newDirection.normalize();
|
| 1463 |
+
|
| 1464 |
+
// ์๋ ์
๋ฐ์ดํธ
|
| 1465 |
+
this.velocity = newDirection.multiplyScalar(this.speed);
|
| 1466 |
+
|
| 1467 |
+
// ์์น ์
๋ฐ์ดํธ
|
| 1468 |
+
this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
|
| 1469 |
+
this.mesh.position.copy(this.position);
|
| 1470 |
+
|
| 1471 |
+
// ๋ฏธ์ฌ์ผ ํ์
|
| 1472 |
+
this.mesh.lookAt(this.target.position);
|
| 1473 |
+
|
| 1474 |
+
// ์ถ๋ ฅ ์ฐ๊ธฐ ์์ฑ
|
| 1475 |
+
this.smokeEmitTime += deltaTime;
|
| 1476 |
+
if (this.smokeEmitTime >= 0.02) {
|
| 1477 |
+
this.smokeEmitTime = 0;
|
| 1478 |
+
this.createSmokeParticle();
|
| 1479 |
+
}
|
| 1480 |
+
|
| 1481 |
+
// ์ฐ๊ธฐ ํํฐํด ์
๋ฐ์ดํธ
|
| 1482 |
+
for (let i = this.smokeTrail.length - 1; i >= 0; i--) {
|
| 1483 |
+
const smoke = this.smokeTrail[i];
|
| 1484 |
+
smoke.life -= deltaTime;
|
| 1485 |
+
|
| 1486 |
+
if (smoke.life <= 0) {
|
| 1487 |
+
this.scene.remove(smoke.mesh);
|
| 1488 |
+
this.smokeTrail.splice(i, 1);
|
| 1489 |
+
} else {
|
| 1490 |
+
// ์ฐ๊ธฐ ํ์ฐ ๋ฐ ํ์ด๋
|
| 1491 |
+
smoke.mesh.scale.multiplyScalar(1.02);
|
| 1492 |
+
smoke.mesh.material.opacity = smoke.life / 3.0;
|
| 1493 |
+
|
| 1494 |
+
// ์ฝ๊ฐ์ ์์น ํจ๊ณผ
|
| 1495 |
+
smoke.mesh.position.y += deltaTime * 2;
|
| 1496 |
+
}
|
| 1497 |
+
}
|
| 1498 |
+
|
| 1499 |
+
// ์ง๋ฉด ์ถฉ๋
|
| 1500 |
+
if (this.position.y <= 0) {
|
| 1501 |
+
this.destroy();
|
| 1502 |
+
return 'expired';
|
| 1503 |
+
}
|
| 1504 |
+
|
| 1505 |
+
return 'flying';
|
| 1506 |
+
}
|
| 1507 |
+
|
| 1508 |
+
createSmokeParticle() {
|
| 1509 |
+
// ๋ฏธ์ฌ์ผ ๋ค์ชฝ ์์น ๊ณ์ฐ
|
| 1510 |
+
const backward = this.velocity.clone().normalize().multiplyScalar(-3);
|
| 1511 |
+
const smokePos = this.position.clone().add(backward);
|
| 1512 |
+
|
| 1513 |
+
// ํ์ ์ฐ๊ธฐ ํํฐํด ์์ฑ
|
| 1514 |
+
const smokeGeometry = new THREE.SphereGeometry(
|
| 1515 |
+
1 + Math.random() * 2.5,
|
| 1516 |
+
6,
|
| 1517 |
+
6
|
| 1518 |
+
);
|
| 1519 |
+
const smokeMaterial = new THREE.MeshBasicMaterial({
|
| 1520 |
+
color: 0xffffff,
|
| 1521 |
+
transparent: true,
|
| 1522 |
+
opacity: 0.8
|
| 1523 |
+
});
|
| 1524 |
+
|
| 1525 |
+
const smoke = new THREE.Mesh(smokeGeometry, smokeMaterial);
|
| 1526 |
+
smoke.position.copy(smokePos);
|
| 1527 |
+
|
| 1528 |
+
// ์ฝ๊ฐ์ ๋๋ค ์คํ์
|
| 1529 |
+
smoke.position.x += (Math.random() - 0.5) * 1;
|
| 1530 |
+
smoke.position.y += (Math.random() - 0.5) * 1;
|
| 1531 |
+
smoke.position.z += (Math.random() - 0.5) * 1;
|
| 1532 |
+
|
| 1533 |
+
this.scene.add(smoke);
|
| 1534 |
+
|
| 1535 |
+
this.smokeTrail.push({
|
| 1536 |
+
mesh: smoke,
|
| 1537 |
+
life: 3.0
|
| 1538 |
+
});
|
| 1539 |
+
|
| 1540 |
+
// ์ฐ๊ธฐ ํํฐํด ์ ํ
|
| 1541 |
+
if (this.smokeTrail.length > 150) {
|
| 1542 |
+
const oldSmoke = this.smokeTrail.shift();
|
| 1543 |
+
this.scene.remove(oldSmoke.mesh);
|
| 1544 |
+
}
|
| 1545 |
+
}
|
| 1546 |
+
|
| 1547 |
+
onHit() {
|
| 1548 |
+
// ๋ช
์ค ํจ๊ณผ
|
| 1549 |
+
if (window.gameInstance) {
|
| 1550 |
+
window.gameInstance.createExplosionEffect(this.position);
|
| 1551 |
+
}
|
| 1552 |
+
|
| 1553 |
+
// ํ๋ ์ด์ด์๊ฒ ํผํด
|
| 1554 |
+
if (this.target && this.target.takeDamage) {
|
| 1555 |
+
this.target.takeDamage(GAME_CONSTANTS.AIM9_DAMAGE);
|
| 1556 |
+
}
|
| 1557 |
+
|
| 1558 |
+
this.destroy();
|
| 1559 |
+
}
|
| 1560 |
+
|
| 1561 |
+
destroy() {
|
| 1562 |
+
if (this.mesh) {
|
| 1563 |
+
this.scene.remove(this.mesh);
|
| 1564 |
+
}
|
| 1565 |
+
|
| 1566 |
+
// ์ฐ๊ธฐ ํํฐํด ์ ๋ฆฌ
|
| 1567 |
+
this.smokeTrail.forEach(smoke => {
|
| 1568 |
+
if (smoke.mesh) {
|
| 1569 |
+
this.scene.remove(smoke.mesh);
|
| 1570 |
+
}
|
| 1571 |
+
});
|
| 1572 |
+
this.smokeTrail = [];
|
| 1573 |
+
}
|
| 1574 |
+
}
|
| 1575 |
+
|
| 1576 |
+
|
| 1577 |
// ์ ์ ํฌ๊ธฐ ํด๋์ค - ์์ ํ ์ฌ์ค๊ณ
|
| 1578 |
class EnemyFighter {
|
| 1579 |
constructor(scene, position) {
|
|
|
|
| 2189 |
|
| 2190 |
this.keys = { w: false, a: false, s: false, d: false, f: false, r: false };
|
| 2191 |
this.isStarted = false;
|
| 2192 |
+
|
| 2193 |
+
window.gameInstance = this;
|
| 2194 |
|
| 2195 |
this.setupScene();
|
| 2196 |
this.setupEventListeners();
|
|
|
|
| 3215 |
console.log('Impact sound error:', e);
|
| 3216 |
}
|
| 3217 |
}
|
| 3218 |
+
|
| 3219 |
+
// ์ ์ด ํ๋ ์ด์ด๋ฅผ ๋ฝ์จ ์์ํ ๋
|
| 3220 |
+
onEnemyLockStart(enemy) {
|
| 3221 |
+
console.log('Warning: Enemy locking on!');
|
| 3222 |
+
// ์ฌ๊ธฐ์ ๋ฝ์จ ๊ฒฝ๊ณ UI๋ ์ฌ์ด๋ ์ถ๊ฐ ๊ฐ๋ฅ
|
| 3223 |
+
}
|
| 3224 |
+
|
| 3225 |
+
// ์ ์ด ๋ฝ์จ์ ์์์ ๋
|
| 3226 |
+
onEnemyLockLost(enemy) {
|
| 3227 |
+
console.log('Enemy lock lost');
|
| 3228 |
+
// ๋ฝ์จ ๊ฒฝ๊ณ ํด์
|
| 3229 |
+
}
|
| 3230 |
+
|
| 3231 |
+
// ์ ์ด ๋ฏธ์ฌ์ผ์ ๋ฐ์ฌํ์ ๋
|
| 3232 |
+
onEnemyMissileLaunch(enemy, missile) {
|
| 3233 |
+
console.log('Warning: Missile launched!');
|
| 3234 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ์ ์ฌ์
|
| 3235 |
+
try {
|
| 3236 |
+
const warningSound = new Audio('sounds/missilewarning.ogg');
|
| 3237 |
+
warningSound.volume = 0.8;
|
| 3238 |
+
warningSound.play().catch(e => {
|
| 3239 |
+
console.log('Missile warning sound not found');
|
| 3240 |
+
});
|
| 3241 |
+
} catch (e) {}
|
| 3242 |
+
}
|
| 3243 |
+
|
| 3244 |
+
|
| 3245 |
|
| 3246 |
checkCollisions() {
|
| 3247 |
// ํ๋ ์ด์ด์ ์ ๊ธฐ์ ์ง์ ์ถฉ๋ ์ฒดํฌ (์ต์ฐ์ )
|
|
|
|
| 3935 |
|
| 3936 |
document.addEventListener('DOMContentLoaded', () => {
|
| 3937 |
console.log('์ ํฌ๊ธฐ ์๋ฎฌ๋ ์ดํฐ ์ด๊ธฐํ ์ค...');
|
| 3938 |
+
const game = new Game(); // window.gameInstance = ์ ๊ฑฐ
|
| 3939 |
});
|