Spaces:
Running
Running
| <html lang="ko"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>JET FIGHT SIMULATER - FPS Mode</title> | |
| <style> | |
| body { | |
| margin: 0; | |
| overflow: hidden; | |
| background: #000; | |
| font-family: 'Courier New', monospace; | |
| } | |
| #loading { | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| background: rgba(0,0,0,0.8); | |
| padding: 20px; | |
| border-radius: 10px; | |
| z-index: 2000; | |
| text-align: center; | |
| } | |
| .loading-spinner { | |
| width: 50px; | |
| height: 50px; | |
| border: 5px solid #0f0; | |
| border-top: 5px solid transparent; | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| margin: 0 auto 20px; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .loading-text { | |
| color: #0f0; | |
| font-size: 24px; | |
| text-align: center; | |
| } | |
| #gameContainer { | |
| position: relative; | |
| width: 100vw; | |
| height: 100vh; | |
| cursor: none; | |
| } | |
| /* HUD μ 체 컨ν μ΄λ */ | |
| #hudContainer { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| pointer-events: none; | |
| z-index: 1000; | |
| } | |
| /* μ€μ HUD */ | |
| #hudCrosshair { | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 400px; | |
| height: 400px; | |
| } | |
| /* μ‘°μ€ μ */ | |
| .hud-aiming-circle { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 150px; | |
| height: 150px; | |
| border: 2px solid rgba(0, 255, 0, 0.5); | |
| border-radius: 50%; | |
| } | |
| /* μ€μμ */ | |
| .hud-center-dot { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 4px; | |
| height: 4px; | |
| background: #00ff00; | |
| border-radius: 50%; | |
| } | |
| /* μνμ */ | |
| .hud-horizon-line { | |
| position: absolute; | |
| top: 50%; | |
| left: 20%; | |
| right: 20%; | |
| height: 1px; | |
| background: rgba(0, 255, 0, 0.4); | |
| } | |
| /* νΌμΉ λλ 컨ν μ΄λ */ | |
| .hud-pitch-ladder { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 200px; | |
| height: 400px; | |
| } | |
| .pitch-line { | |
| position: absolute; | |
| width: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .pitch-line-bar { | |
| width: 60px; | |
| height: 1px; | |
| background: rgba(0, 255, 0, 0.4); | |
| } | |
| .pitch-line-text { | |
| position: absolute; | |
| color: rgba(0, 255, 0, 0.6); | |
| font-size: 10px; | |
| left: -25px; | |
| } | |
| /* μ€μ HUD μ 보 νμ - μλ‘μ΄ μ€νμΌ */ | |
| .hud-central-info { | |
| position: absolute; | |
| color: #00ff00; | |
| font-size: 11px; | |
| font-family: 'Courier New', monospace; | |
| text-shadow: 0 0 3px rgba(0, 0, 0, 0.8); | |
| background: rgba(0, 0, 0, 0.3); | |
| padding: 2px 5px; | |
| border-radius: 2px; | |
| } | |
| /* μ€μ HUD λ΄ μλ νμ */ | |
| #hudSpeedCentral { | |
| left: -120px; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| } | |
| /* μ€μ HUD λ΄ κ³ λ νμ */ | |
| #hudAltitudeCentral { | |
| right: -120px; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| } | |
| /* μ€μ HUD λ΄ ν€λ© νμ */ | |
| #hudHeadingCentral { | |
| top: -30px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| } | |
| /* μ€μ HUD λ΄ G-Force νμ */ | |
| #hudGForceCentral { | |
| bottom: -30px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| } | |
| /* μ€μ HUD λ΄ μ€λ‘ν νμ */ | |
| #hudThrottleCentral { | |
| left: -120px; | |
| top: calc(50% + 25px); | |
| } | |
| /* νκ² λ§μ»€ */ | |
| .target-marker { | |
| position: absolute; | |
| width: 30px; | |
| height: 30px; | |
| border: 2px solid transparent; | |
| transform: translate(-50%, -50%); | |
| } | |
| .target-marker.in-crosshair { | |
| border: 2px solid #ffff00; | |
| animation: target-pulse 0.5s infinite; | |
| } | |
| .target-marker.locked { | |
| border: 2px solid #ff0000; | |
| box-shadow: 0 0 10px #ff0000; | |
| } | |
| .target-marker .target-box { | |
| position: absolute; | |
| top: -5px; | |
| left: -5px; | |
| right: -5px; | |
| bottom: -5px; | |
| border: 1px solid currentColor; | |
| } | |
| @keyframes target-pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| } | |
| .target-info { | |
| position: absolute; | |
| top: 100%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| color: #00ff00; | |
| font-size: 10px; | |
| white-space: nowrap; | |
| margin-top: 5px; | |
| } | |
| #healthBar { | |
| position: absolute; | |
| bottom: 20px; | |
| left: 20px; | |
| width: 200px; | |
| height: 20px; | |
| background: rgba(0,20,0,0.7); | |
| border: 2px solid #0f0; | |
| z-index: 1001; | |
| border-radius: 10px; | |
| overflow: hidden; | |
| } | |
| #health { | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(90deg, #0f0, #00ff00); | |
| transition: width 0.3s; | |
| } | |
| #gameTitle { | |
| position: absolute; | |
| top: 60px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| color: #0f0; | |
| background: rgba(0,20,0,0.7); | |
| padding: 10px 20px; | |
| font-size: 20px; | |
| z-index: 1001; | |
| border: 1px solid #0f0; | |
| border-radius: 5px; | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| } | |
| #ammoDisplay { | |
| position: absolute; | |
| bottom: 20px; | |
| right: 20px; | |
| color: #0f0; | |
| background: rgba(0,20,0,0.7); | |
| padding: 10px; | |
| font-size: 20px; | |
| z-index: 1001; | |
| border: 1px solid #0f0; | |
| border-radius: 5px; | |
| } | |
| #radar { | |
| position: absolute; | |
| bottom: 60px; | |
| left: 20px; | |
| width: 200px; | |
| height: 200px; | |
| background: rgba(30, 30, 30, 0.9); /* λ μ΄λμ΄ νμ λ°°κ²½ */ | |
| border: 2px solid #0f0; | |
| border-radius: 50%; | |
| z-index: 1001; | |
| overflow: hidden; | |
| } | |
| /* RWR λμ€νλ μ΄ μ€νμΌ */ | |
| .rwr-display { | |
| position: relative; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| /* RWR μ€μ ν곡기 μ¬λ³Ό */ | |
| .rwr-center { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 15px; /* λ μκ² */ | |
| height: 15px; /* λ μκ² */ | |
| z-index: 10; | |
| } | |
| .rwr-aircraft-symbol { | |
| width: 100%; | |
| height: 100%; | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .rwr-aircraft-symbol img { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: contain; | |
| filter: drop-shadow(0 0 2px #00ff00); /* μ΄λ‘μ λΉλλ ν¨κ³Ό */ | |
| } | |
| /* RWR 거리 λ§ */ | |
| .rwr-range-ring { | |
| position: absolute; | |
| border: 1px solid rgba(0, 255, 0, 0.4); | |
| border-radius: 50%; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| .rwr-ring-inner { | |
| width: 60px; | |
| height: 60px; | |
| } | |
| .rwr-ring-middle { | |
| width: 120px; | |
| height: 120px; | |
| } | |
| .rwr-ring-outer { | |
| width: 180px; | |
| height: 180px; | |
| } | |
| /* RWR μ€μμ μμ μ μΆκ° */ | |
| .rwr-center-dot { | |
| position: absolute; | |
| top: calc(50% + 4px); /* 4px μλλ‘ μ΄λ */ | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 4px; | |
| height: 4px; | |
| background: #00ff00; | |
| border-radius: 50%; | |
| z-index: 11; | |
| } | |
| /* RWR λ°©ν₯ νμ */ | |
| .rwr-direction-marks { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .rwr-direction-text { | |
| position: absolute; | |
| color: #0f0; | |
| font-size: 12px; | |
| font-weight: bold; | |
| transform: translate(-50%, -50%); | |
| text-shadow: 0 0 2px #0f0; | |
| } | |
| .rwr-north { | |
| top: 15px; | |
| left: 50%; | |
| } | |
| .rwr-east { | |
| top: 50%; | |
| right: 15px; | |
| left: auto; | |
| transform: translateY(-50%); | |
| } | |
| .rwr-south { | |
| bottom: 15px; | |
| left: 50%; | |
| top: auto; | |
| transform: translateX(-50%); | |
| } | |
| .rwr-west { | |
| top: 50%; | |
| left: 15px; | |
| } | |
| /* RWR μν νμ */ | |
| .rwr-threat { | |
| position: absolute; | |
| width: 15px; | |
| height: 15px; | |
| transform: translate(-50%, -50%); | |
| text-align: center; | |
| font-size: 10px; | |
| font-weight: bold; | |
| z-index: 5; | |
| } | |
| /* μν λ λ²¨λ³ μμ */ | |
| .rwr-threat.level-low { | |
| color: #ffff00; /* λ Έλμ */ | |
| text-shadow: 0 0 3px #ffff00; | |
| } | |
| .rwr-threat.level-medium { | |
| color: #ff8800; /* μ£Όν©μ */ | |
| text-shadow: 0 0 3px #ff8800; | |
| } | |
| .rwr-threat.level-high { | |
| color: #ff0000; /* λΉ¨κ°μ */ | |
| text-shadow: 0 0 3px #ff0000; | |
| } | |
| .rwr-threat.missile-lock { | |
| animation: rwr-flash 0.3s infinite; | |
| } | |
| @keyframes rwr-flash { | |
| 0%, 50% { opacity: 1; } | |
| 51%, 100% { opacity: 0.3; } | |
| } | |
| #mission { | |
| position: absolute; | |
| top: 10px; | |
| left: 10px; | |
| color: #0f0; | |
| background: rgba(0,20,0,0.7); | |
| padding: 10px; | |
| font-size: 16px; | |
| z-index: 1001; | |
| border: 1px solid #0f0; | |
| border-radius: 5px; | |
| } | |
| #radarLine { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| width: 50%; | |
| height: 2px; | |
| background: #0f0; | |
| transform-origin: left center; | |
| animation: radar-sweep 4s infinite linear; | |
| } | |
| .enemy-dot { | |
| position: absolute; | |
| width: 6px; | |
| height: 6px; | |
| background: #ff0000; | |
| border-radius: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| @keyframes radar-sweep { | |
| from { | |
| transform: rotate(0deg); | |
| } | |
| to { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| #gameStats { | |
| position: absolute; | |
| top: 10px; | |
| right: 20px; | |
| color: #0f0; | |
| background: rgba(0,20,0,0.7); | |
| padding: 10px; | |
| font-size: 16px; | |
| z-index: 1001; | |
| border: 1px solid #0f0; | |
| border-radius: 5px; | |
| text-align: right; | |
| } | |
| .start-screen { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0,0,0,0.8); | |
| display: none; | |
| justify-content: center; | |
| align-items: center; | |
| flex-direction: column; | |
| z-index: 2000; | |
| } | |
| .start-button { | |
| padding: 15px 30px; | |
| font-size: 24px; | |
| background: #0f0; | |
| color: #000; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| margin-top: 20px; | |
| transition: transform 0.2s; | |
| } | |
| .start-button:hover { | |
| transform: scale(1.1); | |
| } | |
| /* κΈ°μ‘΄ κ°λ³ HUD μ 보λ€μ μ¨κΉ */ | |
| #hudSpeed, #hudAltitude, #hudHeading, #hudPitch, #hudRoll, #hudTurnRate { | |
| display: none; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- λ‘λ© νλ©΄ --> | |
| <div id="loading"> | |
| <div class="loading-spinner"></div> | |
| <div class="loading-text">Loading Fighter Resources...</div> | |
| <div style="color: #0f0; font-size: 16px; margin-top: 10px;"> | |
| <p>Loading Aircraft Models...</p> | |
| <p>Loading Audio Assets...</p> | |
| <p>Preparing Game Environment...</p> | |
| </div> | |
| </div> | |
| <!-- κ²μ μμ νλ©΄ --> | |
| <div class="start-screen" id="startScreen"> | |
| <h1 style="color: #0f0; font-size: 48px; margin-bottom: 20px;">JET FIGHT SIMULATER</h1> | |
| <button class="start-button" onclick="startGame()">Start Game</button> | |
| <div style="color: #0f0; margin-top: 20px; text-align: center;"> | |
| <p>Controls:</p> | |
| <p>W/S - Throttle Control</p> | |
| <p>A/D - Rudder Control</p> | |
| <p>Mouse - Aircraft Control</p> | |
| <p>Left Click - Fire</p> | |
| <p>F - Escape Stall</p> | |
| </div> | |
| </div> | |
| <!-- κ²μ νλ©΄ --> | |
| <div id="gameContainer"> | |
| <!-- κ²μ νμ΄ν (κ²μ μμ μ μ¨κ²¨μ§) --> | |
| <div id="gameTitle" style="display: none;">JET FIGHT SIMULATER</div> | |
| <div id="mission">MISSION: DESTROY ENEMY JET</div> | |
| <div id="gameStats"> | |
| <div id="score">Score: 0</div> | |
| <div id="time">Time: 180s</div> | |
| </div> | |
| <!-- HUD 컨ν μ΄λ --> | |
| <div id="hudContainer"> | |
| <!-- μ€μ HUD --> | |
| <div id="hudCrosshair"> | |
| <div class="hud-aiming-circle"></div> | |
| <div class="hud-center-dot"></div> | |
| <div class="hud-horizon-line"></div> | |
| <!-- μ€μ HUD μ 보 νμ --> | |
| <div class="hud-central-info" id="hudSpeedCentral">SPD: 0 KT</div> | |
| <div class="hud-central-info" id="hudAltitudeCentral">ALT: 0 M</div> | |
| <div class="hud-central-info" id="hudHeadingCentral">HDG: 000Β°</div> | |
| <div class="hud-central-info" id="hudGForceCentral">G: 1.0</div> | |
| <div class="hud-central-info" id="hudThrottleCentral">THR: 60%</div> | |
| <!-- νΌμΉ λλ --> | |
| <div class="hud-pitch-ladder" id="pitchLadder"> | |
| <!-- 10λλΉ 20ν½μ κ°κ²© --> | |
| <div class="pitch-line" style="top: calc(50% - 80px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">40</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% - 60px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">30</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% - 40px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">20</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% - 20px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">10</span> | |
| </div> | |
| <!-- 0λ λΌμΈ - μ νν μ€μ --> | |
| <div class="pitch-line" style="top: 50%;"> | |
| <div class="pitch-line-bar" style="width: 100px; height: 2px; background: rgba(0, 255, 0, 0.8);"></div> | |
| <span class="pitch-line-text" style="color: rgba(0, 255, 0, 0.8); font-weight: bold;">0</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% + 20px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">-10</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% + 40px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">-20</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% + 60px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">-30</span> | |
| </div> | |
| <div class="pitch-line" style="top: calc(50% + 80px);"> | |
| <div class="pitch-line-bar"></div> | |
| <span class="pitch-line-text">-40</span> | |
| </div> | |
| </div> | |
| <!-- λ‘€ μΈλμΌμ΄ν° (μ’/μ° κΈ°μΈκΈ°) - ν¬λ‘μ€ν€μ΄ λ°λ‘ μ --> | |
| <div class="hud-roll-indicator" id="rollIndicator" style=" | |
| position: absolute; | |
| top: -90px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 300px; | |
| height: 35px; | |
| "> | |
| <!-- λ‘€ κ°λ νμ --> | |
| <div style="position: relative; width: 100%; height: 100%;"> | |
| <!-- μ€μ λ§μ»€ --> | |
| <div style=" | |
| position: absolute; | |
| top: 0; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 0; | |
| height: 0; | |
| border-left: 12px solid transparent; | |
| border-right: 12px solid transparent; | |
| border-top: 18px solid #00ff00; | |
| z-index: 2; | |
| "></div> | |
| <!-- λ‘€ μ€μΌμΌ λ°°κ²½ --> | |
| <div style=" | |
| position: absolute; | |
| bottom: 5px; | |
| left: 0; | |
| right: 0; | |
| height: 15px; | |
| background: rgba(0, 0, 0, 0.3); | |
| border: 1px solid rgba(0, 255, 0, 0.3); | |
| border-radius: 3px; | |
| "></div> | |
| <!-- μν ꡬμ νμ (Β±30λ μ΄μ) --> | |
| <div style=" | |
| position: absolute; | |
| bottom: 5px; | |
| left: 0; | |
| width: 25%; | |
| height: 15px; | |
| background: rgba(255, 0, 0, 0.2); | |
| border-radius: 3px 0 0 3px; | |
| "></div> | |
| <div style=" | |
| position: absolute; | |
| bottom: 5px; | |
| right: 0; | |
| width: 25%; | |
| height: 15px; | |
| background: rgba(255, 0, 0, 0.2); | |
| border-radius: 0 3px 3px 0; | |
| "></div> | |
| <!-- λ‘€ μ€μΌμΌ --> | |
| <div style=" | |
| position: absolute; | |
| bottom: 22px; | |
| width: 100%; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-end; | |
| padding: 0 10px; | |
| box-sizing: border-box; | |
| "> | |
| <div style="color: rgba(255, 0, 0, 0.7); font-size: 10px; font-weight: bold;">-60</div> | |
| <div style="position: absolute; left: 25%; transform: translateX(-50%); width: 1px; height: 10px; background: rgba(255, 255, 0, 0.6);"></div> | |
| <div style="position: absolute; left: 25%; transform: translateX(-50%); color: rgba(255, 255, 0, 0.7); font-size: 10px; top: -15px;">-30</div> | |
| <div style="position: absolute; left: 50%; transform: translateX(-50%); width: 2px; height: 12px; background: rgba(0, 255, 0, 0.8);"></div> | |
| <div style="position: absolute; left: 50%; transform: translateX(-50%); color: rgba(0, 255, 0, 1); font-size: 11px; font-weight: bold; top: -15px;">0</div> | |
| <div style="position: absolute; left: 75%; transform: translateX(-50%); width: 1px; height: 10px; background: rgba(255, 255, 0, 0.6);"></div> | |
| <div style="position: absolute; left: 75%; transform: translateX(-50%); color: rgba(255, 255, 0, 0.7); font-size: 10px; top: -15px;">30</div> | |
| <div style="color: rgba(255, 0, 0, 0.7); font-size: 10px; font-weight: bold;">60</div> | |
| </div> | |
| <!-- νμ¬ λ‘€ νμ --> | |
| <div id="currentRollMarker" style=" | |
| position: absolute; | |
| bottom: 5px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 3px; | |
| height: 15px; | |
| background: #00ff00; | |
| transition: left 0.1s; | |
| box-shadow: 0 0 5px #00ff00; | |
| "></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- κΈ°μ‘΄ λΉν μ 보 (μ¨κΉ) --> | |
| <div class="hud-info" id="hudSpeed">SPD: 0 KT</div> | |
| <div class="hud-info" id="hudAltitude">ALT: 0 M</div> | |
| <div class="hud-info" id="hudHeading">HDG: 000Β°</div> | |
| <div class="hud-info" id="hudPitch">PITCH: 0Β°</div> | |
| <div class="hud-info" id="hudRoll">ROLL: 0Β°</div> | |
| <div class="hud-info" id="hudTurnRate">TURN: 0Β°/s</div> | |
| <!-- νκ² λ§μ»€ λ μ΄μ΄ --> | |
| <div id="targetMarkers"></div> | |
| </div> | |
| <!-- 체λ ₯λ° --> | |
| <div id="healthBar"> | |
| <div id="health"></div> | |
| </div> | |
| <!-- νμ½ νμ --> | |
| <div id="ammoDisplay">AMMO: 300</div> | |
| <!-- λ μ΄λ (RWR) --> | |
| <div id="radar"> | |
| <div class="rwr-display"> | |
| <!-- RWR 거리 λ§ --> | |
| <div class="rwr-range-ring rwr-ring-inner"></div> | |
| <div class="rwr-range-ring rwr-ring-middle"></div> | |
| <div class="rwr-range-ring rwr-ring-outer"></div> | |
| <!-- λ°©ν₯ νμ --> | |
| <div class="rwr-direction-marks"> | |
| <div class="rwr-direction-text rwr-north">N</div> | |
| <div class="rwr-direction-text rwr-east">E</div> | |
| <div class="rwr-direction-text rwr-south">S</div> | |
| <div class="rwr-direction-text rwr-west">W</div> | |
| </div> | |
| <!-- μ€μ ν곡기 μ¬λ³Ό --> | |
| <div class="rwr-center"> | |
| <div class="rwr-aircraft-symbol" id="rwrSymbol"> | |
| <!-- μ΄λ―Έμ§λ JavaScriptλ‘ λ‘λ --> | |
| </div> | |
| </div> | |
| <!-- μ€μ μ --> | |
| <div class="rwr-center-dot"></div> | |
| <!-- μν νμ μμ --> | |
| <div id="rwrThreats"></div> | |
| </div> | |
| <!-- κΈ°μ‘΄ λ μ΄λ μμ (μ¨κΉ) --> | |
| <div id="radarLine" style="display: none;"></div> | |
| </div> | |
| </div> | |
| <script type="importmap"> | |
| { | |
| "imports": { | |
| "three": "https://unpkg.com/[email protected]/build/three.module.js", | |
| "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/" | |
| } | |
| } | |
| </script> | |
| <!-- νΌμΉ λλ λ° HUD μ λ°μ΄νΈ μ€ν¬λ¦½νΈ --> | |
| <script> | |
| // μ μ λ³μ | |
| let gameStarted = false; | |
| // κ²μ μ€λΉ μλ£ μ HUD μ λ°μ΄νΈ μμ | |
| window.addEventListener('gameReady', function() { | |
| console.log('Game ready - starting HUD updates'); | |
| // RWR μ¬λ³Ό μ΄λ―Έμ§ λ‘λ | |
| const rwrSymbol = document.getElementById('rwrSymbol'); | |
| if (rwrSymbol) { | |
| // λ°©λ² 1: img νκ·Έλ‘ μλ | |
| const img = new Image(); | |
| img.src = 'effects/symbol.png'; | |
| img.style.width = '100%'; | |
| img.style.height = '100%'; | |
| img.style.objectFit = 'contain'; | |
| img.style.filter = 'drop-shadow(0 0 2px #00ff00)'; // μ΄λ‘μμΌλ‘ λ³κ²½ | |
| img.onload = function() { | |
| console.log('RWR symbol image loaded successfully'); | |
| rwrSymbol.innerHTML = ''; | |
| rwrSymbol.appendChild(img); | |
| }; | |
| img.onerror = function() { | |
| console.log('RWR symbol image failed to load, using fallback'); | |
| // μ΄λ―Έμ§ λ‘λ μ€ν¨μ μμ μ΄λ‘μ μ μΌλ‘ λ체 | |
| rwrSymbol.innerHTML = ` | |
| <div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;"> | |
| <div style="width: 8px; height: 8px; background: #00ff00; border-radius: 50%; box-shadow: 0 0 4px #00ff00;"></div> | |
| </div> | |
| `; | |
| }; | |
| } | |
| // νΌμΉ λλ μ΄κΈ° μμΉ κ°μ μ€μ | |
| setTimeout(function() { | |
| const pitchLadder = document.getElementById('pitchLadder'); | |
| if (pitchLadder) { | |
| // CSSλ‘ μ§μ μμΉ μ‘°μ | |
| pitchLadder.style.position = 'absolute'; | |
| pitchLadder.style.top = 'calc(50% - 200px)'; // 200px μλ‘ μ¬λ¦Ό | |
| pitchLadder.style.left = '50%'; | |
| pitchLadder.style.transform = 'translate(-50%, 0)'; | |
| console.log('Pitch ladder initial position set'); | |
| } | |
| }, 100); | |
| // μ€μ HUD μ 보 μ λ°μ΄νΈλ₯Ό μν μΈν°λ² | |
| setInterval(function() { | |
| if (window.gameInstance && window.gameInstance.fighter && window.gameInstance.fighter.isLoaded) { | |
| const fighter = window.gameInstance.fighter; | |
| // λΉν μ 보 κ³μ° | |
| const speedKnots = Math.round(fighter.speed * 1.94384); | |
| const altitudeMeters = Math.round(fighter.altitude); | |
| const throttlePercent = Math.round(fighter.throttle * 100); | |
| const gForce = fighter.gForce.toFixed(1); | |
| const headingDegrees = Math.round(((fighter.rotation.y * (180 / Math.PI)) + 360) % 360); | |
| // μ€μ HUD μ 보 μ λ°μ΄νΈ | |
| const hudSpeedCentral = document.getElementById('hudSpeedCentral'); | |
| const hudAltitudeCentral = document.getElementById('hudAltitudeCentral'); | |
| const hudHeadingCentral = document.getElementById('hudHeadingCentral'); | |
| const hudGForceCentral = document.getElementById('hudGForceCentral'); | |
| const hudThrottleCentral = document.getElementById('hudThrottleCentral'); | |
| if (hudSpeedCentral) hudSpeedCentral.textContent = `SPD: ${speedKnots} KT`; | |
| if (hudAltitudeCentral) hudAltitudeCentral.textContent = `ALT: ${altitudeMeters} M`; | |
| if (hudHeadingCentral) hudHeadingCentral.textContent = `HDG: ${String(headingDegrees).padStart(3, '0')}Β°`; | |
| if (hudGForceCentral) { | |
| hudGForceCentral.textContent = `G: ${gForce}`; | |
| // G-Forceμ λ°λ₯Έ μμ λ³κ²½ | |
| if (fighter.overG) { | |
| hudGForceCentral.style.color = '#ff0000'; | |
| } else if (parseFloat(gForce) > 7) { | |
| hudGForceCentral.style.color = '#ffff00'; | |
| } else { | |
| hudGForceCentral.style.color = '#00ff00'; | |
| } | |
| } | |
| if (hudThrottleCentral) hudThrottleCentral.textContent = `THR: ${throttlePercent}%`; | |
| // νΌμΉ λλ λμ μ λ°μ΄νΈ - κΈ°λ³Έ μμΉμμ νΌμΉ κ°λλ§νΌ μ΄λ | |
| const pitchLadder = document.getElementById('pitchLadder'); | |
| if (pitchLadder) { | |
| const pitchDegrees = fighter.rotation.x * (180 / Math.PI); | |
| // 10λλΉ 20ν½μ , μμλ‘ λ°λ λ°©ν₯ | |
| const pitchOffset = -200 + (-pitchDegrees * 2); | |
| pitchLadder.style.top = `calc(50% + ${pitchOffset}px)`; | |
| } | |
| // HUD ν¬λ‘μ€ν€μ΄ νμ (λ‘€ κ°λμ λ°λΌ) | |
| const hudCrosshair = document.getElementById('hudCrosshair'); | |
| if (hudCrosshair && fighter.rotation) { | |
| const rollDegrees = fighter.rotation.z * (180 / Math.PI); | |
| hudCrosshair.style.transform = `translate(-50%, -50%) rotate(${-rollDegrees}deg)`; | |
| } | |
| // λ‘€ μΈλμΌμ΄ν° μ λ°μ΄νΈ | |
| const currentRollMarker = document.getElementById('currentRollMarker'); | |
| const rollIndicator = document.getElementById('rollIndicator'); | |
| if (currentRollMarker && fighter.rotation) { | |
| const rollDegrees = fighter.rotation.z * (180 / Math.PI); | |
| // -60λμμ +60λ λ²μλ₯Ό μ 체 λλΉμ λ°±λΆμ¨λ‘ λ§€ν | |
| // 300px λλΉμμ μμͺ½ 10px ν¨λ©μ λΊ 280px μ¬μ© | |
| const normalizedRoll = (rollDegrees + 60) / 120; // 0~1 λ²μλ‘ μ κ·ν | |
| const markerPosition = 10 + (normalizedRoll * 280); // 10px ~ 290px | |
| currentRollMarker.style.left = `${markerPosition}px`; | |
| currentRollMarker.style.transform = 'translateX(-50%)'; | |
| // λ‘€μ΄ Β±30λλ₯Ό μ΄κ³Όνλ©΄ μμ λ³κ²½ | |
| if (Math.abs(rollDegrees) > 30) { | |
| currentRollMarker.style.background = '#ff0000'; | |
| currentRollMarker.style.boxShadow = '0 0 8px #ff0000'; | |
| currentRollMarker.style.width = '4px'; | |
| } else { | |
| currentRollMarker.style.background = '#00ff00'; | |
| currentRollMarker.style.boxShadow = '0 0 5px #00ff00'; | |
| currentRollMarker.style.width = '3px'; | |
| } | |
| } | |
| // RWR μ λ°μ΄νΈ | |
| updateRWR(fighter); | |
| } | |
| }, 16); // μ½ 60fps | |
| }); | |
| // RWR μ λ°μ΄νΈ ν¨μ | |
| function updateRWR(fighter) { | |
| const rwrThreats = document.getElementById('rwrThreats'); | |
| if (!rwrThreats || !window.gameInstance) return; | |
| // κΈ°μ‘΄ μν νμ μ κ±° | |
| rwrThreats.innerHTML = ''; | |
| // μ ν곡기 νμ | |
| if (window.gameInstance.enemies) { | |
| window.gameInstance.enemies.forEach((enemy, index) => { | |
| if (!enemy.mesh || !enemy.isLoaded) return; | |
| const distance = fighter.position.distanceTo(enemy.position); | |
| // 10km μ΄λ΄μ μ λ§ RWRμ νμ | |
| if (distance <= 10000) { | |
| // μλ μμΉ κ³μ° | |
| const relativePos = enemy.position.clone().sub(fighter.position); | |
| // μ ν¬κΈ°μ headingμ κ³ λ €ν κ°λ κ³μ° | |
| const angle = Math.atan2(relativePos.x, relativePos.z) - fighter.rotation.y; | |
| // RWR μμ μμΉ κ³μ° (μ΅λ λ°κ²½ 90px) | |
| const maxRadius = 90; | |
| const relativeDistance = Math.min(distance / 10000, 1) * maxRadius; | |
| const x = Math.sin(angle) * relativeDistance + 100; // μ€μμ΄ 100px | |
| const y = -Math.cos(angle) * relativeDistance + 100; | |
| // μν μ¬λ³Ό μμ± | |
| const threat = document.createElement('div'); | |
| threat.className = 'rwr-threat'; | |
| // 거리μ λ°λ₯Έ μν λ 벨 (μ νκ³΅κΈ°λ§ νμ) | |
| if (distance < 2000) { | |
| threat.classList.add('level-high'); | |
| threat.classList.add('missile-lock'); | |
| threat.textContent = 'β'; | |
| } else if (distance < 5000) { | |
| threat.classList.add('level-medium'); | |
| threat.textContent = 'β'; | |
| } else { | |
| threat.classList.add('level-low'); | |
| threat.textContent = 'β'; | |
| } | |
| threat.style.left = `${x}px`; | |
| threat.style.top = `${y}px`; | |
| rwrThreats.appendChild(threat); | |
| } | |
| }); | |
| } | |
| } | |
| // startGame ν¨μ μ μ | |
| window.startGame = function() { | |
| if (!window.gameInstance || !window.gameInstance.isLoaded || !window.gameInstance.isBGMReady) { | |
| console.log('κ²μμ΄ μμ§ μ€λΉλμ§ μμμ΅λλ€...'); | |
| return; | |
| } | |
| gameStarted = true; | |
| document.getElementById('startScreen').style.display = 'none'; | |
| // κ²μ νμ΄ν μ¨κΈ°κΈ° | |
| const gameTitle = document.getElementById('gameTitle'); | |
| if (gameTitle) { | |
| gameTitle.style.display = 'none'; | |
| } | |
| document.body.requestPointerLock(); | |
| window.gameInstance.startBGM(); | |
| window.gameInstance.startGame(); | |
| } | |
| </script> | |
| <script src="game.js" type="module"></script> | |
| </body> | |
| </html> |