Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -18,7 +18,9 @@ const GAME_CONSTANTS = {
|
|
| 18 |
MAX_G_FORCE: 12.0,
|
| 19 |
ENEMY_COUNT: 4,
|
| 20 |
MISSILE_COUNT: 6,
|
| 21 |
-
AMMO_COUNT:
|
|
|
|
|
|
|
| 22 |
};
|
| 23 |
|
| 24 |
// μ ν¬κΈ° ν΄λμ€
|
|
@@ -38,7 +40,7 @@ class Fighter {
|
|
| 38 |
this.speed = 350; // μ΄κΈ° μλ 350kt
|
| 39 |
this.altitude = 2000;
|
| 40 |
this.gForce = 1.0;
|
| 41 |
-
this.health =
|
| 42 |
|
| 43 |
// μ‘°μ’
μ
λ ₯ μμ€ν
|
| 44 |
this.pitchInput = 0;
|
|
@@ -59,6 +61,7 @@ class Fighter {
|
|
| 59 |
this.ammo = GAME_CONSTANTS.AMMO_COUNT;
|
| 60 |
this.bullets = [];
|
| 61 |
this.lastShootTime = 0;
|
|
|
|
| 62 |
|
| 63 |
// μ€ν¨ νμΆμ μν Fν€ μν
|
| 64 |
this.escapeKeyPressed = false;
|
|
@@ -276,32 +279,32 @@ class Fighter {
|
|
| 276 |
}
|
| 277 |
|
| 278 |
updateControls(keys, deltaTime) {
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
|
|
|
| 293 |
}
|
| 294 |
-
}
|
| 295 |
|
| 296 |
updatePhysics(deltaTime) {
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
|
| 306 |
// λ‘€ μλ λ³΅κ· μμ€ν
|
| 307 |
if (Math.abs(this.targetYaw - this.rotation.y) < 0.05) {
|
|
@@ -579,10 +582,9 @@ class Fighter {
|
|
| 579 |
}
|
| 580 |
|
| 581 |
shoot(scene) {
|
| 582 |
-
|
| 583 |
-
if (
|
| 584 |
|
| 585 |
-
this.lastShootTime = currentTime;
|
| 586 |
this.ammo--;
|
| 587 |
|
| 588 |
const bulletGeometry = new THREE.SphereGeometry(0.2);
|
|
@@ -593,10 +595,14 @@ class Fighter {
|
|
| 593 |
});
|
| 594 |
const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
|
| 595 |
|
|
|
|
| 596 |
const muzzleOffset = new THREE.Vector3(0, 0, 8);
|
| 597 |
muzzleOffset.applyEuler(this.rotation);
|
| 598 |
bullet.position.copy(this.position).add(muzzleOffset);
|
| 599 |
|
|
|
|
|
|
|
|
|
|
| 600 |
const bulletSpeed = 1000;
|
| 601 |
const direction = new THREE.Vector3(0, 0, 1);
|
| 602 |
direction.applyEuler(this.rotation);
|
|
@@ -605,8 +611,9 @@ class Fighter {
|
|
| 605 |
scene.add(bullet);
|
| 606 |
this.bullets.push(bullet);
|
| 607 |
|
|
|
|
| 608 |
try {
|
| 609 |
-
const audio = new Audio('sounds/
|
| 610 |
if (audio) {
|
| 611 |
audio.volume = 0.3;
|
| 612 |
audio.play().catch(e => console.log('Gunfire sound failed to play'));
|
|
@@ -619,7 +626,8 @@ class Fighter {
|
|
| 619 |
const bullet = this.bullets[i];
|
| 620 |
bullet.position.add(bullet.velocity.clone().multiplyScalar(deltaTime));
|
| 621 |
|
| 622 |
-
|
|
|
|
| 623 |
bullet.position.y < 0 ||
|
| 624 |
bullet.position.y > GAME_CONSTANTS.MAX_ALTITUDE + 500) {
|
| 625 |
scene.remove(bullet);
|
|
@@ -661,7 +669,7 @@ class EnemyFighter {
|
|
| 661 |
this.position = position.clone();
|
| 662 |
this.velocity = new THREE.Vector3(0, 0, 120);
|
| 663 |
this.rotation = new THREE.Euler(0, 0, 0);
|
| 664 |
-
this.health =
|
| 665 |
this.speed = 120;
|
| 666 |
this.bullets = [];
|
| 667 |
this.lastShootTime = 0;
|
|
@@ -857,6 +865,7 @@ class Game {
|
|
| 857 |
this.lastTime = performance.now();
|
| 858 |
this.gameTimer = null;
|
| 859 |
this.animationFrameId = null;
|
|
|
|
| 860 |
|
| 861 |
this.bgm = null;
|
| 862 |
this.bgmPlaying = false;
|
|
@@ -1063,6 +1072,22 @@ class Game {
|
|
| 1063 |
this.fighter.updateMouseInput(deltaX, deltaY);
|
| 1064 |
});
|
| 1065 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1066 |
window.addEventListener('resize', () => {
|
| 1067 |
this.camera.aspect = window.innerWidth / window.innerHeight;
|
| 1068 |
this.camera.updateProjectionMatrix();
|
|
@@ -1142,9 +1167,19 @@ class Game {
|
|
| 1142 |
const ammoElement = document.getElementById('ammoDisplay');
|
| 1143 |
const gameStatsElement = document.getElementById('gameStats');
|
| 1144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1145 |
if (scoreElement) scoreElement.textContent = `Score: ${this.score}`;
|
| 1146 |
if (timeElement) timeElement.textContent = `Time: ${this.gameTime}s`;
|
| 1147 |
-
if (healthElement) healthElement.style.width = `${this.fighter.health}%`;
|
| 1148 |
if (ammoElement) ammoElement.textContent = `AMMO: ${this.fighter.ammo}`;
|
| 1149 |
|
| 1150 |
if (gameStatsElement) {
|
|
@@ -1287,242 +1322,242 @@ class Game {
|
|
| 1287 |
}
|
| 1288 |
|
| 1289 |
// Game ν΄λμ€μ updateWarnings λ©μλ μμ
|
| 1290 |
-
updateWarnings() {
|
| 1291 |
-
|
| 1292 |
-
|
| 1293 |
-
|
| 1294 |
-
|
| 1295 |
-
// μ€ν¨ νμΆ κ²½κ³ μ κ±°
|
| 1296 |
-
const existingStallWarnings = document.querySelectorAll('.stall-escape-warning');
|
| 1297 |
-
existingStallWarnings.forEach(w => w.remove());
|
| 1298 |
-
|
| 1299 |
-
// κ³ λ κ²½κ³ μΈκ³½ ν¨κ³Ό
|
| 1300 |
-
let altitudeEdgeEffect = document.getElementById('altitudeEdgeEffect');
|
| 1301 |
-
if (this.fighter.altitude < 500) {
|
| 1302 |
-
if (!altitudeEdgeEffect) {
|
| 1303 |
-
altitudeEdgeEffect = document.createElement('div');
|
| 1304 |
-
altitudeEdgeEffect.id = 'altitudeEdgeEffect';
|
| 1305 |
-
document.body.appendChild(altitudeEdgeEffect);
|
| 1306 |
-
}
|
| 1307 |
-
|
| 1308 |
-
let edgeIntensity;
|
| 1309 |
-
if (this.fighter.altitude < 250) {
|
| 1310 |
-
// PULL UP κ²½κ³ - κ°ν λΆμ ν¨κ³Ό
|
| 1311 |
-
edgeIntensity = 0.6;
|
| 1312 |
-
altitudeEdgeEffect.style.cssText = `
|
| 1313 |
-
position: fixed;
|
| 1314 |
-
top: 0;
|
| 1315 |
-
left: 0;
|
| 1316 |
-
width: 100%;
|
| 1317 |
-
height: 100%;
|
| 1318 |
-
pointer-events: none;
|
| 1319 |
-
z-index: 1300;
|
| 1320 |
-
background: radial-gradient(ellipse at center,
|
| 1321 |
-
transparent 40%,
|
| 1322 |
-
rgba(255, 0, 0, ${edgeIntensity * 0.3}) 60%,
|
| 1323 |
-
rgba(255, 0, 0, ${edgeIntensity}) 100%);
|
| 1324 |
-
box-shadow: inset 0 0 150px rgba(255, 0, 0, ${edgeIntensity}),
|
| 1325 |
-
inset 0 0 100px rgba(255, 0, 0, ${edgeIntensity * 0.8});
|
| 1326 |
-
animation: pulse-red 0.5s infinite;
|
| 1327 |
-
`;
|
| 1328 |
-
} else {
|
| 1329 |
-
// LOW ALTITUDE κ²½κ³ - μ½ν λΆμ ν¨κ³Ό
|
| 1330 |
-
edgeIntensity = 0.3;
|
| 1331 |
-
altitudeEdgeEffect.style.cssText = `
|
| 1332 |
-
position: fixed;
|
| 1333 |
-
top: 0;
|
| 1334 |
-
left: 0;
|
| 1335 |
-
width: 100%;
|
| 1336 |
-
height: 100%;
|
| 1337 |
-
pointer-events: none;
|
| 1338 |
-
z-index: 1300;
|
| 1339 |
-
background: radial-gradient(ellipse at center,
|
| 1340 |
-
transparent 50%,
|
| 1341 |
-
rgba(255, 0, 0, ${edgeIntensity * 0.2}) 70%,
|
| 1342 |
-
rgba(255, 0, 0, ${edgeIntensity}) 100%);
|
| 1343 |
-
box-shadow: inset 0 0 100px rgba(255, 0, 0, ${edgeIntensity}),
|
| 1344 |
-
inset 0 0 50px rgba(255, 0, 0, ${edgeIntensity * 0.5});
|
| 1345 |
-
`;
|
| 1346 |
-
}
|
| 1347 |
-
} else {
|
| 1348 |
-
// κ³ λκ° μμ νλ©΄ ν¨κ³Ό μ κ±°
|
| 1349 |
-
if (altitudeEdgeEffect) {
|
| 1350 |
-
altitudeEdgeEffect.remove();
|
| 1351 |
-
}
|
| 1352 |
-
}
|
| 1353 |
-
|
| 1354 |
-
if (this.fighter.warningBlinkState) {
|
| 1355 |
-
const warningContainer = document.createElement('div');
|
| 1356 |
-
warningContainer.className = 'warning-message';
|
| 1357 |
-
warningContainer.style.cssText = `
|
| 1358 |
-
position: fixed;
|
| 1359 |
-
top: 30%;
|
| 1360 |
-
left: 50%;
|
| 1361 |
-
transform: translateX(-50%);
|
| 1362 |
-
color: #ff0000;
|
| 1363 |
-
font-size: 24px;
|
| 1364 |
-
font-weight: bold;
|
| 1365 |
-
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
|
| 1366 |
-
z-index: 1500;
|
| 1367 |
-
text-align: center;
|
| 1368 |
-
`;
|
| 1369 |
-
|
| 1370 |
-
let warningText = '';
|
| 1371 |
|
| 1372 |
-
|
| 1373 |
-
|
| 1374 |
-
|
| 1375 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1376 |
}
|
| 1377 |
|
| 1378 |
-
if (this.fighter.
|
| 1379 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1380 |
}
|
| 1381 |
|
|
|
|
| 1382 |
if (this.fighter.stallWarning) {
|
| 1383 |
-
|
| 1384 |
-
|
| 1385 |
-
|
| 1386 |
-
|
| 1387 |
-
|
| 1388 |
-
|
| 1389 |
-
|
| 1390 |
-
|
| 1391 |
-
|
| 1392 |
-
|
| 1393 |
-
|
| 1394 |
-
|
| 1395 |
-
|
| 1396 |
-
|
| 1397 |
-
|
| 1398 |
-
|
| 1399 |
-
|
| 1400 |
-
|
| 1401 |
-
|
| 1402 |
-
|
| 1403 |
-
|
| 1404 |
-
|
| 1405 |
-
|
| 1406 |
-
|
| 1407 |
-
|
| 1408 |
-
|
| 1409 |
-
|
| 1410 |
-
|
| 1411 |
-
|
| 1412 |
-
z-index: 1600;
|
| 1413 |
-
text-align: center;
|
| 1414 |
-
animation: blink 0.5s infinite;
|
| 1415 |
-
`;
|
| 1416 |
-
stallEscapeWarning.innerHTML = 'PRESS F TO ESCAPE';
|
| 1417 |
-
document.body.appendChild(stallEscapeWarning);
|
| 1418 |
-
|
| 1419 |
-
// μ λλ©μ΄μ
μ€νμΌ μΆκ°
|
| 1420 |
-
if (!document.getElementById('blinkAnimation')) {
|
| 1421 |
-
const style = document.createElement('style');
|
| 1422 |
-
style.id = 'blinkAnimation';
|
| 1423 |
-
style.innerHTML = `
|
| 1424 |
-
@keyframes blink {
|
| 1425 |
-
0%, 50% { opacity: 1; }
|
| 1426 |
-
51%, 100% { opacity: 0.3; }
|
| 1427 |
-
}
|
| 1428 |
-
@keyframes pulse-green {
|
| 1429 |
-
0%, 100% {
|
| 1430 |
-
opacity: 1;
|
| 1431 |
-
transform: translateX(-50%) scale(1);
|
| 1432 |
-
}
|
| 1433 |
-
50% {
|
| 1434 |
-
opacity: 0.8;
|
| 1435 |
-
transform: translateX(-50%) scale(1.1);
|
| 1436 |
-
}
|
| 1437 |
-
}
|
| 1438 |
-
@keyframes box-pulse {
|
| 1439 |
-
0%, 100% {
|
| 1440 |
-
background: rgba(255, 0, 0, 0.9);
|
| 1441 |
-
box-shadow: 0 0 20px rgba(255, 0, 0, 0.8),
|
| 1442 |
-
0 0 40px rgba(255, 0, 0, 0.4);
|
| 1443 |
}
|
| 1444 |
-
|
| 1445 |
-
|
| 1446 |
-
|
| 1447 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1448 |
}
|
| 1449 |
-
|
| 1450 |
-
|
| 1451 |
-
|
| 1452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1453 |
}
|
| 1454 |
-
|
| 1455 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1456 |
}
|
| 1457 |
-
|
| 1458 |
-
|
| 1459 |
-
|
| 1460 |
-
}
|
| 1461 |
-
}
|
| 1462 |
-
|
| 1463 |
-
// Over-G μμΌ ν¨κ³Ό - μμ λ λΆλΆ
|
| 1464 |
-
if (this.fighter.overG && this.fighter.overGTimer > 0) {
|
| 1465 |
-
let blurEffect = document.getElementById('overGBlurEffect');
|
| 1466 |
-
if (!blurEffect) {
|
| 1467 |
-
blurEffect = document.createElement('div');
|
| 1468 |
-
blurEffect.id = 'overGBlurEffect';
|
| 1469 |
-
document.body.appendChild(blurEffect);
|
| 1470 |
-
}
|
| 1471 |
-
|
| 1472 |
-
// Over-G μ§μ μκ°μ λ°λΌ μ μ§μ μΌλ‘ μ΄λμμ§
|
| 1473 |
-
// 0μ΄: ν¨κ³Ό μμ
|
| 1474 |
-
// 1μ΄: κ±°μ μμ ν μ΄λμμ§
|
| 1475 |
-
const darknessFactor = Math.min(this.fighter.overGTimer, 1.0); // 0~1 λ²μλ‘ μ ν
|
| 1476 |
-
|
| 1477 |
-
// μμΌ κ°μ₯μ리λΆν° μ΄λμμ§λ ν¨κ³Ό
|
| 1478 |
-
// μ€μμ μλμ μΌλ‘ λ¦κ² μ΄λμμ§
|
| 1479 |
-
const centerTransparency = Math.max(0, 1 - darknessFactor * 1.2); // μ€μ ν¬λͺ
λ
|
| 1480 |
-
const midTransparency = Math.max(0, 1 - darknessFactor * 0.8); // μ€κ° ν¬λͺ
λ
|
| 1481 |
-
const edgeOpacity = Math.min(0.95, darknessFactor * 0.95); // κ°μ₯μ리 λΆν¬λͺ
λ
|
| 1482 |
-
|
| 1483 |
-
// λΆμ μμ‘° μΆκ° (νμ‘ μν λ¬Έμ λ₯Ό μκ°ν) - μ½νλ λ²μ
|
| 1484 |
-
const redTint = Math.min(darknessFactor * 0.1, 0.1); // 0.3μμ 0.1λ‘ κ°μ
|
| 1485 |
-
|
| 1486 |
-
blurEffect.style.cssText = `
|
| 1487 |
-
position: fixed;
|
| 1488 |
-
top: 0;
|
| 1489 |
-
left: 0;
|
| 1490 |
-
width: 100%;
|
| 1491 |
-
height: 100%;
|
| 1492 |
-
background: radial-gradient(ellipse at center,
|
| 1493 |
-
rgba(${Math.floor(255 * redTint)}, 0, 0, ${1 - centerTransparency}) 0%,
|
| 1494 |
-
rgba(${Math.floor(150 * redTint)}, 0, 0, ${1 - midTransparency}) 40%,
|
| 1495 |
-
rgba(0, 0, 0, ${edgeOpacity}) 70%,
|
| 1496 |
-
rgba(0, 0, 0, ${Math.min(0.98, edgeOpacity + 0.05)}) 100%);
|
| 1497 |
-
pointer-events: none;
|
| 1498 |
-
z-index: 1400;
|
| 1499 |
-
transition: background 0.1s ease-out;
|
| 1500 |
-
`;
|
| 1501 |
-
|
| 1502 |
-
// μ¬ν Over-G μνμμ νλ©΄ νλ€λ¦Ό ν¨κ³Ό
|
| 1503 |
-
if (darknessFactor > 0.7) {
|
| 1504 |
-
const shake = (1 - Math.random() * 2) * 2;
|
| 1505 |
-
blurEffect.style.transform = `translate(${shake}px, ${shake}px)`;
|
| 1506 |
}
|
| 1507 |
|
| 1508 |
-
//
|
| 1509 |
-
|
| 1510 |
-
|
| 1511 |
-
|
| 1512 |
-
|
| 1513 |
-
|
| 1514 |
-
|
| 1515 |
-
|
| 1516 |
-
|
| 1517 |
-
|
| 1518 |
-
|
| 1519 |
-
|
| 1520 |
-
|
| 1521 |
-
|
| 1522 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1523 |
}
|
| 1524 |
}
|
| 1525 |
-
}
|
| 1526 |
|
| 1527 |
updateRadar() {
|
| 1528 |
const radar = document.getElementById('radar');
|
|
@@ -1570,7 +1605,7 @@ updateWarnings() {
|
|
| 1570 |
this.scene.remove(bullet);
|
| 1571 |
this.fighter.bullets.splice(i, 1);
|
| 1572 |
|
| 1573 |
-
if (enemy.takeDamage(
|
| 1574 |
enemy.destroy();
|
| 1575 |
this.enemies.splice(j, 1);
|
| 1576 |
this.score += 100;
|
|
@@ -1587,7 +1622,7 @@ updateWarnings() {
|
|
| 1587 |
this.scene.remove(bullet);
|
| 1588 |
enemy.bullets.splice(index, 1);
|
| 1589 |
|
| 1590 |
-
if (this.fighter.takeDamage(
|
| 1591 |
this.endGame(false);
|
| 1592 |
}
|
| 1593 |
}
|
|
@@ -1612,6 +1647,15 @@ updateWarnings() {
|
|
| 1612 |
this.fighter.updatePhysics(deltaTime);
|
| 1613 |
this.fighter.updateBullets(this.scene, deltaTime);
|
| 1614 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1615 |
if (this.isStarted) {
|
| 1616 |
this.enemies.forEach(enemy => {
|
| 1617 |
enemy.update(this.fighter.position, deltaTime);
|
|
@@ -1783,9 +1827,7 @@ document.addEventListener('click', (event) => {
|
|
| 1783 |
console.log('κ²μ μ€ ν΄λ¦ - ν¬μΈν° λ½ μ¬μμ²');
|
| 1784 |
document.body.requestPointerLock();
|
| 1785 |
}
|
| 1786 |
-
|
| 1787 |
-
window.gameInstance.fighter.shoot(window.gameInstance.scene);
|
| 1788 |
-
}
|
| 1789 |
}
|
| 1790 |
}, true);
|
| 1791 |
|
|
|
|
| 18 |
MAX_G_FORCE: 12.0,
|
| 19 |
ENEMY_COUNT: 4,
|
| 20 |
MISSILE_COUNT: 6,
|
| 21 |
+
AMMO_COUNT: 940, // 940λ°λ‘ λ³κ²½
|
| 22 |
+
BULLET_DAMAGE: 25, // λ°λΉ 25 λ°λ―Έμ§
|
| 23 |
+
MAX_HEALTH: 1000 // 체λ ₯ 1000
|
| 24 |
};
|
| 25 |
|
| 26 |
// μ ν¬κΈ° ν΄λμ€
|
|
|
|
| 40 |
this.speed = 350; // μ΄κΈ° μλ 350kt
|
| 41 |
this.altitude = 2000;
|
| 42 |
this.gForce = 1.0;
|
| 43 |
+
this.health = GAME_CONSTANTS.MAX_HEALTH; // 체λ ₯ 1000
|
| 44 |
|
| 45 |
// μ‘°μ’
μ
λ ₯ μμ€ν
|
| 46 |
this.pitchInput = 0;
|
|
|
|
| 61 |
this.ammo = GAME_CONSTANTS.AMMO_COUNT;
|
| 62 |
this.bullets = [];
|
| 63 |
this.lastShootTime = 0;
|
| 64 |
+
this.isMouseDown = false; // λ§μ°μ€ λλ¦ μν μΆμ
|
| 65 |
|
| 66 |
// μ€ν¨ νμΆμ μν Fν€ μν
|
| 67 |
this.escapeKeyPressed = false;
|
|
|
|
| 279 |
}
|
| 280 |
|
| 281 |
updateControls(keys, deltaTime) {
|
| 282 |
+
// W/S: μ€λ‘νλ§ μ μ΄ (κ°μ/κ°μ)
|
| 283 |
+
if (keys.w) {
|
| 284 |
+
this.throttle = Math.min(1.0, this.throttle + deltaTime * 0.5); // μ²μ²ν κ°μ
|
| 285 |
+
}
|
| 286 |
+
if (keys.s) {
|
| 287 |
+
this.throttle = Math.max(0.1, this.throttle - deltaTime * 0.5); // μ²μ²ν κ°μ
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
// A/D: 보쑰 μ μ μ΄ (λ¬λ) - λ°μμ± κ°μ
|
| 291 |
+
if (keys.a) {
|
| 292 |
+
this.targetYaw -= deltaTime * 1.2; // 0.4μμ 1.2λ‘ μ¦κ° (3λ°°)
|
| 293 |
+
}
|
| 294 |
+
if (keys.d) {
|
| 295 |
+
this.targetYaw += deltaTime * 1.2; // 0.4μμ 1.2λ‘ μ¦κ° (3λ°°)
|
| 296 |
+
}
|
| 297 |
}
|
|
|
|
| 298 |
|
| 299 |
updatePhysics(deltaTime) {
|
| 300 |
+
if (!this.mesh) return;
|
| 301 |
+
|
| 302 |
+
// λΆλλ¬μ΄ νμ λ³΄κ° - Yaw νμ μλ κ°μ
|
| 303 |
+
const rotationSpeed = deltaTime * 2.0;
|
| 304 |
+
const yawRotationSpeed = deltaTime * 3.0; // Yawλ λ λΉ λ₯΄κ² λ°μνλλ‘ λ³λ μ€μ
|
| 305 |
+
|
| 306 |
+
this.rotation.x = THREE.MathUtils.lerp(this.rotation.x, this.targetPitch, rotationSpeed);
|
| 307 |
+
this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetYaw, yawRotationSpeed); // κ°μ λ μλ
|
| 308 |
|
| 309 |
// λ‘€ μλ λ³΅κ· μμ€ν
|
| 310 |
if (Math.abs(this.targetYaw - this.rotation.y) < 0.05) {
|
|
|
|
| 582 |
}
|
| 583 |
|
| 584 |
shoot(scene) {
|
| 585 |
+
// νμ½μ΄ μμΌλ©΄ λ°μ¬νμ§ μμ
|
| 586 |
+
if (this.ammo <= 0) return;
|
| 587 |
|
|
|
|
| 588 |
this.ammo--;
|
| 589 |
|
| 590 |
const bulletGeometry = new THREE.SphereGeometry(0.2);
|
|
|
|
| 595 |
});
|
| 596 |
const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
|
| 597 |
|
| 598 |
+
// κΈ°μ λμμ λ°μ¬
|
| 599 |
const muzzleOffset = new THREE.Vector3(0, 0, 8);
|
| 600 |
muzzleOffset.applyEuler(this.rotation);
|
| 601 |
bullet.position.copy(this.position).add(muzzleOffset);
|
| 602 |
|
| 603 |
+
// νν μ΄κΈ° μμΉ μ μ₯
|
| 604 |
+
bullet.startPosition = bullet.position.clone();
|
| 605 |
+
|
| 606 |
const bulletSpeed = 1000;
|
| 607 |
const direction = new THREE.Vector3(0, 0, 1);
|
| 608 |
direction.applyEuler(this.rotation);
|
|
|
|
| 611 |
scene.add(bullet);
|
| 612 |
this.bullets.push(bullet);
|
| 613 |
|
| 614 |
+
// 30MM_M163.ogg μ리 μ¬μ
|
| 615 |
try {
|
| 616 |
+
const audio = new Audio('sounds/30MM_M163.ogg');
|
| 617 |
if (audio) {
|
| 618 |
audio.volume = 0.3;
|
| 619 |
audio.play().catch(e => console.log('Gunfire sound failed to play'));
|
|
|
|
| 626 |
const bullet = this.bullets[i];
|
| 627 |
bullet.position.add(bullet.velocity.clone().multiplyScalar(deltaTime));
|
| 628 |
|
| 629 |
+
// 1000m μ΄μ λ μκ°λ©΄ μ κ±°
|
| 630 |
+
if (bullet.position.distanceTo(bullet.startPosition) > 1000 ||
|
| 631 |
bullet.position.y < 0 ||
|
| 632 |
bullet.position.y > GAME_CONSTANTS.MAX_ALTITUDE + 500) {
|
| 633 |
scene.remove(bullet);
|
|
|
|
| 669 |
this.position = position.clone();
|
| 670 |
this.velocity = new THREE.Vector3(0, 0, 120);
|
| 671 |
this.rotation = new THREE.Euler(0, 0, 0);
|
| 672 |
+
this.health = GAME_CONSTANTS.MAX_HEALTH; // 체λ ₯ 1000
|
| 673 |
this.speed = 120;
|
| 674 |
this.bullets = [];
|
| 675 |
this.lastShootTime = 0;
|
|
|
|
| 865 |
this.lastTime = performance.now();
|
| 866 |
this.gameTimer = null;
|
| 867 |
this.animationFrameId = null;
|
| 868 |
+
this.lastShootTime = 0;
|
| 869 |
|
| 870 |
this.bgm = null;
|
| 871 |
this.bgmPlaying = false;
|
|
|
|
| 1072 |
this.fighter.updateMouseInput(deltaX, deltaY);
|
| 1073 |
});
|
| 1074 |
|
| 1075 |
+
// λ§μ°μ€ λ€μ΄/μ
μ΄λ²€νΈ μΆκ°
|
| 1076 |
+
document.addEventListener('mousedown', (event) => {
|
| 1077 |
+
if (!document.pointerLockElement || this.isGameOver || !gameStarted) return;
|
| 1078 |
+
|
| 1079 |
+
if (event.button === 0) { // μΌμͺ½ λ§μ°μ€ λ²νΌ
|
| 1080 |
+
this.fighter.isMouseDown = true;
|
| 1081 |
+
this.lastShootTime = 0; // μ¦μ λ°μ¬
|
| 1082 |
+
}
|
| 1083 |
+
});
|
| 1084 |
+
|
| 1085 |
+
document.addEventListener('mouseup', (event) => {
|
| 1086 |
+
if (event.button === 0) { // μΌμͺ½ λ§μ°μ€ λ²νΌ
|
| 1087 |
+
this.fighter.isMouseDown = false;
|
| 1088 |
+
}
|
| 1089 |
+
});
|
| 1090 |
+
|
| 1091 |
window.addEventListener('resize', () => {
|
| 1092 |
this.camera.aspect = window.innerWidth / window.innerHeight;
|
| 1093 |
this.camera.updateProjectionMatrix();
|
|
|
|
| 1167 |
const ammoElement = document.getElementById('ammoDisplay');
|
| 1168 |
const gameStatsElement = document.getElementById('gameStats');
|
| 1169 |
|
| 1170 |
+
// 체λ ₯λ°μ μμΉ νμ
|
| 1171 |
+
const healthBar = document.getElementById('healthBar');
|
| 1172 |
+
if (healthBar) {
|
| 1173 |
+
healthBar.innerHTML = `
|
| 1174 |
+
<div id="health" style="width: ${(this.fighter.health / GAME_CONSTANTS.MAX_HEALTH) * 100}%"></div>
|
| 1175 |
+
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-weight: bold;">
|
| 1176 |
+
${this.fighter.health}/${GAME_CONSTANTS.MAX_HEALTH}
|
| 1177 |
+
</div>
|
| 1178 |
+
`;
|
| 1179 |
+
}
|
| 1180 |
+
|
| 1181 |
if (scoreElement) scoreElement.textContent = `Score: ${this.score}`;
|
| 1182 |
if (timeElement) timeElement.textContent = `Time: ${this.gameTime}s`;
|
|
|
|
| 1183 |
if (ammoElement) ammoElement.textContent = `AMMO: ${this.fighter.ammo}`;
|
| 1184 |
|
| 1185 |
if (gameStatsElement) {
|
|
|
|
| 1322 |
}
|
| 1323 |
|
| 1324 |
// Game ν΄λμ€μ updateWarnings λ©μλ μμ
|
| 1325 |
+
updateWarnings() {
|
| 1326 |
+
// κΈ°μ‘΄ κ²½κ³ λ©μμ§ μ κ±°
|
| 1327 |
+
const existingWarnings = document.querySelectorAll('.warning-message');
|
| 1328 |
+
existingWarnings.forEach(w => w.remove());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1329 |
|
| 1330 |
+
// μ€ν¨ νμΆ κ²½κ³ μ κ±°
|
| 1331 |
+
const existingStallWarnings = document.querySelectorAll('.stall-escape-warning');
|
| 1332 |
+
existingStallWarnings.forEach(w => w.remove());
|
| 1333 |
+
|
| 1334 |
+
// κ³ λ κ²½κ³ μΈκ³½ ν¨κ³Ό
|
| 1335 |
+
let altitudeEdgeEffect = document.getElementById('altitudeEdgeEffect');
|
| 1336 |
+
if (this.fighter.altitude < 500) {
|
| 1337 |
+
if (!altitudeEdgeEffect) {
|
| 1338 |
+
altitudeEdgeEffect = document.createElement('div');
|
| 1339 |
+
altitudeEdgeEffect.id = 'altitudeEdgeEffect';
|
| 1340 |
+
document.body.appendChild(altitudeEdgeEffect);
|
| 1341 |
+
}
|
| 1342 |
+
|
| 1343 |
+
let edgeIntensity;
|
| 1344 |
+
if (this.fighter.altitude < 250) {
|
| 1345 |
+
// PULL UP κ²½κ³ - κ°ν λΆμ ν¨κ³Ό
|
| 1346 |
+
edgeIntensity = 0.6;
|
| 1347 |
+
altitudeEdgeEffect.style.cssText = `
|
| 1348 |
+
position: fixed;
|
| 1349 |
+
top: 0;
|
| 1350 |
+
left: 0;
|
| 1351 |
+
width: 100%;
|
| 1352 |
+
height: 100%;
|
| 1353 |
+
pointer-events: none;
|
| 1354 |
+
z-index: 1300;
|
| 1355 |
+
background: radial-gradient(ellipse at center,
|
| 1356 |
+
transparent 40%,
|
| 1357 |
+
rgba(255, 0, 0, ${edgeIntensity * 0.3}) 60%,
|
| 1358 |
+
rgba(255, 0, 0, ${edgeIntensity}) 100%);
|
| 1359 |
+
box-shadow: inset 0 0 150px rgba(255, 0, 0, ${edgeIntensity}),
|
| 1360 |
+
inset 0 0 100px rgba(255, 0, 0, ${edgeIntensity * 0.8});
|
| 1361 |
+
animation: pulse-red 0.5s infinite;
|
| 1362 |
+
`;
|
| 1363 |
+
} else {
|
| 1364 |
+
// LOW ALTITUDE κ²½κ³ - μ½ν λΆμ ν¨κ³Ό
|
| 1365 |
+
edgeIntensity = 0.3;
|
| 1366 |
+
altitudeEdgeEffect.style.cssText = `
|
| 1367 |
+
position: fixed;
|
| 1368 |
+
top: 0;
|
| 1369 |
+
left: 0;
|
| 1370 |
+
width: 100%;
|
| 1371 |
+
height: 100%;
|
| 1372 |
+
pointer-events: none;
|
| 1373 |
+
z-index: 1300;
|
| 1374 |
+
background: radial-gradient(ellipse at center,
|
| 1375 |
+
transparent 50%,
|
| 1376 |
+
rgba(255, 0, 0, ${edgeIntensity * 0.2}) 70%,
|
| 1377 |
+
rgba(255, 0, 0, ${edgeIntensity}) 100%);
|
| 1378 |
+
box-shadow: inset 0 0 100px rgba(255, 0, 0, ${edgeIntensity}),
|
| 1379 |
+
inset 0 0 50px rgba(255, 0, 0, ${edgeIntensity * 0.5});
|
| 1380 |
+
`;
|
| 1381 |
+
}
|
| 1382 |
+
} else {
|
| 1383 |
+
// κ³ λκ° μμ νλ©΄ ν¨κ³Ό μ κ±°
|
| 1384 |
+
if (altitudeEdgeEffect) {
|
| 1385 |
+
altitudeEdgeEffect.remove();
|
| 1386 |
+
}
|
| 1387 |
}
|
| 1388 |
|
| 1389 |
+
if (this.fighter.warningBlinkState) {
|
| 1390 |
+
const warningContainer = document.createElement('div');
|
| 1391 |
+
warningContainer.className = 'warning-message';
|
| 1392 |
+
warningContainer.style.cssText = `
|
| 1393 |
+
position: fixed;
|
| 1394 |
+
top: 30%;
|
| 1395 |
+
left: 50%;
|
| 1396 |
+
transform: translateX(-50%);
|
| 1397 |
+
color: #ff0000;
|
| 1398 |
+
font-size: 24px;
|
| 1399 |
+
font-weight: bold;
|
| 1400 |
+
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
|
| 1401 |
+
z-index: 1500;
|
| 1402 |
+
text-align: center;
|
| 1403 |
+
`;
|
| 1404 |
+
|
| 1405 |
+
let warningText = '';
|
| 1406 |
+
|
| 1407 |
+
if (this.fighter.altitude < 250) {
|
| 1408 |
+
warningText += 'PULL UP! PULL UP!\n';
|
| 1409 |
+
} else if (this.fighter.altitude < 500) {
|
| 1410 |
+
warningText += 'LOW ALTITUDE WARNING\n';
|
| 1411 |
+
}
|
| 1412 |
+
|
| 1413 |
+
if (this.fighter.altitudeWarning) {
|
| 1414 |
+
warningText += 'ALTITUDE LIMIT\n';
|
| 1415 |
+
}
|
| 1416 |
+
|
| 1417 |
+
if (this.fighter.stallWarning) {
|
| 1418 |
+
warningText += 'STALL WARNING\n';
|
| 1419 |
+
}
|
| 1420 |
+
|
| 1421 |
+
if (this.fighter.overG) {
|
| 1422 |
+
warningText += 'OVER-G! OVER-G!\n';
|
| 1423 |
+
}
|
| 1424 |
+
|
| 1425 |
+
if (warningText) {
|
| 1426 |
+
warningContainer.innerHTML = warningText.replace(/\n/g, '<br>');
|
| 1427 |
+
document.body.appendChild(warningContainer);
|
| 1428 |
+
}
|
| 1429 |
}
|
| 1430 |
|
| 1431 |
+
// μ€ν¨ μνμΌ λλ§ "Press F to Escape" κ²½κ³ νμ
|
| 1432 |
if (this.fighter.stallWarning) {
|
| 1433 |
+
const stallEscapeWarning = document.createElement('div');
|
| 1434 |
+
stallEscapeWarning.className = 'stall-escape-warning';
|
| 1435 |
+
stallEscapeWarning.style.cssText = `
|
| 1436 |
+
position: fixed;
|
| 1437 |
+
bottom: 100px;
|
| 1438 |
+
left: 50%;
|
| 1439 |
+
transform: translateX(-50%);
|
| 1440 |
+
background: rgba(255, 0, 0, 0.8);
|
| 1441 |
+
color: #ffffff;
|
| 1442 |
+
font-size: 28px;
|
| 1443 |
+
font-weight: bold;
|
| 1444 |
+
padding: 15px 30px;
|
| 1445 |
+
border: 3px solid #ff0000;
|
| 1446 |
+
border-radius: 10px;
|
| 1447 |
+
z-index: 1600;
|
| 1448 |
+
text-align: center;
|
| 1449 |
+
animation: blink 0.5s infinite;
|
| 1450 |
+
`;
|
| 1451 |
+
stallEscapeWarning.innerHTML = 'PRESS F TO ESCAPE';
|
| 1452 |
+
document.body.appendChild(stallEscapeWarning);
|
| 1453 |
+
|
| 1454 |
+
// μ λλ©μ΄μ
μ€νμΌ μΆκ°
|
| 1455 |
+
if (!document.getElementById('blinkAnimation')) {
|
| 1456 |
+
const style = document.createElement('style');
|
| 1457 |
+
style.id = 'blinkAnimation';
|
| 1458 |
+
style.innerHTML = `
|
| 1459 |
+
@keyframes blink {
|
| 1460 |
+
0%, 50% { opacity: 1; }
|
| 1461 |
+
51%, 100% { opacity: 0.3; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1462 |
}
|
| 1463 |
+
@keyframes pulse-green {
|
| 1464 |
+
0%, 100% {
|
| 1465 |
+
opacity: 1;
|
| 1466 |
+
transform: translateX(-50%) scale(1);
|
| 1467 |
+
}
|
| 1468 |
+
50% {
|
| 1469 |
+
opacity: 0.8;
|
| 1470 |
+
transform: translateX(-50%) scale(1.1);
|
| 1471 |
+
}
|
| 1472 |
}
|
| 1473 |
+
@keyframes box-pulse {
|
| 1474 |
+
0%, 100% {
|
| 1475 |
+
background: rgba(255, 0, 0, 0.9);
|
| 1476 |
+
box-shadow: 0 0 20px rgba(255, 0, 0, 0.8),
|
| 1477 |
+
0 0 40px rgba(255, 0, 0, 0.4);
|
| 1478 |
+
}
|
| 1479 |
+
50% {
|
| 1480 |
+
background: rgba(255, 50, 50, 1);
|
| 1481 |
+
box-shadow: 0 0 30px rgba(255, 100, 100, 1),
|
| 1482 |
+
0 0 60px rgba(255, 0, 0, 0.8);
|
| 1483 |
+
}
|
| 1484 |
}
|
| 1485 |
+
@keyframes pulse-red {
|
| 1486 |
+
0%, 100% {
|
| 1487 |
+
opacity: 1;
|
| 1488 |
+
}
|
| 1489 |
+
50% {
|
| 1490 |
+
opacity: 0.7;
|
| 1491 |
+
}
|
| 1492 |
}
|
| 1493 |
+
`;
|
| 1494 |
+
document.head.appendChild(style);
|
| 1495 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1496 |
}
|
| 1497 |
|
| 1498 |
+
// Over-G μμΌ ν¨κ³Ό - μμ λ λΆλΆ
|
| 1499 |
+
if (this.fighter.overG && this.fighter.overGTimer > 0) {
|
| 1500 |
+
let blurEffect = document.getElementById('overGBlurEffect');
|
| 1501 |
+
if (!blurEffect) {
|
| 1502 |
+
blurEffect = document.createElement('div');
|
| 1503 |
+
blurEffect.id = 'overGBlurEffect';
|
| 1504 |
+
document.body.appendChild(blurEffect);
|
| 1505 |
+
}
|
| 1506 |
+
|
| 1507 |
+
// Over-G μ§μ μκ°μ λ°λΌ μ μ§μ μΌλ‘ μ΄λμμ§
|
| 1508 |
+
// 0μ΄: ν¨κ³Ό μμ
|
| 1509 |
+
// 1μ΄: κ±°μ μμ ν μ΄λμμ§
|
| 1510 |
+
const darknessFactor = Math.min(this.fighter.overGTimer, 1.0); // 0~1 λ²μλ‘ μ ν
|
| 1511 |
+
|
| 1512 |
+
// μμΌ κ°μ₯μ리λΆν° μ΄λμμ§λ ν¨κ³Ό
|
| 1513 |
+
// μ€μμ μλμ μΌλ‘ λ¦κ² μ΄λμμ§
|
| 1514 |
+
const centerTransparency = Math.max(0, 1 - darknessFactor * 1.2); // μ€μ ν¬λͺ
λ
|
| 1515 |
+
const midTransparency = Math.max(0, 1 - darknessFactor * 0.8); // μ€κ° ν¬λͺ
λ
|
| 1516 |
+
const edgeOpacity = Math.min(0.95, darknessFactor * 0.95); // κ°μ₯μ리 λΆν¬λͺ
λ
|
| 1517 |
+
|
| 1518 |
+
// λΆοΏ½οΏ½ μμ‘° μΆκ° (νμ‘ μν λ¬Έμ λ₯Ό μκ°ν) - μ½νλ λ²μ
|
| 1519 |
+
const redTint = Math.min(darknessFactor * 0.1, 0.1); // 0.3μμ 0.1λ‘ κ°μ
|
| 1520 |
+
|
| 1521 |
+
blurEffect.style.cssText = `
|
| 1522 |
+
position: fixed;
|
| 1523 |
+
top: 0;
|
| 1524 |
+
left: 0;
|
| 1525 |
+
width: 100%;
|
| 1526 |
+
height: 100%;
|
| 1527 |
+
background: radial-gradient(ellipse at center,
|
| 1528 |
+
rgba(${Math.floor(255 * redTint)}, 0, 0, ${1 - centerTransparency}) 0%,
|
| 1529 |
+
rgba(${Math.floor(150 * redTint)}, 0, 0, ${1 - midTransparency}) 40%,
|
| 1530 |
+
rgba(0, 0, 0, ${edgeOpacity}) 70%,
|
| 1531 |
+
rgba(0, 0, 0, ${Math.min(0.98, edgeOpacity + 0.05)}) 100%);
|
| 1532 |
+
pointer-events: none;
|
| 1533 |
+
z-index: 1400;
|
| 1534 |
+
transition: background 0.1s ease-out;
|
| 1535 |
+
`;
|
| 1536 |
+
|
| 1537 |
+
// μ¬ν Over-G μνμμ νλ©΄ νλ€λ¦Ό ν¨κ³Ό
|
| 1538 |
+
if (darknessFactor > 0.7) {
|
| 1539 |
+
const shake = (1 - Math.random() * 2) * 2;
|
| 1540 |
+
blurEffect.style.transform = `translate(${shake}px, ${shake}px)`;
|
| 1541 |
+
}
|
| 1542 |
+
|
| 1543 |
+
// λλ²κ·Έ μ 보 (μ νμ¬ν)
|
| 1544 |
+
// console.log(`Over-G Timer: ${this.fighter.overGTimer.toFixed(2)}s, Darkness: ${(darknessFactor * 100).toFixed(0)}%`);
|
| 1545 |
+
|
| 1546 |
+
} else {
|
| 1547 |
+
// Over-G μνκ° μλλ©΄ ν¨κ³Ό μ κ±°
|
| 1548 |
+
const blurEffect = document.getElementById('overGBlurEffect');
|
| 1549 |
+
if (blurEffect) {
|
| 1550 |
+
// λΆλλ¬μ΄ μ κ±°λ₯Ό μν νμ΄λμμ
|
| 1551 |
+
blurEffect.style.transition = 'opacity 0.5s ease-out';
|
| 1552 |
+
blurEffect.style.opacity = '0';
|
| 1553 |
+
setTimeout(() => {
|
| 1554 |
+
if (blurEffect.parentNode) {
|
| 1555 |
+
blurEffect.remove();
|
| 1556 |
+
}
|
| 1557 |
+
}, 500);
|
| 1558 |
+
}
|
| 1559 |
}
|
| 1560 |
}
|
|
|
|
| 1561 |
|
| 1562 |
updateRadar() {
|
| 1563 |
const radar = document.getElementById('radar');
|
|
|
|
| 1605 |
this.scene.remove(bullet);
|
| 1606 |
this.fighter.bullets.splice(i, 1);
|
| 1607 |
|
| 1608 |
+
if (enemy.takeDamage(GAME_CONSTANTS.BULLET_DAMAGE)) { // 25 λ°λ―Έμ§
|
| 1609 |
enemy.destroy();
|
| 1610 |
this.enemies.splice(j, 1);
|
| 1611 |
this.score += 100;
|
|
|
|
| 1622 |
this.scene.remove(bullet);
|
| 1623 |
enemy.bullets.splice(index, 1);
|
| 1624 |
|
| 1625 |
+
if (this.fighter.takeDamage(GAME_CONSTANTS.BULLET_DAMAGE)) { // 25 λ°λ―Έμ§
|
| 1626 |
this.endGame(false);
|
| 1627 |
}
|
| 1628 |
}
|
|
|
|
| 1647 |
this.fighter.updatePhysics(deltaTime);
|
| 1648 |
this.fighter.updateBullets(this.scene, deltaTime);
|
| 1649 |
|
| 1650 |
+
// λ§μ°μ€ λλ¦ μνμΌ λ μ°μ λ°μ¬
|
| 1651 |
+
if (this.fighter.isMouseDown && this.isStarted) {
|
| 1652 |
+
const currentShootTime = Date.now();
|
| 1653 |
+
if (!this.lastShootTime || currentShootTime - this.lastShootTime >= 500) { // 0.5μ΄λ§λ€
|
| 1654 |
+
this.fighter.shoot(this.scene);
|
| 1655 |
+
this.lastShootTime = currentShootTime;
|
| 1656 |
+
}
|
| 1657 |
+
}
|
| 1658 |
+
|
| 1659 |
if (this.isStarted) {
|
| 1660 |
this.enemies.forEach(enemy => {
|
| 1661 |
enemy.update(this.fighter.position, deltaTime);
|
|
|
|
| 1827 |
console.log('κ²μ μ€ ν΄λ¦ - ν¬μΈν° λ½ μ¬μμ²');
|
| 1828 |
document.body.requestPointerLock();
|
| 1829 |
}
|
| 1830 |
+
// ν΄λ¦μΌλ‘ λ¨λ° μ¬κ²© μ κ±° (λ§μ°μ€ λ€μ΄/μ
μ΄λ²€νΈλ‘ μ²λ¦¬)
|
|
|
|
|
|
|
| 1831 |
}
|
| 1832 |
}, true);
|
| 1833 |
|