Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -461,230 +461,23 @@ class Fighter {
|
|
| 461 |
this.stallEscapeProgress = 0; // μ€ν¨ μ§μ
μ μ§νλ μ΄κΈ°ν
|
| 462 |
}
|
| 463 |
|
| 464 |
-
//
|
| 465 |
-
} else if (this.stallWarning && !this.escapeKeyPressed) {
|
| 466 |
-
// Fν€λ₯Ό λμΌλ©΄ μ§νλ κ°μ
|
| 467 |
-
this.stallEscapeProgress = Math.max(0, this.stallEscapeProgress - deltaTime * 2);
|
| 468 |
-
}
|
| 469 |
-
|
| 470 |
-
// μλ λ³ν μ μ©
|
| 471 |
if (this.stallWarning) {
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 477 |
} else {
|
| 478 |
-
//
|
| 479 |
-
this.
|
| 480 |
}
|
| 481 |
-
} else {
|
| 482 |
-
// μ μ λΉν μ μλ λ³ν
|
| 483 |
-
this.speed = THREE.MathUtils.lerp(this.speed, targetSpeed, deltaTime * 0.5);
|
| 484 |
-
}
|
| 485 |
-
|
| 486 |
-
// μ€ν¨ μνμμμ 물리 ν¨κ³Ό
|
| 487 |
-
if (this.stallWarning) {
|
| 488 |
-
// λ°λ₯μΌλ‘ μΆλ½νλ©° κ°μλκ° λΉ λ₯΄κ² λΆμ
|
| 489 |
-
this.targetPitch = Math.min(Math.PI / 2.5, this.targetPitch + deltaTime * 2.5); // κΈ°μκ° λ κ·Ήλ¨μ μΌλ‘ μλλ‘ (72λκΉμ§)
|
| 490 |
-
|
| 491 |
-
// μ‘°μ’
λΆλ₯ μν - λ μ¬ν νλ€λ¦Ό
|
| 492 |
-
this.rotation.x += (Math.random() - 0.5) * deltaTime * 0.8;
|
| 493 |
-
this.rotation.z += (Math.random() - 0.5) * deltaTime * 0.8;
|
| 494 |
-
|
| 495 |
-
// μ€λ ₯μ μν κ°μ
|
| 496 |
-
const gravityAcceleration = GAME_CONSTANTS.GRAVITY * deltaTime * 3.0; // 3λ°° μ€λ ₯
|
| 497 |
-
this.velocity.y -= gravityAcceleration;
|
| 498 |
-
}
|
| 499 |
-
|
| 500 |
-
// μλ λ²‘ν° κ³μ°
|
| 501 |
-
const noseDirection = new THREE.Vector3(0, 0, 1);
|
| 502 |
-
noseDirection.applyEuler(this.rotation);
|
| 503 |
-
|
| 504 |
-
if (!this.stallWarning) {
|
| 505 |
-
// μ μ λΉν μ
|
| 506 |
-
this.velocity = noseDirection.multiplyScalar(this.speed);
|
| 507 |
-
} else {
|
| 508 |
-
// μ€ν¨ μμλ μ€λ ₯μ΄ μ£Όλμ μ΄μ§λ§ λ€μ΄λΉ μλλ λ°μ
|
| 509 |
-
this.velocity.x = noseDirection.x * this.speed * 0.5; // μ λ°© μλ μ¦κ°
|
| 510 |
-
this.velocity.z = noseDirection.z * this.speed * 0.5;
|
| 511 |
-
// y μλλ μμμ μ€λ ₯μΌλ‘ μ²λ¦¬λ¨
|
| 512 |
-
}
|
| 513 |
-
|
| 514 |
-
// μ μ λΉν μ μ€λ ₯ ν¨κ³Ό
|
| 515 |
-
if (!this.stallWarning) {
|
| 516 |
-
const gravityEffect = GAME_CONSTANTS.GRAVITY * deltaTime * 0.15;
|
| 517 |
-
this.velocity.y -= gravityEffect;
|
| 518 |
-
|
| 519 |
-
// μλ ₯ ν¨κ³Ό (μλμ λΉλ‘)
|
| 520 |
-
const liftFactor = (this.speed / maxSpeed) * 0.8;
|
| 521 |
-
const lift = gravityEffect * liftFactor;
|
| 522 |
-
this.velocity.y += lift;
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
// μμΉ μ
λ°μ΄νΈ
|
| 526 |
-
this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
|
| 527 |
-
|
| 528 |
-
// μ§ν μΆ©λ κ°μ§ (Game ν΄λμ€μμ μ²λ¦¬νλλ‘ μμ )
|
| 529 |
-
|
| 530 |
-
// μ§λ©΄ μΆ©λ
|
| 531 |
-
if (this.position.y <= GAME_CONSTANTS.MIN_ALTITUDE) {
|
| 532 |
-
this.position.y = GAME_CONSTANTS.MIN_ALTITUDE;
|
| 533 |
-
this.health = 0;
|
| 534 |
-
return;
|
| 535 |
-
}
|
| 536 |
-
|
| 537 |
-
// μ΅λ κ³ λ μ ν
|
| 538 |
-
if (this.position.y > GAME_CONSTANTS.MAX_ALTITUDE) {
|
| 539 |
-
this.position.y = GAME_CONSTANTS.MAX_ALTITUDE;
|
| 540 |
-
this.altitudeWarning = true;
|
| 541 |
-
if (this.velocity.y > 0) this.velocity.y = 0;
|
| 542 |
-
} else {
|
| 543 |
-
this.altitudeWarning = false;
|
| 544 |
-
}
|
| 545 |
-
|
| 546 |
-
// λ§΅ κ²½κ³ μ²λ¦¬
|
| 547 |
-
const mapLimit = GAME_CONSTANTS.MAP_SIZE / 2;
|
| 548 |
-
if (this.position.x > mapLimit) this.position.x = -mapLimit;
|
| 549 |
-
if (this.position.x < -mapLimit) this.position.x = mapLimit;
|
| 550 |
-
if (this.position.z > mapLimit) this.position.z = -mapLimit;
|
| 551 |
-
if (this.position.z < -mapLimit) this.position.z = mapLimit;
|
| 552 |
-
|
| 553 |
-
// λ©μ μμΉ λ° νμ μ
λ°μ΄νΈ
|
| 554 |
-
this.mesh.position.copy(this.position);
|
| 555 |
-
this.mesh.rotation.x = this.rotation.x;
|
| 556 |
-
this.mesh.rotation.y = this.rotation.y + 3 * Math.PI / 2;
|
| 557 |
-
this.mesh.rotation.z = this.rotation.z;
|
| 558 |
-
|
| 559 |
-
// κ²½κ³ κΉλΉ‘μ νμ΄λ¨Έ
|
| 560 |
-
this.warningBlinkTimer += deltaTime;
|
| 561 |
-
if (this.warningBlinkTimer >= 1.0) {
|
| 562 |
-
this.warningBlinkTimer = 0;
|
| 563 |
-
this.warningBlinkState = !this.warningBlinkState;
|
| 564 |
-
}
|
| 565 |
-
|
| 566 |
-
// κ³ λ κ³μ°
|
| 567 |
-
this.altitude = this.position.y;
|
| 568 |
-
|
| 569 |
-
// κ²½κ³ μ μ
λ°μ΄νΈ (μμ§ μ리λ κ³μ μ μ§)
|
| 570 |
-
this.updateWarningAudios();
|
| 571 |
-
|
| 572 |
-
// μμ§ μ리 λ³Όλ₯¨μ μ€λ‘νμ μ°λ
|
| 573 |
-
if (this.warningAudios.normal && !this.warningAudios.normal.paused) {
|
| 574 |
-
this.warningAudios.normal.volume = 0.3 + this.throttle * 0.4; // 0.3~0.7
|
| 575 |
-
}
|
| 576 |
-
} Fν€λ₯Ό λμΌλ©΄ μ§νλ κ°μ
|
| 577 |
-
this.stallEscapeProgress = Math.max(0, this.stallEscapeProgress - deltaTime * 2);
|
| 578 |
-
}
|
| 579 |
-
|
| 580 |
-
// μλ λ³ν μ μ©
|
| 581 |
-
if (this.stallWarning) {
|
| 582 |
-
// μ€ν¨ μνμμμ μλ λ³ν
|
| 583 |
-
if (pitchAngle > 0.1) { // κΈ°μκ° μλλ₯Ό ν₯ν λ
|
| 584 |
-
// λ€μ΄λΉμΌλ‘ μΈν μλ μ¦κ°
|
| 585 |
-
const diveSpeedGain = Math.min(pitchAngle * 300, 200); // μ΅λ 200m/s μ¦κ°
|
| 586 |
-
this.speed = Math.min(maxSpeed, this.speed + diveSpeedGain * deltaTime);
|
| 587 |
-
} else {
|
| 588 |
-
// κΈ°μκ° μλ₯Ό ν₯νκ±°λ μνμΌ λλ μλ κ°μ
|
| 589 |
-
this.speed = Math.max(0, this.speed - deltaTime * 100);
|
| 590 |
-
}
|
| 591 |
-
} else {
|
| 592 |
-
// μ μ λΉν μ μλ λ³ν
|
| 593 |
-
this.speed = THREE.MathUtils.lerp(this.speed, targetSpeed, deltaTime * 0.5);
|
| 594 |
-
}
|
| 595 |
-
|
| 596 |
-
// μ€ν¨ μνμμμ 물리 ν¨κ³Ό
|
| 597 |
-
if (this.stallWarning) {
|
| 598 |
-
// λ°λ₯μΌλ‘ μΆλ½νλ©° κ°μλκ° λΉ λ₯΄κ² λΆμ
|
| 599 |
-
this.targetPitch = Math.min(Math.PI / 2.5, this.targetPitch + deltaTime * 2.5); // κΈ°μκ° λ κ·Ήλ¨μ μΌλ‘ μλλ‘ (72λκΉμ§)
|
| 600 |
-
|
| 601 |
-
// μ‘°μ’
λΆλ₯ μν - λ μ¬ν νλ€λ¦Ό
|
| 602 |
-
this.rotation.x += (Math.random() - 0.5) * deltaTime * 0.8;
|
| 603 |
-
this.rotation.z += (Math.random() - 0.5) * deltaTime * 0.8;
|
| 604 |
-
|
| 605 |
-
// μ€λ ₯μ μν κ°μ
|
| 606 |
-
const gravityAcceleration = GAME_CONSTANTS.GRAVITY * deltaTime * 3.0; // 3λ°° μ€λ ₯
|
| 607 |
-
this.velocity.y -= gravityAcceleration;
|
| 608 |
-
}
|
| 609 |
-
|
| 610 |
-
// μλ λ²‘ν° κ³μ°
|
| 611 |
-
const noseDirection = new THREE.Vector3(0, 0, 1);
|
| 612 |
-
noseDirection.applyEuler(this.rotation);
|
| 613 |
-
|
| 614 |
-
if (!this.stallWarning) {
|
| 615 |
-
// μ μ λΉν μ
|
| 616 |
-
this.velocity = noseDirection.multiplyScalar(this.speed);
|
| 617 |
-
} else {
|
| 618 |
-
// μ€ν¨ μμλ μ€λ ₯μ΄ μ£Όλμ μ΄μ§λ§ λ€μ΄λΉ μλλ λ°μ
|
| 619 |
-
this.velocity.x = noseDirection.x * this.speed * 0.5; // μ λ°© μλ μ¦κ°
|
| 620 |
-
this.velocity.z = noseDirection.z * this.speed * 0.5;
|
| 621 |
-
// y μλλ μμμ μ€λ ₯μΌλ‘ μ²λ¦¬λ¨
|
| 622 |
-
}
|
| 623 |
-
|
| 624 |
-
// μ μ λΉν μ μ€λ ₯ ν¨κ³Ό
|
| 625 |
-
if (!this.stallWarning) {
|
| 626 |
-
const gravityEffect = GAME_CONSTANTS.GRAVITY * deltaTime * 0.15;
|
| 627 |
-
this.velocity.y -= gravityEffect;
|
| 628 |
-
|
| 629 |
-
// μλ ₯ ν¨κ³Ό (μλμ λΉλ‘)
|
| 630 |
-
const liftFactor = (this.speed / maxSpeed) * 0.8;
|
| 631 |
-
const lift = gravityEffect * liftFactor;
|
| 632 |
-
this.velocity.y += lift;
|
| 633 |
-
}
|
| 634 |
-
|
| 635 |
-
// μμΉ μ
λ°μ΄νΈ
|
| 636 |
-
this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
|
| 637 |
-
|
| 638 |
-
// μ§ν μΆ©λ κ°μ§ (Game ν΄λμ€μμ μ²λ¦¬νλλ‘ μμ )
|
| 639 |
-
|
| 640 |
-
// μ§λ©΄ μΆ©λ
|
| 641 |
-
if (this.position.y <= GAME_CONSTANTS.MIN_ALTITUDE) {
|
| 642 |
-
this.position.y = GAME_CONSTANTS.MIN_ALTITUDE;
|
| 643 |
-
this.health = 0;
|
| 644 |
-
return;
|
| 645 |
-
}
|
| 646 |
-
|
| 647 |
-
// μ΅λ κ³ λ μ ν
|
| 648 |
-
if (this.position.y > GAME_CONSTANTS.MAX_ALTITUDE) {
|
| 649 |
-
this.position.y = GAME_CONSTANTS.MAX_ALTITUDE;
|
| 650 |
-
this.altitudeWarning = true;
|
| 651 |
-
if (this.velocity.y > 0) this.velocity.y = 0;
|
| 652 |
-
} else {
|
| 653 |
-
this.altitudeWarning = false;
|
| 654 |
-
}
|
| 655 |
-
|
| 656 |
-
// λ§΅ κ²½κ³ μ²λ¦¬
|
| 657 |
-
const mapLimit = GAME_CONSTANTS.MAP_SIZE / 2;
|
| 658 |
-
if (this.position.x > mapLimit) this.position.x = -mapLimit;
|
| 659 |
-
if (this.position.x < -mapLimit) this.position.x = mapLimit;
|
| 660 |
-
if (this.position.z > mapLimit) this.position.z = -mapLimit;
|
| 661 |
-
if (this.position.z < -mapLimit) this.position.z = mapLimit;
|
| 662 |
-
|
| 663 |
-
// λ©μ μμΉ λ° νμ μ
λ°μ΄νΈ
|
| 664 |
-
this.mesh.position.copy(this.position);
|
| 665 |
-
this.mesh.rotation.x = this.rotation.x;
|
| 666 |
-
this.mesh.rotation.y = this.rotation.y + 3 * Math.PI / 2;
|
| 667 |
-
this.mesh.rotation.z = this.rotation.z;
|
| 668 |
-
|
| 669 |
-
// κ²½κ³ κΉλΉ‘μ νμ΄λ¨Έ
|
| 670 |
-
this.warningBlinkTimer += deltaTime;
|
| 671 |
-
if (this.warningBlinkTimer >= 1.0) {
|
| 672 |
-
this.warningBlinkTimer = 0;
|
| 673 |
-
this.warningBlinkState = !this.warningBlinkState;
|
| 674 |
-
}
|
| 675 |
-
|
| 676 |
-
// κ³ λ κ³μ°
|
| 677 |
-
this.altitude = this.position.y;
|
| 678 |
-
|
| 679 |
-
// κ²½κ³ μ μ
λ°μ΄νΈ (μμ§ μ리λ κ³μ μ μ§)
|
| 680 |
-
this.updateWarningAudios();
|
| 681 |
-
|
| 682 |
-
// μμ§ μ리 λ³Όλ₯¨μ μ€λ‘νμ μ°λ
|
| 683 |
-
if (this.warningAudios.normal && !this.warningAudios.normal.paused) {
|
| 684 |
-
this.warningAudios.normal.volume = 0.3 + this.throttle * 0.4; // 0.3~0.7
|
| 685 |
-
}
|
| 686 |
-
} Fν€λ₯Ό λμΌλ©΄ μ§νλ κ°μ
|
| 687 |
-
this.stallEscapeProgress = Math.max(0, this.stallEscapeProgress - deltaTime * 2);
|
| 688 |
}
|
| 689 |
|
| 690 |
// μλ λ³ν μ μ©
|
|
@@ -1440,362 +1233,6 @@ class Game {
|
|
| 1440 |
// κ°μ λ κ΅¬λ¦ μΆκ°
|
| 1441 |
this.addClouds();
|
| 1442 |
}
|
| 1443 |
-
|
| 1444 |
-
createProceduralTerrain() {
|
| 1445 |
-
// μ§ν μμ±μ μν μΈκ·Έλ¨ΌνΈ
|
| 1446 |
-
const segments = 100;
|
| 1447 |
-
const terrainGeometry = new THREE.PlaneGeometry(
|
| 1448 |
-
GAME_CONSTANTS.MAP_SIZE,
|
| 1449 |
-
GAME_CONSTANTS.MAP_SIZE,
|
| 1450 |
-
segments,
|
| 1451 |
-
segments
|
| 1452 |
-
);
|
| 1453 |
-
|
| 1454 |
-
// λ²ν
μ€μ λ
Έμ΄μ¦ μΆκ°νμ¬ μΈλ ν¨κ³Ό
|
| 1455 |
-
const vertices = terrainGeometry.attributes.position.array;
|
| 1456 |
-
const heightMap = [];
|
| 1457 |
-
|
| 1458 |
-
for (let i = 0; i < vertices.length; i += 3) {
|
| 1459 |
-
const x = vertices[i];
|
| 1460 |
-
const y = vertices[i + 1];
|
| 1461 |
-
|
| 1462 |
-
// λ€μ€ μ€μΌμΌ λ
Έμ΄μ¦λ‘ μμ°μ€λ¬μ΄ μ§ν μμ±
|
| 1463 |
-
let height = 0;
|
| 1464 |
-
|
| 1465 |
-
// ν° μ€μΌμΌ μΈλ (μ£Όμ μ§ν)
|
| 1466 |
-
height += Math.sin(x * 0.0001) * Math.cos(y * 0.0001) * 300;
|
| 1467 |
-
|
| 1468 |
-
// μ€κ° μ€μΌμΌ μΈλ
|
| 1469 |
-
height += Math.sin(x * 0.0003) * Math.cos(y * 0.0003) * 150;
|
| 1470 |
-
|
| 1471 |
-
// μμ μ€μΌμΌ λν
μΌ
|
| 1472 |
-
height += Math.sin(x * 0.001) * Math.cos(y * 0.001) * 50;
|
| 1473 |
-
|
| 1474 |
-
// λλ€ λ
Έμ΄μ¦
|
| 1475 |
-
height += (Math.random() - 0.5) * 20;
|
| 1476 |
-
|
| 1477 |
-
// λ§΅ κ°μ₯μλ¦¬λ‘ κ°μλ‘ λμ΄ κ°μ (κ²½κ³ λΆλλ½κ²)
|
| 1478 |
-
const distanceFromCenter = Math.sqrt(x * x + y * y);
|
| 1479 |
-
const maxDistance = GAME_CONSTANTS.MAP_SIZE * 0.4;
|
| 1480 |
-
if (distanceFromCenter > maxDistance) {
|
| 1481 |
-
const fade = 1 - (distanceFromCenter - maxDistance) / (GAME_CONSTANTS.MAP_SIZE * 0.1);
|
| 1482 |
-
height *= Math.max(0, fade);
|
| 1483 |
-
}
|
| 1484 |
-
|
| 1485 |
-
vertices[i + 2] = height;
|
| 1486 |
-
heightMap.push(height);
|
| 1487 |
-
}
|
| 1488 |
-
|
| 1489 |
-
terrainGeometry.computeVertexNormals();
|
| 1490 |
-
|
| 1491 |
-
// λ¨μν μ΄λ‘μ μ§ν λ¨Έν°λ¦¬μΌ
|
| 1492 |
-
const terrainMaterial = new THREE.MeshLambertMaterial({
|
| 1493 |
-
color: 0x8FBC8F,
|
| 1494 |
-
flatShading: false
|
| 1495 |
-
});
|
| 1496 |
-
|
| 1497 |
-
const terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
|
| 1498 |
-
terrain.rotation.x = -Math.PI / 2;
|
| 1499 |
-
terrain.receiveShadow = true;
|
| 1500 |
-
|
| 1501 |
-
// μ§ν μ 보 μ μ₯ (μ΄λͺ© λ°°μΉ λ° μΆ©λ νμ μ©)
|
| 1502 |
-
this.terrain = terrain;
|
| 1503 |
-
this.terrainGeometry = terrainGeometry;
|
| 1504 |
-
this.heightMap = heightMap;
|
| 1505 |
-
this.terrainSegments = segments;
|
| 1506 |
-
|
| 1507 |
-
this.scene.add(terrain);
|
| 1508 |
-
}
|
| 1509 |
-
|
| 1510 |
-
addVegetation() {
|
| 1511 |
-
if (!this.terrain || !this.heightMap) return;
|
| 1512 |
-
|
| 1513 |
-
// κ°λ¨ν λ무 λ°°μΉ
|
| 1514 |
-
const treeCount = 300;
|
| 1515 |
-
|
| 1516 |
-
for (let i = 0; i < treeCount; i++) {
|
| 1517 |
-
// λλ€ μμΉ μ ν
|
| 1518 |
-
const x = (Math.random() - 0.5) * GAME_CONSTANTS.MAP_SIZE * 0.8;
|
| 1519 |
-
const z = (Math.random() - 0.5) * GAME_CONSTANTS.MAP_SIZE * 0.8;
|
| 1520 |
-
|
| 1521 |
-
// ν΄λΉ μμΉμ μ§ν λμ΄ κ³μ°
|
| 1522 |
-
const terrainHeight = this.getTerrainHeightAt(x, z);
|
| 1523 |
-
|
| 1524 |
-
// λ무 λμ κ³³μλ λ무λ₯Ό λ°°μΉνμ§ μμ
|
| 1525 |
-
if (terrainHeight > 200) continue;
|
| 1526 |
-
|
| 1527 |
-
// κ°λ¨ν λ무 μμ±
|
| 1528 |
-
const tree = new THREE.Group();
|
| 1529 |
-
|
| 1530 |
-
// λͺΈν΅
|
| 1531 |
-
const trunkGeometry = new THREE.CylinderGeometry(1, 1.5, 15, 6);
|
| 1532 |
-
const trunkMaterial = new THREE.MeshLambertMaterial({
|
| 1533 |
-
color: 0x4a3c28
|
| 1534 |
-
});
|
| 1535 |
-
const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
|
| 1536 |
-
trunk.position.y = 7.5;
|
| 1537 |
-
trunk.castShadow = true;
|
| 1538 |
-
trunk.receiveShadow = true;
|
| 1539 |
-
tree.add(trunk);
|
| 1540 |
-
|
| 1541 |
-
// μ
|
| 1542 |
-
const leavesGeometry = new THREE.SphereGeometry(8, 6, 5);
|
| 1543 |
-
const leavesMaterial = new THREE.MeshLambertMaterial({
|
| 1544 |
-
color: 0x2d5016
|
| 1545 |
-
});
|
| 1546 |
-
const leaves = new THREE.Mesh(leavesGeometry, leavesMaterial);
|
| 1547 |
-
leaves.position.y = 20;
|
| 1548 |
-
leaves.castShadow = true;
|
| 1549 |
-
leaves.receiveShadow = true;
|
| 1550 |
-
tree.add(leaves);
|
| 1551 |
-
|
| 1552 |
-
// λ무 μμΉ λ° ν¬κΈ° μ€μ
|
| 1553 |
-
tree.position.set(x, terrainHeight, z);
|
| 1554 |
-
|
| 1555 |
-
// ν¬κΈ° λ³ν
|
| 1556 |
-
const scale = 0.8 + Math.random() * 0.4;
|
| 1557 |
-
tree.scale.set(scale, scale, scale);
|
| 1558 |
-
|
| 1559 |
-
// λλ€ νμ
|
| 1560 |
-
tree.rotation.y = Math.random() * Math.PI * 2;
|
| 1561 |
-
|
| 1562 |
-
this.scene.add(tree);
|
| 1563 |
-
}
|
| 1564 |
-
|
| 1565 |
-
// κ°λ¨ν κ΄λͺ© μΆκ°
|
| 1566 |
-
const bushCount = 200;
|
| 1567 |
-
|
| 1568 |
-
for (let i = 0; i < bushCount; i++) {
|
| 1569 |
-
const x = (Math.random() - 0.5) * GAME_CONSTANTS.MAP_SIZE * 0.8;
|
| 1570 |
-
const z = (Math.random() - 0.5) * GAME_CONSTANTS.MAP_SIZE * 0.8;
|
| 1571 |
-
const terrainHeight = this.getTerrainHeightAt(x, z);
|
| 1572 |
-
|
| 1573 |
-
if (terrainHeight > 150) continue;
|
| 1574 |
-
|
| 1575 |
-
const bushGeometry = new THREE.SphereGeometry(3, 5, 4);
|
| 1576 |
-
const bushMaterial = new THREE.MeshLambertMaterial({
|
| 1577 |
-
color: 0x3a5f3a
|
| 1578 |
-
});
|
| 1579 |
-
const bush = new THREE.Mesh(bushGeometry, bushMaterial);
|
| 1580 |
-
|
| 1581 |
-
bush.position.set(x, terrainHeight + 1.5, z);
|
| 1582 |
-
bush.scale.set(
|
| 1583 |
-
1 + Math.random() * 0.5,
|
| 1584 |
-
0.6 + Math.random() * 0.3,
|
| 1585 |
-
1 + Math.random() * 0.5
|
| 1586 |
-
);
|
| 1587 |
-
|
| 1588 |
-
bush.castShadow = true;
|
| 1589 |
-
bush.receiveShadow = true;
|
| 1590 |
-
|
| 1591 |
-
this.scene.add(bush);
|
| 1592 |
-
}
|
| 1593 |
-
}
|
| 1594 |
-
|
| 1595 |
-
getTerrainHeightAt(x, z) {
|
| 1596 |
-
if (!this.terrainGeometry || !this.heightMap) return 0;
|
| 1597 |
-
|
| 1598 |
-
// μ§ν μ’νλ₯Ό μ κ·ν
|
| 1599 |
-
const normalizedX = (x + GAME_CONSTANTS.MAP_SIZE / 2) / GAME_CONSTANTS.MAP_SIZE;
|
| 1600 |
-
const normalizedZ = (z + GAME_CONSTANTS.MAP_SIZE / 2) / GAME_CONSTANTS.MAP_SIZE;
|
| 1601 |
-
|
| 1602 |
-
// κ°μ₯ κ°κΉμ΄ λ²ν
μ€ μΈλ±μ€ μ°ΎκΈ°
|
| 1603 |
-
const segments = this.terrainSegments || 100; // terrainSegmentsκ° μμΌλ©΄ κΈ°λ³Έκ° μ¬μ©
|
| 1604 |
-
const gridX = Math.floor(normalizedX * (segments - 1));
|
| 1605 |
-
const gridZ = Math.floor(normalizedZ * (segments - 1));
|
| 1606 |
-
|
| 1607 |
-
if (gridX < 0 || gridX >= segments - 1 || gridZ < 0 || gridZ >= segments - 1) {
|
| 1608 |
-
return 0;
|
| 1609 |
-
}
|
| 1610 |
-
|
| 1611 |
-
const index = gridZ * segments + gridX;
|
| 1612 |
-
return this.heightMap[index] || 0;
|
| 1613 |
-
}
|
| 1614 |
-
|
| 1615 |
-
addAtmosphericEffects() {
|
| 1616 |
-
// κ°μ λ μ° μ§ν μμ€ν
|
| 1617 |
-
this.createMountainRanges();
|
| 1618 |
-
}
|
| 1619 |
-
|
| 1620 |
-
createMountainRanges() {
|
| 1621 |
-
// μ°λ§₯ μμ±μ μν μ€μ
|
| 1622 |
-
const mountainRanges = [
|
| 1623 |
-
{
|
| 1624 |
-
distance: GAME_CONSTANTS.MAP_SIZE * 0.6,
|
| 1625 |
-
count: 25,
|
| 1626 |
-
heightRange: { min: 2000, max: 5000 },
|
| 1627 |
-
widthRange: { min: 1500, max: 3000 },
|
| 1628 |
-
color: 0x5a6b7a
|
| 1629 |
-
},
|
| 1630 |
-
{
|
| 1631 |
-
distance: GAME_CONSTANTS.MAP_SIZE * 0.8,
|
| 1632 |
-
count: 20,
|
| 1633 |
-
heightRange: { min: 3000, max: 7000 },
|
| 1634 |
-
widthRange: { min: 2000, max: 4000 },
|
| 1635 |
-
color: 0x4a5b6a
|
| 1636 |
-
},
|
| 1637 |
-
{
|
| 1638 |
-
distance: GAME_CONSTANTS.MAP_SIZE * 1.0,
|
| 1639 |
-
count: 15,
|
| 1640 |
-
heightRange: { min: 4000, max: 9000 },
|
| 1641 |
-
widthRange: { min: 3000, max: 5000 },
|
| 1642 |
-
color: 0x3a4b5a
|
| 1643 |
-
}
|
| 1644 |
-
];
|
| 1645 |
-
|
| 1646 |
-
mountainRanges.forEach(range => {
|
| 1647 |
-
for (let i = 0; i < range.count; i++) {
|
| 1648 |
-
const angle = (i / range.count) * Math.PI * 2 + (Math.random() - 0.5) * 0.3;
|
| 1649 |
-
const distance = range.distance + (Math.random() - 0.5) * 1000;
|
| 1650 |
-
|
| 1651 |
-
// μ° κ·Έλ£Ή μμ± (μ¬λ¬ λ΄μ°λ¦¬λ‘ ꡬμ±)
|
| 1652 |
-
const mountainGroup = new THREE.Group();
|
| 1653 |
-
|
| 1654 |
-
// λ©μΈ λ΄μ°λ¦¬
|
| 1655 |
-
const mainPeakHeight = range.heightRange.min + Math.random() * (range.heightRange.max - range.heightRange.min);
|
| 1656 |
-
const mainPeakWidth = range.widthRange.min + Math.random() * (range.widthRange.max - range.widthRange.min);
|
| 1657 |
-
|
| 1658 |
-
// κ°μ λ μ° νν (νκ°λΏ λμ λ μμ°μ€λ¬μ΄ νν)
|
| 1659 |
-
const mainPeakGeometry = new THREE.ConeGeometry(mainPeakWidth, mainPeakHeight, 12);
|
| 1660 |
-
const vertices = mainPeakGeometry.attributes.position.array;
|
| 1661 |
-
|
| 1662 |
-
// μ μ λ³νμΌλ‘ λ μμ°μ€λ¬μ΄ μ° νν λ§λ€κΈ°
|
| 1663 |
-
for (let j = 0; j < vertices.length; j += 3) {
|
| 1664 |
-
const x = vertices[j];
|
| 1665 |
-
const y = vertices[j + 1];
|
| 1666 |
-
const z = vertices[j + 2];
|
| 1667 |
-
|
| 1668 |
-
// λμ΄μ λ°λ₯Έ λλ€ λ³ν
|
| 1669 |
-
const heightFactor = (y + mainPeakHeight * 0.5) / mainPeakHeight;
|
| 1670 |
-
const noise = (Math.random() - 0.5) * mainPeakWidth * 0.3 * (1 - heightFactor);
|
| 1671 |
-
|
| 1672 |
-
vertices[j] += noise;
|
| 1673 |
-
vertices[j + 2] += noise;
|
| 1674 |
-
}
|
| 1675 |
-
|
| 1676 |
-
mainPeakGeometry.computeVertexNormals();
|
| 1677 |
-
|
| 1678 |
-
const mainPeakMaterial = new THREE.MeshLambertMaterial({
|
| 1679 |
-
color: range.color,
|
| 1680 |
-
flatShading: true,
|
| 1681 |
-
fog: true
|
| 1682 |
-
});
|
| 1683 |
-
|
| 1684 |
-
const mainPeak = new THREE.Mesh(mainPeakGeometry, mainPeakMaterial);
|
| 1685 |
-
mountainGroup.add(mainPeak);
|
| 1686 |
-
|
| 1687 |
-
// μ£Όλ³ μμ λ΄μ°λ¦¬λ€ μΆκ°
|
| 1688 |
-
const subPeakCount = 2 + Math.floor(Math.random() * 3);
|
| 1689 |
-
for (let j = 0; j < subPeakCount; j++) {
|
| 1690 |
-
const subPeakHeight = mainPeakHeight * (0.5 + Math.random() * 0.3);
|
| 1691 |
-
const subPeakWidth = mainPeakWidth * (0.6 + Math.random() * 0.3);
|
| 1692 |
-
|
| 1693 |
-
const subPeakGeometry = new THREE.ConeGeometry(subPeakWidth, subPeakHeight, 8);
|
| 1694 |
-
const subPeak = new THREE.Mesh(subPeakGeometry, mainPeakMaterial);
|
| 1695 |
-
|
| 1696 |
-
// λ©μΈ λ΄μ°λ¦¬ μ£Όλ³μ λ°°μΉ
|
| 1697 |
-
const offsetAngle = (j / subPeakCount) * Math.PI * 2;
|
| 1698 |
-
const offsetDistance = mainPeakWidth * (0.6 + Math.random() * 0.4);
|
| 1699 |
-
|
| 1700 |
-
subPeak.position.set(
|
| 1701 |
-
Math.cos(offsetAngle) * offsetDistance,
|
| 1702 |
-
-mainPeakHeight * 0.3,
|
| 1703 |
-
Math.sin(offsetAngle) * offsetDistance
|
| 1704 |
-
);
|
| 1705 |
-
|
| 1706 |
-
mountainGroup.add(subPeak);
|
| 1707 |
-
}
|
| 1708 |
-
|
| 1709 |
-
// μ° κΈ°λ°λΆ (λ μμ°μ€λ¬μ΄ κ²½μ¬)
|
| 1710 |
-
const baseGeometry = new THREE.CylinderGeometry(
|
| 1711 |
-
mainPeakWidth * 1.5,
|
| 1712 |
-
mainPeakWidth * 2.5,
|
| 1713 |
-
mainPeakHeight * 0.3,
|
| 1714 |
-
12
|
| 1715 |
-
);
|
| 1716 |
-
const baseMaterial = new THREE.MeshLambertMaterial({
|
| 1717 |
-
color: new THREE.Color(range.color).multiplyScalar(0.8),
|
| 1718 |
-
flatShading: true,
|
| 1719 |
-
fog: true
|
| 1720 |
-
});
|
| 1721 |
-
const base = new THREE.Mesh(baseGeometry, baseMaterial);
|
| 1722 |
-
base.position.y = -mainPeakHeight * 0.35;
|
| 1723 |
-
mountainGroup.add(base);
|
| 1724 |
-
|
| 1725 |
-
// μ° κ·Έλ£Ή μμΉ μ€μ
|
| 1726 |
-
mountainGroup.position.set(
|
| 1727 |
-
Math.cos(angle) * distance,
|
| 1728 |
-
mainPeakHeight * 0.5,
|
| 1729 |
-
Math.sin(angle) * distance
|
| 1730 |
-
);
|
| 1731 |
-
|
| 1732 |
-
// μ½κ°μ λλ€ νμ
|
| 1733 |
-
mountainGroup.rotation.y = Math.random() * Math.PI;
|
| 1734 |
-
|
| 1735 |
-
// κ±°λ¦¬λ³ μμ: λ©λ¦¬ μλ μ°μΌμλ‘ λ νΈλ₯ΈμμΌλ‘ 보μ΄λλ‘ μ€μ
|
| 1736 |
-
mountainGroup.layers.set(0);
|
| 1737 |
-
|
| 1738 |
-
this.scene.add(mountainGroup);
|
| 1739 |
-
}
|
| 1740 |
-
});
|
| 1741 |
-
|
| 1742 |
-
// κ°μ₯ λ¨Ό 거리μ κ±°λν μ°λ§₯ μ€λ£¨μ£ μΆκ°
|
| 1743 |
-
this.createDistantMountainSilhouette();
|
| 1744 |
-
}
|
| 1745 |
-
|
| 1746 |
-
createDistantMountainSilhouette() {
|
| 1747 |
-
// μ거리 μ°λ§₯ μ€λ£¨μ£ (2D νλ©΄)
|
| 1748 |
-
const silhouetteDistance = GAME_CONSTANTS.MAP_SIZE * 1.2;
|
| 1749 |
-
const segments = 50;
|
| 1750 |
-
|
| 1751 |
-
for (let side = 0; side < 4; side++) {
|
| 1752 |
-
const curve = new THREE.CatmullRomCurve3([]);
|
| 1753 |
-
|
| 1754 |
-
// μ°λ§₯ μ€λ£¨μ£ 곑μ μμ±
|
| 1755 |
-
for (let i = 0; i <= segments; i++) {
|
| 1756 |
-
const t = i / segments;
|
| 1757 |
-
const x = (t - 0.5) * GAME_CONSTANTS.MAP_SIZE;
|
| 1758 |
-
const baseHeight = 3000;
|
| 1759 |
-
const variation = Math.sin(t * Math.PI * 3) * 2000 +
|
| 1760 |
-
Math.sin(t * Math.PI * 7) * 1000 +
|
| 1761 |
-
Math.sin(t * Math.PI * 13) * 500;
|
| 1762 |
-
const y = baseHeight + variation + Math.random() * 500;
|
| 1763 |
-
|
| 1764 |
-
curve.points.push(new THREE.Vector3(x, y, 0));
|
| 1765 |
-
}
|
| 1766 |
-
|
| 1767 |
-
// μ€λ£¨μ£ λ©μ μμ±
|
| 1768 |
-
const points = curve.getPoints(100);
|
| 1769 |
-
const shape = new THREE.Shape();
|
| 1770 |
-
|
| 1771 |
-
shape.moveTo(points[0].x, 0);
|
| 1772 |
-
points.forEach(p => shape.lineTo(p.x, p.y));
|
| 1773 |
-
shape.lineTo(points[points.length - 1].x, 0);
|
| 1774 |
-
shape.lineTo(points[0].x, 0);
|
| 1775 |
-
|
| 1776 |
-
const silhouetteGeometry = new THREE.ShapeGeometry(shape);
|
| 1777 |
-
const silhouetteMaterial = new THREE.MeshBasicMaterial({
|
| 1778 |
-
color: 0x2a3b4a,
|
| 1779 |
-
side: THREE.DoubleSide,
|
| 1780 |
-
fog: true,
|
| 1781 |
-
transparent: true,
|
| 1782 |
-
opacity: 0.7
|
| 1783 |
-
});
|
| 1784 |
-
|
| 1785 |
-
const silhouette = new THREE.Mesh(silhouetteGeometry, silhouetteMaterial);
|
| 1786 |
-
|
| 1787 |
-
// κ° λ©΄μ λ°°μΉ
|
| 1788 |
-
const angle = (side / 4) * Math.PI * 2;
|
| 1789 |
-
silhouette.position.set(
|
| 1790 |
-
Math.cos(angle) * silhouetteDistance,
|
| 1791 |
-
0,
|
| 1792 |
-
Math.sin(angle) * silhouetteDistance
|
| 1793 |
-
);
|
| 1794 |
-
silhouette.lookAt(0, 0, 0);
|
| 1795 |
-
|
| 1796 |
-
this.scene.add(silhouette);
|
| 1797 |
-
}
|
| 1798 |
-
}
|
| 1799 |
|
| 1800 |
addClouds() {
|
| 1801 |
// λ€μΈ΅ κ΅¬λ¦ μμ€ν
|
|
@@ -2051,11 +1488,11 @@ class Game {
|
|
| 2051 |
const rollDegrees = this.fighter.rotation.z * (180 / Math.PI);
|
| 2052 |
hudElement.style.transform = `translate(-50%, -50%) rotate(${-rollDegrees}deg)`;
|
| 2053 |
|
| 2054 |
-
// νΌμΉ λλ μ
λ°μ΄νΈ
|
| 2055 |
const pitchLadder = document.getElementById('pitchLadder');
|
| 2056 |
if (pitchLadder) {
|
| 2057 |
const pitchDegrees = this.fighter.rotation.x * (180 / Math.PI);
|
| 2058 |
-
//
|
| 2059 |
const pitchOffset = -pitchDegrees * 2;
|
| 2060 |
pitchLadder.style.transform = `translateY(${pitchOffset}px)`;
|
| 2061 |
}
|
|
@@ -2164,7 +1601,6 @@ class Game {
|
|
| 2164 |
return { x, y };
|
| 2165 |
}
|
| 2166 |
|
| 2167 |
-
// Game ν΄λμ€μ updateWarnings λ©μλ μμ
|
| 2168 |
updateWarnings() {
|
| 2169 |
// κΈ°μ‘΄ κ²½κ³ λ©μμ§ μ κ±°
|
| 2170 |
const existingWarnings = document.querySelectorAll('.warning-message');
|
|
|
|
| 461 |
this.stallEscapeProgress = 0; // μ€ν¨ μ§μ
μ μ§νλ μ΄κΈ°ν
|
| 462 |
}
|
| 463 |
|
| 464 |
+
// μ€ν¨ νμΆ μ‘°κ±΄
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 465 |
if (this.stallWarning) {
|
| 466 |
+
if (this.escapeKeyPressed) {
|
| 467 |
+
// Fν€λ₯Ό λλ₯΄κ³ μμΌλ©΄ μ§νλ μ¦κ°
|
| 468 |
+
this.stallEscapeProgress += deltaTime;
|
| 469 |
+
|
| 470 |
+
// 2μ΄ μ΄μ λλ₯΄λ©΄ μ€ν¨μμ νμΆ
|
| 471 |
+
if (this.stallEscapeProgress >= 2.0 && speedKnots >= 350) {
|
| 472 |
+
this.stallWarning = false;
|
| 473 |
+
this.stallEscapeProgress = 0;
|
| 474 |
+
// μ€ν¨μμ λ²μ΄λλ©΄ μμΈλ₯Ό μ½κ° μμ ν
|
| 475 |
+
this.targetPitch = Math.max(-0.2, Math.min(0.2, this.targetPitch));
|
| 476 |
+
}
|
| 477 |
} else {
|
| 478 |
+
// Fν€λ₯Ό λμΌλ©΄ μ§νλ κ°μ
|
| 479 |
+
this.stallEscapeProgress = Math.max(0, this.stallEscapeProgress - deltaTime * 2);
|
| 480 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
}
|
| 482 |
|
| 483 |
// μλ λ³ν μ μ©
|
|
|
|
| 1233 |
// κ°μ λ κ΅¬λ¦ μΆκ°
|
| 1234 |
this.addClouds();
|
| 1235 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1236 |
|
| 1237 |
addClouds() {
|
| 1238 |
// λ€μΈ΅ κ΅¬λ¦ μμ€ν
|
|
|
|
| 1488 |
const rollDegrees = this.fighter.rotation.z * (180 / Math.PI);
|
| 1489 |
hudElement.style.transform = `translate(-50%, -50%) rotate(${-rollDegrees}deg)`;
|
| 1490 |
|
| 1491 |
+
// νΌμΉ λλ μ
λ°μ΄νΈ
|
| 1492 |
const pitchLadder = document.getElementById('pitchLadder');
|
| 1493 |
if (pitchLadder) {
|
| 1494 |
const pitchDegrees = this.fighter.rotation.x * (180 / Math.PI);
|
| 1495 |
+
// μμλ₯Ό κ³±ν΄μ λ°λ λ°©ν₯μΌλ‘, 10λλΉ 20ν½μ
|
| 1496 |
const pitchOffset = -pitchDegrees * 2;
|
| 1497 |
pitchLadder.style.transform = `translateY(${pitchOffset}px)`;
|
| 1498 |
}
|
|
|
|
| 1601 |
return { x, y };
|
| 1602 |
}
|
| 1603 |
|
|
|
|
| 1604 |
updateWarnings() {
|
| 1605 |
// κΈ°μ‘΄ κ²½κ³ λ©μμ§ μ κ±°
|
| 1606 |
const existingWarnings = document.querySelectorAll('.warning-message');
|