Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
@@ -25,7 +25,10 @@ const GAME_CONSTANTS = {
|
|
25 |
AIM9_DAMAGE: 1000, // AIM-9 ๋ฏธ์ฌ์ผ ํผํด 1000!
|
26 |
AIM9_SPEED: 514.4, // 1000kt๋ฅผ m/s๋ก ๋ณํ
|
27 |
AIM9_LOCK_RANGE: 6000, // ๋ฝ์จ ๊ฑฐ๋ฆฌ 6000m
|
28 |
-
AIM9_LOCK_REQUIRED: 3 // 3๋ฒ ๋ฝ์จ ํ์
|
|
|
|
|
|
|
29 |
};
|
30 |
|
31 |
// ์ ํฌ๊ธฐ ํด๋์ค
|
@@ -108,9 +111,16 @@ class Fighter {
|
|
108 |
pullup: null,
|
109 |
overg: null,
|
110 |
stall: null,
|
111 |
-
normal: null // ์์ง ์๋ฆฌ
|
|
|
|
|
112 |
};
|
113 |
this.initializeWarningAudios();
|
|
|
|
|
|
|
|
|
|
|
114 |
}
|
115 |
|
116 |
// ํค๋ฉ์ 0~360๋๋ก ์ ๊ทํํ๋ ํฌํผ ํจ์
|
@@ -147,9 +157,18 @@ class Fighter {
|
|
147 |
this.warningAudios.normal.volume = 0.5;
|
148 |
this.warningAudios.normal.loop = true; // ์์ง ์๋ฆฌ๋ ๊ณ์ ๋ฐ๋ณต
|
149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
// ๊ฒฝ๊ณ ์์๋ง ended ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ถ๊ฐ (์์ง ์๋ฆฌ ์ ์ธ)
|
151 |
Object.keys(this.warningAudios).forEach(key => {
|
152 |
-
if (key !== 'normal' && this.warningAudios[key]) {
|
153 |
this.warningAudios[key].addEventListener('ended', () => {
|
154 |
this.updateWarningAudios();
|
155 |
});
|
@@ -185,6 +204,35 @@ class Fighter {
|
|
185 |
updateWarningAudios() {
|
186 |
let currentWarning = null;
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
if (this.altitude < 250) {
|
189 |
currentWarning = 'pullup';
|
190 |
}
|
@@ -198,9 +246,10 @@ class Fighter {
|
|
198 |
currentWarning = 'stall';
|
199 |
}
|
200 |
|
201 |
-
// ๊ฒฝ๊ณ ์๋ง ๊ด๋ฆฌ (์์ง
|
202 |
Object.keys(this.warningAudios).forEach(key => {
|
203 |
-
if (key !== 'normal' && key !==
|
|
|
204 |
this.warningAudios[key].pause();
|
205 |
this.warningAudios[key].currentTime = 0;
|
206 |
}
|
@@ -1616,6 +1665,15 @@ class EnemyFighter {
|
|
1616 |
this.nearbyEnemies = [];
|
1617 |
this.avoidanceVector = new THREE.Vector3();
|
1618 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1619 |
// ์ด๊ธฐ ๋ชฉํ ์ค์
|
1620 |
this.selectNewPatrolTarget();
|
1621 |
}
|
@@ -1711,6 +1769,14 @@ update(playerPosition, deltaTime) {
|
|
1711 |
|
1712 |
// ํํ ์
๋ฐ์ดํธ
|
1713 |
this.updateBullets(deltaTime);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1714 |
}
|
1715 |
|
1716 |
executePatrol(deltaTime) {
|
@@ -1732,7 +1798,6 @@ update(playerPosition, deltaTime) {
|
|
1732 |
executeCombat(playerPosition, deltaTime) {
|
1733 |
const distance = this.position.distanceTo(playerPosition);
|
1734 |
|
1735 |
-
|
1736 |
// ํ๋ ์ด์ด๋ฅผ ํฅํด ํ์
|
1737 |
this.smoothTurnToTarget(playerPosition, deltaTime);
|
1738 |
|
@@ -2093,6 +2158,136 @@ update(playerPosition, deltaTime) {
|
|
2093 |
}
|
2094 |
}
|
2095 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2096 |
calculateAimAccuracy(target) {
|
2097 |
const toTarget = target.clone().sub(this.position).normalize();
|
2098 |
const forward = new THREE.Vector3(0, 0, 1).applyEuler(this.rotation);
|
@@ -2152,6 +2347,8 @@ update(playerPosition, deltaTime) {
|
|
2152 |
this.scene.remove(this.mesh);
|
2153 |
this.bullets.forEach(bullet => this.scene.remove(bullet));
|
2154 |
this.bullets = [];
|
|
|
|
|
2155 |
this.isLoaded = false;
|
2156 |
}
|
2157 |
}
|
@@ -2565,6 +2762,50 @@ class Game {
|
|
2565 |
}, 1000);
|
2566 |
}
|
2567 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2568 |
updateUI() {
|
2569 |
if (this.fighter.isLoaded) {
|
2570 |
const speedKnots = Math.round(this.fighter.speed * 1.94384);
|
@@ -2781,9 +3022,60 @@ class Game {
|
|
2781 |
const existingStallWarnings = document.querySelectorAll('.stall-escape-warning');
|
2782 |
existingStallWarnings.forEach(w => w.remove());
|
2783 |
|
|
|
|
|
|
|
|
|
2784 |
// ๊ณ ๋ ๊ฒฝ๊ณ ์ธ๊ณฝ ํจ๊ณผ
|
2785 |
let altitudeEdgeEffect = document.getElementById('altitudeEdgeEffect');
|
2786 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2787 |
if (!altitudeEdgeEffect) {
|
2788 |
altitudeEdgeEffect = document.createElement('div');
|
2789 |
altitudeEdgeEffect.id = 'altitudeEdgeEffect';
|
@@ -2940,6 +3232,18 @@ class Game {
|
|
2940 |
opacity: 0.7;
|
2941 |
}
|
2942 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2943 |
`;
|
2944 |
document.head.appendChild(style);
|
2945 |
}
|
@@ -3216,33 +3520,6 @@ class Game {
|
|
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 |
// ํ๋ ์ด์ด์ ์ ๊ธฐ์ ์ง์ ์ถฉ๋ ์ฒดํฌ (์ต์ฐ์ )
|
3248 |
for (let i = this.enemies.length - 1; i >= 0; i--) {
|
@@ -3370,6 +3647,11 @@ class Game {
|
|
3370 |
}
|
3371 |
}
|
3372 |
});
|
|
|
|
|
|
|
|
|
|
|
3373 |
}
|
3374 |
|
3375 |
createHitEffect(position) {
|
@@ -3812,7 +4094,7 @@ class Game {
|
|
3812 |
document.exitPointerLock();
|
3813 |
|
3814 |
// ๋ชจ๋ ๊ฒฝ๊ณ ๋ฐ ํจ๊ณผ ์ ๊ฑฐ
|
3815 |
-
const existingWarnings = document.querySelectorAll('.warning-message, .stall-escape-warning');
|
3816 |
existingWarnings.forEach(w => w.remove());
|
3817 |
|
3818 |
const blurEffect = document.getElementById('overGBlurEffect');
|
|
|
25 |
AIM9_DAMAGE: 1000, // AIM-9 ๋ฏธ์ฌ์ผ ํผํด 1000!
|
26 |
AIM9_SPEED: 514.4, // 1000kt๋ฅผ m/s๋ก ๋ณํ
|
27 |
AIM9_LOCK_RANGE: 6000, // ๋ฝ์จ ๊ฑฐ๋ฆฌ 6000m
|
28 |
+
AIM9_LOCK_REQUIRED: 3, // 3๋ฒ ๋ฝ์จ ํ์
|
29 |
+
ENEMY_AIM9_COUNT: 4, // ์ AIM-9 ๋ฏธ์ฌ์ผ ์
|
30 |
+
ENEMY_LOCK_RANGE: 5000, // ์ ๋ฝ์จ ๊ฑฐ๋ฆฌ
|
31 |
+
ENEMY_LOCK_ANGLE: Math.PI / 12 // ์ ๋ฝ์จ ๊ฐ๋ (15๋)
|
32 |
};
|
33 |
|
34 |
// ์ ํฌ๊ธฐ ํด๋์ค
|
|
|
111 |
pullup: null,
|
112 |
overg: null,
|
113 |
stall: null,
|
114 |
+
normal: null, // ์์ง ์๋ฆฌ
|
115 |
+
missileLock: null,
|
116 |
+
missileIncoming: null
|
117 |
};
|
118 |
this.initializeWarningAudios();
|
119 |
+
|
120 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ์์คํ
|
121 |
+
this.incomingMissiles = []; // ํ๋ ์ด์ด๋ฅผ ํฅํด ๋ ์์ค๋ ๋ฏธ์ฌ์ผ
|
122 |
+
this.missileWarningActive = false;
|
123 |
+
this.beingLockedBy = []; // ๋ฝ์จ ์ค์ธ ์ ๋ค
|
124 |
}
|
125 |
|
126 |
// ํค๋ฉ์ 0~360๋๋ก ์ ๊ทํํ๋ ํฌํผ ํจ์
|
|
|
157 |
this.warningAudios.normal.volume = 0.5;
|
158 |
this.warningAudios.normal.loop = true; // ์์ง ์๋ฆฌ๋ ๊ณ์ ๋ฐ๋ณต
|
159 |
|
160 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ์ ์ถ๊ฐ
|
161 |
+
this.warningAudios.missileLock = new Audio('sounds/missile2.ogg');
|
162 |
+
this.warningAudios.missileLock.volume = 0.8;
|
163 |
+
this.warningAudios.missileLock.loop = true;
|
164 |
+
|
165 |
+
this.warningAudios.missileIncoming = new Audio('sounds/missile3.ogg');
|
166 |
+
this.warningAudios.missileIncoming.volume = 1.0;
|
167 |
+
this.warningAudios.missileIncoming.loop = true;
|
168 |
+
|
169 |
// ๊ฒฝ๊ณ ์์๋ง ended ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ถ๊ฐ (์์ง ์๋ฆฌ ์ ์ธ)
|
170 |
Object.keys(this.warningAudios).forEach(key => {
|
171 |
+
if (key !== 'normal' && key !== 'missileLock' && key !== 'missileIncoming' && this.warningAudios[key]) {
|
172 |
this.warningAudios[key].addEventListener('ended', () => {
|
173 |
this.updateWarningAudios();
|
174 |
});
|
|
|
204 |
updateWarningAudios() {
|
205 |
let currentWarning = null;
|
206 |
|
207 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ๊ฐ ์ต์ฐ์
|
208 |
+
if (this.incomingMissiles.length > 0) {
|
209 |
+
// missileIncoming ์ฌ์
|
210 |
+
if (this.warningAudios.missileIncoming && this.warningAudios.missileIncoming.paused) {
|
211 |
+
this.warningAudios.missileIncoming.play().catch(e => {});
|
212 |
+
}
|
213 |
+
} else {
|
214 |
+
// ๋ฏธ์ฌ์ผ์ด ์์ผ๋ฉด missileIncoming ์ค์ง
|
215 |
+
if (this.warningAudios.missileIncoming && !this.warningAudios.missileIncoming.paused) {
|
216 |
+
this.warningAudios.missileIncoming.pause();
|
217 |
+
this.warningAudios.missileIncoming.currentTime = 0;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
// ๋ฝ์จ ๊ฒฝ๊ณ
|
222 |
+
if (this.beingLockedBy.length > 0 && this.incomingMissiles.length === 0) {
|
223 |
+
// missileLock ์ฌ์
|
224 |
+
if (this.warningAudios.missileLock && this.warningAudios.missileLock.paused) {
|
225 |
+
this.warningAudios.missileLock.play().catch(e => {});
|
226 |
+
}
|
227 |
+
} else {
|
228 |
+
// ๋ฝ์จ์ด ์์ผ๋ฉด missileLock ์ค์ง
|
229 |
+
if (this.warningAudios.missileLock && !this.warningAudios.missileLock.paused) {
|
230 |
+
this.warningAudios.missileLock.pause();
|
231 |
+
this.warningAudios.missileLock.currentTime = 0;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
// ๊ธฐ์กด ๊ฒฝ๊ณ ์ ์ฒ๋ฆฌ
|
236 |
if (this.altitude < 250) {
|
237 |
currentWarning = 'pullup';
|
238 |
}
|
|
|
246 |
currentWarning = 'stall';
|
247 |
}
|
248 |
|
249 |
+
// ๊ฒฝ๊ณ ์๋ง ๊ด๋ฆฌ (์์ง ์๋ฆฌ, ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ์ ์ ์ธ)
|
250 |
Object.keys(this.warningAudios).forEach(key => {
|
251 |
+
if (key !== 'normal' && key !== 'missileLock' && key !== 'missileIncoming' &&
|
252 |
+
key !== currentWarning && this.warningAudios[key] && !this.warningAudios[key].paused) {
|
253 |
this.warningAudios[key].pause();
|
254 |
this.warningAudios[key].currentTime = 0;
|
255 |
}
|
|
|
1665 |
this.nearbyEnemies = [];
|
1666 |
this.avoidanceVector = new THREE.Vector3();
|
1667 |
|
1668 |
+
// AIM-9 ๋ฏธ์ฌ์ผ ์์คํ
|
1669 |
+
this.aim9Missiles = GAME_CONSTANTS.ENEMY_AIM9_COUNT;
|
1670 |
+
this.firedMissiles = [];
|
1671 |
+
this.lockTarget = null;
|
1672 |
+
this.lockProgress = 0;
|
1673 |
+
this.lastLockTime = 0;
|
1674 |
+
this.lastMissileFireTime = 0;
|
1675 |
+
this.isLocking = false;
|
1676 |
+
|
1677 |
// ์ด๊ธฐ ๋ชฉํ ์ค์
|
1678 |
this.selectNewPatrolTarget();
|
1679 |
}
|
|
|
1769 |
|
1770 |
// ํํ ์
๋ฐ์ดํธ
|
1771 |
this.updateBullets(deltaTime);
|
1772 |
+
|
1773 |
+
// ๋ฏธ์ฌ์ผ ์
๋ฐ์ดํธ
|
1774 |
+
this.updateMissiles(deltaTime);
|
1775 |
+
|
1776 |
+
// ๋ฝ์จ ์์คํ
์
๋ฐ์ดํธ
|
1777 |
+
if (this.playerFighter) {
|
1778 |
+
this.updateLockOn(deltaTime);
|
1779 |
+
}
|
1780 |
}
|
1781 |
|
1782 |
executePatrol(deltaTime) {
|
|
|
1798 |
executeCombat(playerPosition, deltaTime) {
|
1799 |
const distance = this.position.distanceTo(playerPosition);
|
1800 |
|
|
|
1801 |
// ํ๋ ์ด์ด๋ฅผ ํฅํด ํ์
|
1802 |
this.smoothTurnToTarget(playerPosition, deltaTime);
|
1803 |
|
|
|
2158 |
}
|
2159 |
}
|
2160 |
|
2161 |
+
updateMissiles(deltaTime) {
|
2162 |
+
for (let i = this.firedMissiles.length - 1; i >= 0; i--) {
|
2163 |
+
const missile = this.firedMissiles[i];
|
2164 |
+
const result = missile.update(deltaTime, this.position);
|
2165 |
+
|
2166 |
+
if (result === 'hit' || result === 'expired') {
|
2167 |
+
this.firedMissiles.splice(i, 1);
|
2168 |
+
}
|
2169 |
+
}
|
2170 |
+
}
|
2171 |
+
|
2172 |
+
updateLockOn(deltaTime) {
|
2173 |
+
if (!this.playerFighter || this.aim9Missiles <= 0) {
|
2174 |
+
this.lockTarget = null;
|
2175 |
+
this.lockProgress = 0;
|
2176 |
+
this.isLocking = false;
|
2177 |
+
return;
|
2178 |
+
}
|
2179 |
+
|
2180 |
+
const now = Date.now();
|
2181 |
+
const distance = this.position.distanceTo(this.playerFighter.position);
|
2182 |
+
|
2183 |
+
// ๋ฝ์จ ๋ฒ์ ๋ด์ ์๊ณ ์ ํฌ ์ค์ผ ๋๋ง
|
2184 |
+
if (distance <= GAME_CONSTANTS.ENEMY_LOCK_RANGE && this.aiState === 'combat') {
|
2185 |
+
// ํ๋ ์ด์ด๊ฐ ์์ผ๊ฐ ๋ด์ ์๋์ง ํ์ธ
|
2186 |
+
const toPlayer = this.playerFighter.position.clone().sub(this.position).normalize();
|
2187 |
+
const forward = new THREE.Vector3(0, 0, 1).applyEuler(this.rotation);
|
2188 |
+
const dotProduct = forward.dot(toPlayer);
|
2189 |
+
const angle = Math.acos(Math.max(-1, Math.min(1, dotProduct)));
|
2190 |
+
|
2191 |
+
if (angle < GAME_CONSTANTS.ENEMY_LOCK_ANGLE) {
|
2192 |
+
// 1์ด๋ง๋ค ๋ฝ์จ ์งํ
|
2193 |
+
if (now - this.lastLockTime >= 1000) {
|
2194 |
+
if (this.lockTarget === this.playerFighter) {
|
2195 |
+
this.lockProgress++;
|
2196 |
+
this.lastLockTime = now;
|
2197 |
+
|
2198 |
+
// ๋ฝ์จ ์์ ์๋ฆผ
|
2199 |
+
if (this.lockProgress === 1 && !this.isLocking) {
|
2200 |
+
this.isLocking = true;
|
2201 |
+
if (window.gameInstance) {
|
2202 |
+
window.gameInstance.onEnemyLockStart(this);
|
2203 |
+
}
|
2204 |
+
}
|
2205 |
+
|
2206 |
+
// ๋ฝ์จ ์๋ฃ ๋ฐ ๋ฐ์ฌ
|
2207 |
+
if (this.lockProgress >= GAME_CONSTANTS.AIM9_LOCK_REQUIRED) {
|
2208 |
+
// ๋ฏธ์ฌ์ผ ์ฟจ๋ค์ด ์ฒดํฌ (3์ด)
|
2209 |
+
if (now - this.lastMissileFireTime >= 3000) {
|
2210 |
+
this.fireAIM9();
|
2211 |
+
this.lastMissileFireTime = now;
|
2212 |
+
}
|
2213 |
+
// ๋ฝ์จ ๋ฆฌ์
|
2214 |
+
this.lockTarget = null;
|
2215 |
+
this.lockProgress = 0;
|
2216 |
+
this.isLocking = false;
|
2217 |
+
}
|
2218 |
+
} else {
|
2219 |
+
// ์๋ก์ด ๋ฝ์จ ์์
|
2220 |
+
this.lockTarget = this.playerFighter;
|
2221 |
+
this.lockProgress = 1;
|
2222 |
+
this.lastLockTime = now;
|
2223 |
+
this.isLocking = true;
|
2224 |
+
if (window.gameInstance) {
|
2225 |
+
window.gameInstance.onEnemyLockStart(this);
|
2226 |
+
}
|
2227 |
+
}
|
2228 |
+
}
|
2229 |
+
} else {
|
2230 |
+
// ์์ผ๊ฐ์ ๋ฒ์ด๋๋ฉด ๋ฝ์จ ํด์
|
2231 |
+
if (this.lockTarget) {
|
2232 |
+
this.lockTarget = null;
|
2233 |
+
this.lockProgress = 0;
|
2234 |
+
if (this.isLocking) {
|
2235 |
+
this.isLocking = false;
|
2236 |
+
if (window.gameInstance) {
|
2237 |
+
window.gameInstance.onEnemyLockLost(this);
|
2238 |
+
}
|
2239 |
+
}
|
2240 |
+
}
|
2241 |
+
}
|
2242 |
+
} else {
|
2243 |
+
// ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ฉด ๋ฝ์จ ํด์
|
2244 |
+
if (this.lockTarget) {
|
2245 |
+
this.lockTarget = null;
|
2246 |
+
this.lockProgress = 0;
|
2247 |
+
if (this.isLocking) {
|
2248 |
+
this.isLocking = false;
|
2249 |
+
if (window.gameInstance) {
|
2250 |
+
window.gameInstance.onEnemyLockLost(this);
|
2251 |
+
}
|
2252 |
+
}
|
2253 |
+
}
|
2254 |
+
}
|
2255 |
+
}
|
2256 |
+
|
2257 |
+
fireAIM9() {
|
2258 |
+
if (this.aim9Missiles <= 0 || !this.lockTarget) return;
|
2259 |
+
|
2260 |
+
this.aim9Missiles--;
|
2261 |
+
|
2262 |
+
// ๋ ๊ฐ ๋ฐ์ฌ ์์น
|
2263 |
+
const isLeftWing = Math.random() < 0.5;
|
2264 |
+
const wingOffset = new THREE.Vector3(isLeftWing ? -6 : 6, -1, 2);
|
2265 |
+
wingOffset.applyEuler(this.rotation);
|
2266 |
+
const missileStartPos = this.position.clone().add(wingOffset);
|
2267 |
+
|
2268 |
+
// ๋ฏธ์ฌ์ผ ์์ฑ
|
2269 |
+
const missile = new EnemyAIM9Missile(this.scene, missileStartPos, this.lockTarget, this.rotation.clone());
|
2270 |
+
this.firedMissiles.push(missile);
|
2271 |
+
|
2272 |
+
// ๋ฐ์ฌ ์๋ฆผ
|
2273 |
+
if (window.gameInstance) {
|
2274 |
+
window.gameInstance.onEnemyMissileLaunch(this, missile);
|
2275 |
+
}
|
2276 |
+
|
2277 |
+
// ๋ฐ์ฌ์ (๊ฑฐ๋ฆฌ์ ๋ฐ๋ผ)
|
2278 |
+
if (this.playerFighter) {
|
2279 |
+
const distanceToPlayer = this.position.distanceTo(this.playerFighter.position);
|
2280 |
+
if (distanceToPlayer < 3000) {
|
2281 |
+
try {
|
2282 |
+
const missileSound = new Audio('sounds/missile.ogg');
|
2283 |
+
const volumeMultiplier = 1 - (distanceToPlayer / 3000);
|
2284 |
+
missileSound.volume = 0.5 * volumeMultiplier;
|
2285 |
+
missileSound.play().catch(e => {});
|
2286 |
+
} catch (e) {}
|
2287 |
+
}
|
2288 |
+
}
|
2289 |
+
}
|
2290 |
+
|
2291 |
calculateAimAccuracy(target) {
|
2292 |
const toTarget = target.clone().sub(this.position).normalize();
|
2293 |
const forward = new THREE.Vector3(0, 0, 1).applyEuler(this.rotation);
|
|
|
2347 |
this.scene.remove(this.mesh);
|
2348 |
this.bullets.forEach(bullet => this.scene.remove(bullet));
|
2349 |
this.bullets = [];
|
2350 |
+
this.firedMissiles.forEach(missile => missile.destroy());
|
2351 |
+
this.firedMissiles = [];
|
2352 |
this.isLoaded = false;
|
2353 |
}
|
2354 |
}
|
|
|
2762 |
}, 1000);
|
2763 |
}
|
2764 |
|
2765 |
+
// ์ ์ด ํ๋ ์ด์ด๋ฅผ ๋ฝ์จ ์์ํ ๋
|
2766 |
+
onEnemyLockStart(enemy) {
|
2767 |
+
console.log('Warning: Enemy locking on!');
|
2768 |
+
|
2769 |
+
// ๋ฝ์จ ์ค์ธ ์ ์ถ๊ฐ
|
2770 |
+
if (!this.fighter.beingLockedBy.includes(enemy)) {
|
2771 |
+
this.fighter.beingLockedBy.push(enemy);
|
2772 |
+
}
|
2773 |
+
|
2774 |
+
// ๊ฒฝ๊ณ ์ ์
๋ฐ์ดํธ
|
2775 |
+
this.fighter.updateWarningAudios();
|
2776 |
+
}
|
2777 |
+
|
2778 |
+
// ์ ์ด ๋ฝ์จ์ ์์์ ๋
|
2779 |
+
onEnemyLockLost(enemy) {
|
2780 |
+
console.log('Enemy lock lost');
|
2781 |
+
|
2782 |
+
// ๋ฝ์จ ๋ชฉ๋ก์์ ์ ๊ฑฐ
|
2783 |
+
const index = this.fighter.beingLockedBy.indexOf(enemy);
|
2784 |
+
if (index !== -1) {
|
2785 |
+
this.fighter.beingLockedBy.splice(index, 1);
|
2786 |
+
}
|
2787 |
+
|
2788 |
+
// ๊ฒฝ๊ณ ์ ์
๋ฐ์ดํธ
|
2789 |
+
this.fighter.updateWarningAudios();
|
2790 |
+
}
|
2791 |
+
|
2792 |
+
// ์ ์ด ๋ฏธ์ฌ์ผ์ ๋ฐ์ฌํ์ ๋
|
2793 |
+
onEnemyMissileLaunch(enemy, missile) {
|
2794 |
+
console.log('Warning: Missile launched!');
|
2795 |
+
|
2796 |
+
// ํ๋ ์ด์ด์ incoming missiles ๋ชฉ๋ก์ ์ถ๊ฐ
|
2797 |
+
this.fighter.incomingMissiles.push(missile);
|
2798 |
+
|
2799 |
+
// ๋ฝ์จ ๋ชฉ๋ก์์ ์ ๊ฑฐ (๋ฏธ์ฌ์ผ ๋ฐ์ฌ ํ ๋ฝ์จ ํด์ )
|
2800 |
+
const index = this.fighter.beingLockedBy.indexOf(enemy);
|
2801 |
+
if (index !== -1) {
|
2802 |
+
this.fighter.beingLockedBy.splice(index, 1);
|
2803 |
+
}
|
2804 |
+
|
2805 |
+
// ๊ฒฝ๊ณ ์ ์
๋ฐ์ดํธ
|
2806 |
+
this.fighter.updateWarningAudios();
|
2807 |
+
}
|
2808 |
+
|
2809 |
updateUI() {
|
2810 |
if (this.fighter.isLoaded) {
|
2811 |
const speedKnots = Math.round(this.fighter.speed * 1.94384);
|
|
|
3022 |
const existingStallWarnings = document.querySelectorAll('.stall-escape-warning');
|
3023 |
existingStallWarnings.forEach(w => w.remove());
|
3024 |
|
3025 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ์ ๊ฑฐ
|
3026 |
+
const existingMissileWarnings = document.querySelectorAll('.missile-warning');
|
3027 |
+
existingMissileWarnings.forEach(w => w.remove());
|
3028 |
+
|
3029 |
// ๊ณ ๋ ๊ฒฝ๊ณ ์ธ๊ณฝ ํจ๊ณผ
|
3030 |
let altitudeEdgeEffect = document.getElementById('altitudeEdgeEffect');
|
3031 |
+
|
3032 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ๊ฐ ์ต์ฐ์
|
3033 |
+
if (this.fighter.incomingMissiles.length > 0) {
|
3034 |
+
if (!altitudeEdgeEffect) {
|
3035 |
+
altitudeEdgeEffect = document.createElement('div');
|
3036 |
+
altitudeEdgeEffect.id = 'altitudeEdgeEffect';
|
3037 |
+
document.body.appendChild(altitudeEdgeEffect);
|
3038 |
+
}
|
3039 |
+
|
3040 |
+
// ๊ฐ๋ ฌํ ๋ถ์์ ํจ๊ณผ
|
3041 |
+
const edgeIntensity = 0.8;
|
3042 |
+
altitudeEdgeEffect.style.cssText = `
|
3043 |
+
position: fixed;
|
3044 |
+
top: 0;
|
3045 |
+
left: 0;
|
3046 |
+
width: 100%;
|
3047 |
+
height: 100%;
|
3048 |
+
pointer-events: none;
|
3049 |
+
z-index: 1300;
|
3050 |
+
background: radial-gradient(ellipse at center,
|
3051 |
+
transparent 30%,
|
3052 |
+
rgba(255, 0, 0, ${edgeIntensity * 0.4}) 50%,
|
3053 |
+
rgba(255, 0, 0, ${edgeIntensity}) 100%);
|
3054 |
+
box-shadow: inset 0 0 200px rgba(255, 0, 0, ${edgeIntensity}),
|
3055 |
+
inset 0 0 150px rgba(255, 0, 0, ${edgeIntensity * 0.8});
|
3056 |
+
animation: missile-pulse 0.3s infinite;
|
3057 |
+
`;
|
3058 |
+
|
3059 |
+
// ๋ฏธ์ฌ์ผ ๊ฒฝ๊ณ ํ
์คํธ
|
3060 |
+
const missileWarning = document.createElement('div');
|
3061 |
+
missileWarning.className = 'missile-warning';
|
3062 |
+
missileWarning.style.cssText = `
|
3063 |
+
position: fixed;
|
3064 |
+
top: 20%;
|
3065 |
+
left: 50%;
|
3066 |
+
transform: translateX(-50%);
|
3067 |
+
color: #ff0000;
|
3068 |
+
font-size: 36px;
|
3069 |
+
font-weight: bold;
|
3070 |
+
text-shadow: 0 0 20px rgba(255,0,0,1), 0 0 40px rgba(255,0,0,0.8);
|
3071 |
+
z-index: 1600;
|
3072 |
+
text-align: center;
|
3073 |
+
animation: missile-blink 0.2s infinite;
|
3074 |
+
`;
|
3075 |
+
missileWarning.innerHTML = 'MISSILE INCOMING!<br>EVADE! EVADE!';
|
3076 |
+
document.body.appendChild(missileWarning);
|
3077 |
+
|
3078 |
+
} else if (this.fighter.altitude < 500) {
|
3079 |
if (!altitudeEdgeEffect) {
|
3080 |
altitudeEdgeEffect = document.createElement('div');
|
3081 |
altitudeEdgeEffect.id = 'altitudeEdgeEffect';
|
|
|
3232 |
opacity: 0.7;
|
3233 |
}
|
3234 |
}
|
3235 |
+
@keyframes missile-pulse {
|
3236 |
+
0%, 100% {
|
3237 |
+
opacity: 1;
|
3238 |
+
}
|
3239 |
+
50% {
|
3240 |
+
opacity: 0.5;
|
3241 |
+
}
|
3242 |
+
}
|
3243 |
+
@keyframes missile-blink {
|
3244 |
+
0%, 50% { opacity: 1; }
|
3245 |
+
51%, 100% { opacity: 0.2; }
|
3246 |
+
}
|
3247 |
`;
|
3248 |
document.head.appendChild(style);
|
3249 |
}
|
|
|
3520 |
}
|
3521 |
}
|
3522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3523 |
checkCollisions() {
|
3524 |
// ํ๋ ์ด์ด์ ์ ๊ธฐ์ ์ง์ ์ถฉ๋ ์ฒดํฌ (์ต์ฐ์ )
|
3525 |
for (let i = this.enemies.length - 1; i >= 0; i--) {
|
|
|
3647 |
}
|
3648 |
}
|
3649 |
});
|
3650 |
+
|
3651 |
+
// incoming missiles ์
๋ฐ์ดํธ (ํ๊ดด๋ ๋ฏธ์ฌ์ผ ์ ๊ฑฐ)
|
3652 |
+
this.fighter.incomingMissiles = this.fighter.incomingMissiles.filter(missile => {
|
3653 |
+
return missile && missile.mesh && missile.mesh.parent;
|
3654 |
+
});
|
3655 |
}
|
3656 |
|
3657 |
createHitEffect(position) {
|
|
|
4094 |
document.exitPointerLock();
|
4095 |
|
4096 |
// ๋ชจ๋ ๊ฒฝ๊ณ ๋ฐ ํจ๊ณผ ์ ๊ฑฐ
|
4097 |
+
const existingWarnings = document.querySelectorAll('.warning-message, .stall-escape-warning, .missile-warning');
|
4098 |
existingWarnings.forEach(w => w.remove());
|
4099 |
|
4100 |
const blurEffect = document.getElementById('overGBlurEffect');
|