Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -542,6 +542,12 @@ class Fighter {
|
|
| 542 |
if (this.position.y <= GAME_CONSTANTS.MIN_ALTITUDE) {
|
| 543 |
this.position.y = GAME_CONSTANTS.MIN_ALTITUDE;
|
| 544 |
this.health = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 545 |
return;
|
| 546 |
}
|
| 547 |
|
|
@@ -2208,6 +2214,166 @@ class Game {
|
|
| 2208 |
} catch (e) {}
|
| 2209 |
}
|
| 2210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2211 |
showHitMarker(position) {
|
| 2212 |
// 히트 마커 div 생성
|
| 2213 |
const hitMarker = document.createElement('div');
|
|
|
|
| 542 |
if (this.position.y <= GAME_CONSTANTS.MIN_ALTITUDE) {
|
| 543 |
this.position.y = GAME_CONSTANTS.MIN_ALTITUDE;
|
| 544 |
this.health = 0;
|
| 545 |
+
|
| 546 |
+
// 지면 충돌 시 폭발 효과 추가
|
| 547 |
+
if (window.gameInstance) {
|
| 548 |
+
window.gameInstance.createExplosionEffect(this.position);
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
return;
|
| 552 |
}
|
| 553 |
|
|
|
|
| 2214 |
} catch (e) {}
|
| 2215 |
}
|
| 2216 |
|
| 2217 |
+
createExplosionEffect(position) {
|
| 2218 |
+
// 메인 폭발 플래시
|
| 2219 |
+
const explosionGeometry = new THREE.SphereGeometry(50, 16, 16);
|
| 2220 |
+
const explosionMaterial = new THREE.MeshBasicMaterial({
|
| 2221 |
+
color: 0xffaa00,
|
| 2222 |
+
emissive: 0xffaa00,
|
| 2223 |
+
emissiveIntensity: 3.0,
|
| 2224 |
+
transparent: true,
|
| 2225 |
+
opacity: 1.0
|
| 2226 |
+
});
|
| 2227 |
+
|
| 2228 |
+
const explosion = new THREE.Mesh(explosionGeometry, explosionMaterial);
|
| 2229 |
+
explosion.position.copy(position);
|
| 2230 |
+
this.scene.add(explosion);
|
| 2231 |
+
|
| 2232 |
+
// 폭발 파편들
|
| 2233 |
+
const debrisCount = 30;
|
| 2234 |
+
const debris = [];
|
| 2235 |
+
|
| 2236 |
+
for (let i = 0; i < debrisCount; i++) {
|
| 2237 |
+
const debrisGeometry = new THREE.BoxGeometry(
|
| 2238 |
+
2 + Math.random() * 4,
|
| 2239 |
+
2 + Math.random() * 4,
|
| 2240 |
+
2 + Math.random() * 4
|
| 2241 |
+
);
|
| 2242 |
+
const debrisMaterial = new THREE.MeshBasicMaterial({
|
| 2243 |
+
color: Math.random() > 0.5 ? 0xff6600 : 0x333333,
|
| 2244 |
+
transparent: true,
|
| 2245 |
+
opacity: 1.0
|
| 2246 |
+
});
|
| 2247 |
+
|
| 2248 |
+
const debrisPiece = new THREE.Mesh(debrisGeometry, debrisMaterial);
|
| 2249 |
+
debrisPiece.position.copy(position);
|
| 2250 |
+
|
| 2251 |
+
// 랜덤 속도와 회전
|
| 2252 |
+
debrisPiece.velocity = new THREE.Vector3(
|
| 2253 |
+
(Math.random() - 0.5) * 200,
|
| 2254 |
+
(Math.random() - 0.5) * 200,
|
| 2255 |
+
(Math.random() - 0.5) * 200
|
| 2256 |
+
);
|
| 2257 |
+
debrisPiece.rotationSpeed = new THREE.Vector3(
|
| 2258 |
+
Math.random() * 10,
|
| 2259 |
+
Math.random() * 10,
|
| 2260 |
+
Math.random() * 10
|
| 2261 |
+
);
|
| 2262 |
+
debrisPiece.life = 2.0;
|
| 2263 |
+
|
| 2264 |
+
this.scene.add(debrisPiece);
|
| 2265 |
+
debris.push(debrisPiece);
|
| 2266 |
+
}
|
| 2267 |
+
|
| 2268 |
+
// 연기 효과
|
| 2269 |
+
const smokeCount = 10;
|
| 2270 |
+
const smoke = [];
|
| 2271 |
+
|
| 2272 |
+
for (let i = 0; i < smokeCount; i++) {
|
| 2273 |
+
const smokeGeometry = new THREE.SphereGeometry(10 + Math.random() * 20, 8, 8);
|
| 2274 |
+
const smokeMaterial = new THREE.MeshBasicMaterial({
|
| 2275 |
+
color: 0x222222,
|
| 2276 |
+
transparent: true,
|
| 2277 |
+
opacity: 0.8
|
| 2278 |
+
});
|
| 2279 |
+
|
| 2280 |
+
const smokePuff = new THREE.Mesh(smokeGeometry, smokeMaterial);
|
| 2281 |
+
smokePuff.position.copy(position);
|
| 2282 |
+
smokePuff.position.add(new THREE.Vector3(
|
| 2283 |
+
(Math.random() - 0.5) * 20,
|
| 2284 |
+
(Math.random() - 0.5) * 20,
|
| 2285 |
+
(Math.random() - 0.5) * 20
|
| 2286 |
+
));
|
| 2287 |
+
|
| 2288 |
+
smokePuff.velocity = new THREE.Vector3(
|
| 2289 |
+
(Math.random() - 0.5) * 50,
|
| 2290 |
+
Math.random() * 50 + 20,
|
| 2291 |
+
(Math.random() - 0.5) * 50
|
| 2292 |
+
);
|
| 2293 |
+
smokePuff.life = 3.0;
|
| 2294 |
+
|
| 2295 |
+
this.scene.add(smokePuff);
|
| 2296 |
+
smoke.push(smokePuff);
|
| 2297 |
+
}
|
| 2298 |
+
|
| 2299 |
+
// 폭발음 재생 - 150% 음량
|
| 2300 |
+
try {
|
| 2301 |
+
const explosionSound = new Audio('sounds/bang.ogg');
|
| 2302 |
+
explosionSound.volume = 1.0;
|
| 2303 |
+
explosionSound.play().catch(e => console.log('Explosion sound failed:', e));
|
| 2304 |
+
} catch (e) {
|
| 2305 |
+
console.log('Explosion sound error:', e);
|
| 2306 |
+
}
|
| 2307 |
+
|
| 2308 |
+
// 애니메이션
|
| 2309 |
+
const animateExplosion = () => {
|
| 2310 |
+
let allDead = true;
|
| 2311 |
+
|
| 2312 |
+
// 메인 폭발 애니메이션
|
| 2313 |
+
if (explosion.material.opacity > 0) {
|
| 2314 |
+
explosion.material.opacity -= 0.02;
|
| 2315 |
+
explosion.scale.multiplyScalar(1.08);
|
| 2316 |
+
allDead = false;
|
| 2317 |
+
} else if (explosion.parent) {
|
| 2318 |
+
this.scene.remove(explosion);
|
| 2319 |
+
}
|
| 2320 |
+
|
| 2321 |
+
// 파편 애니메이션
|
| 2322 |
+
debris.forEach(piece => {
|
| 2323 |
+
if (piece.life > 0) {
|
| 2324 |
+
allDead = false;
|
| 2325 |
+
piece.life -= 0.02;
|
| 2326 |
+
|
| 2327 |
+
// 위치 업데이트
|
| 2328 |
+
piece.position.add(piece.velocity.clone().multiplyScalar(0.02));
|
| 2329 |
+
|
| 2330 |
+
// 중력
|
| 2331 |
+
piece.velocity.y -= 3;
|
| 2332 |
+
|
| 2333 |
+
// 회전
|
| 2334 |
+
piece.rotation.x += piece.rotationSpeed.x * 0.02;
|
| 2335 |
+
piece.rotation.y += piece.rotationSpeed.y * 0.02;
|
| 2336 |
+
piece.rotation.z += piece.rotationSpeed.z * 0.02;
|
| 2337 |
+
|
| 2338 |
+
// 페이드 아웃
|
| 2339 |
+
piece.material.opacity = piece.life / 2;
|
| 2340 |
+
} else if (piece.parent) {
|
| 2341 |
+
this.scene.remove(piece);
|
| 2342 |
+
}
|
| 2343 |
+
});
|
| 2344 |
+
|
| 2345 |
+
// 연기 애니메이션
|
| 2346 |
+
smoke.forEach(puff => {
|
| 2347 |
+
if (puff.life > 0) {
|
| 2348 |
+
allDead = false;
|
| 2349 |
+
puff.life -= 0.02;
|
| 2350 |
+
|
| 2351 |
+
// 위치 업데이트
|
| 2352 |
+
puff.position.add(puff.velocity.clone().multiplyScalar(0.02));
|
| 2353 |
+
|
| 2354 |
+
// 상승 감속
|
| 2355 |
+
puff.velocity.y *= 0.98;
|
| 2356 |
+
puff.velocity.x *= 0.98;
|
| 2357 |
+
puff.velocity.z *= 0.98;
|
| 2358 |
+
|
| 2359 |
+
// 확산
|
| 2360 |
+
puff.scale.multiplyScalar(1.02);
|
| 2361 |
+
|
| 2362 |
+
// 페이드 아웃
|
| 2363 |
+
puff.material.opacity = (puff.life / 3) * 0.8;
|
| 2364 |
+
} else if (puff.parent) {
|
| 2365 |
+
this.scene.remove(puff);
|
| 2366 |
+
}
|
| 2367 |
+
});
|
| 2368 |
+
|
| 2369 |
+
if (!allDead) {
|
| 2370 |
+
requestAnimationFrame(animateExplosion);
|
| 2371 |
+
}
|
| 2372 |
+
};
|
| 2373 |
+
|
| 2374 |
+
animateExplosion();
|
| 2375 |
+
}
|
| 2376 |
+
|
| 2377 |
showHitMarker(position) {
|
| 2378 |
// 히트 마커 div 생성
|
| 2379 |
const hitMarker = document.createElement('div');
|