cutechicken commited on
Commit
c7c19ae
Β·
verified Β·
1 Parent(s): 6fdf7cb

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +142 -27
game.js CHANGED
@@ -74,6 +74,7 @@ class Fighter {
74
  // Over-G μ‹œμŠ€ν…œ
75
  this.overG = false;
76
  this.maxGForce = 9.0;
 
77
 
78
  // 경고음 μ‹œμŠ€ν…œ
79
  this.warningAudios = {
@@ -285,22 +286,56 @@ class Fighter {
285
  this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetYaw, rotationSpeed);
286
 
287
  // ν˜„μ‹€μ μΈ 속도 계산
288
- const minSpeed = 150; // μ΅œμ†Œ 속도 150kt
289
  const maxSpeed = 600; // μ΅œλŒ€ 속도 600kt
290
  let targetSpeed = minSpeed + (maxSpeed - minSpeed) * this.throttle;
291
 
292
- // ν”ΌμΉ˜ 각도에 λ”°λ₯Έ 속도 λ³€ν™” (μƒμŠΉμ‹œ 감속, ν•˜κ°•μ‹œ 가속)
293
  const pitchAngle = this.rotation.x;
 
 
 
294
  if (pitchAngle < -0.1) { // κΈ°μˆ˜κ°€ μœ„λ‘œ (μƒμŠΉ)
295
- const climbFactor = Math.abs(pitchAngle) / (Math.PI / 3);
296
- targetSpeed *= (1 - climbFactor * 0.3); // μ΅œλŒ€ 30% 감속
 
 
 
 
297
  } else if (pitchAngle > 0.1) { // κΈ°μˆ˜κ°€ μ•„λž˜λ‘œ (ν•˜κ°•)
298
  const diveFactor = pitchAngle / (Math.PI / 3);
299
  targetSpeed *= (1 + diveFactor * 0.2); // μ΅œλŒ€ 20% 가속
300
  }
301
 
302
- // 속도 λ³€ν™”λ₯Ό 천천히 적용
303
- this.speed = THREE.MathUtils.lerp(this.speed, targetSpeed, deltaTime * 0.5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
 
305
  // μŠ€ν†¨ κ²½κ³ : 300kt μ΄ν•˜μ—μ„œ μŠ€ν†¨ μœ„ν—˜
306
  const speedKnots = this.speed * 1.94384; // m/s to knots
@@ -308,24 +343,38 @@ class Fighter {
308
 
309
  // μŠ€ν†¨ μƒνƒœμ—μ„œμ˜ 물리 효과
310
  if (this.stallWarning) {
311
- // κΈ°μˆ˜κ°€ μ•„λž˜λ‘œ 떨어짐
312
- this.targetPitch += deltaTime * 0.5;
313
- // μ‘°μ’…μ„± κ°μ†Œ
314
- this.rotation.x += (Math.random() - 0.5) * deltaTime * 0.2;
315
- this.rotation.z += (Math.random() - 0.5) * deltaTime * 0.2;
 
 
 
 
 
316
  }
317
 
318
  // 속도 벑터 계산
319
  const noseDirection = new THREE.Vector3(0, 0, 1);
320
  noseDirection.applyEuler(this.rotation);
321
- this.velocity = noseDirection.multiplyScalar(this.speed);
322
 
323
- // ν˜„μ‹€μ μΈ 쀑λ ₯ 효과
324
- const gravityEffect = GAME_CONSTANTS.GRAVITY * deltaTime * 0.15;
325
- this.velocity.y -= gravityEffect;
 
 
 
 
 
 
326
 
327
- // μ–‘λ ₯ 효과 (속도에 λΉ„λ‘€)
328
  if (!this.stallWarning) {
 
 
 
 
329
  const liftFactor = (this.speed / maxSpeed) * 0.8;
330
  const lift = gravityEffect * liftFactor;
331
  this.velocity.y += lift;
@@ -370,17 +419,9 @@ class Fighter {
370
  this.warningBlinkState = !this.warningBlinkState;
371
  }
372
 
373
- // 고도 및 G-Force 계산
374
  this.altitude = this.position.y;
375
 
376
- // G-Force 계산
377
- const turnRate = Math.abs(bankTurnRate) * 100;
378
- const pitchRate = Math.abs(this.rotation.x - this.targetPitch) * 10;
379
- this.gForce = 1.0 + turnRate + pitchRate + (Math.abs(this.rotation.z) * 3);
380
-
381
- // Over-G 체크
382
- this.overG = this.gForce > this.maxGForce;
383
-
384
  // 경고음 μ—…λ°μ΄νŠΈ (μ—”μ§„ μ†Œλ¦¬λŠ” 계속 μœ μ§€)
385
  this.updateWarningAudios();
386
 
@@ -1007,7 +1048,6 @@ class Game {
1007
 
1008
  if (this.fighter.stallWarning) {
1009
  warningText += 'STALL WARNING\n';
1010
- warningText += '<span style="font-size: 16px;">INCREASE THROTTLE</span>\n';
1011
  }
1012
 
1013
  if (this.fighter.overG) {
@@ -1019,6 +1059,75 @@ class Game {
1019
  document.body.appendChild(warningContainer);
1020
  }
1021
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1022
  }
1023
 
1024
  updateRadar() {
@@ -1163,9 +1272,15 @@ class Game {
1163
 
1164
  document.exitPointerLock();
1165
 
1166
- const existingWarnings = document.querySelectorAll('.warning-message');
 
1167
  existingWarnings.forEach(w => w.remove());
1168
 
 
 
 
 
 
1169
  const gameOverDiv = document.createElement('div');
1170
  gameOverDiv.className = 'start-screen';
1171
  gameOverDiv.style.display = 'flex';
 
74
  // Over-G μ‹œμŠ€ν…œ
75
  this.overG = false;
76
  this.maxGForce = 9.0;
77
+ this.overGTimer = 0; // Over-G 지속 μ‹œκ°„
78
 
79
  // 경고음 μ‹œμŠ€ν…œ
80
  this.warningAudios = {
 
286
  this.rotation.y = THREE.MathUtils.lerp(this.rotation.y, this.targetYaw, rotationSpeed);
287
 
288
  // ν˜„μ‹€μ μΈ 속도 계산
289
+ const minSpeed = 0; // μ΅œμ†Œ 속도 0kt
290
  const maxSpeed = 600; // μ΅œλŒ€ 속도 600kt
291
  let targetSpeed = minSpeed + (maxSpeed - minSpeed) * this.throttle;
292
 
293
+ // ν”ΌμΉ˜ 각도에 λ”°λ₯Έ 속도 λ³€ν™”
294
  const pitchAngle = this.rotation.x;
295
+ const pitchDegrees = Math.abs(pitchAngle) * (180 / Math.PI);
296
+
297
+ // κΈ°μˆ˜κ°€ μœ„λ₯Ό ν–₯ν•˜κ³  μžˆμ„ 경우 λΉ λ₯Έ 속도 κ°μ†Œ
298
  if (pitchAngle < -0.1) { // κΈ°μˆ˜κ°€ μœ„λ‘œ (μƒμŠΉ)
299
+ const climbFactor = Math.abs(pitchAngle) / (Math.PI / 2); // 90도 κΈ°μ€€
300
+ if (pitchDegrees > 30) { // 30도 이상일 λ•Œ κΈ‰κ²©ν•œ 감속
301
+ targetSpeed *= Math.max(0, 1 - climbFactor * 1.5); // μ΅œλŒ€ 150% 감속 (0ktκΉŒμ§€)
302
+ } else {
303
+ targetSpeed *= (1 - climbFactor * 0.3); // 정상적인 감속
304
+ }
305
  } else if (pitchAngle > 0.1) { // κΈ°μˆ˜κ°€ μ•„λž˜λ‘œ (ν•˜κ°•)
306
  const diveFactor = pitchAngle / (Math.PI / 3);
307
  targetSpeed *= (1 + diveFactor * 0.2); // μ΅œλŒ€ 20% 가속
308
  }
309
 
310
+ // Over-G μƒνƒœ 처리
311
+ const turnRate = Math.abs(bankTurnRate) * 100;
312
+ const pitchRate = Math.abs(this.rotation.x - this.targetPitch) * 10;
313
+ this.gForce = 1.0 + turnRate + pitchRate + (Math.abs(this.rotation.z) * 3);
314
+
315
+ this.overG = this.gForce > this.maxGForce;
316
+
317
+ // Over-G 타이머 μ—…λ°μ΄νŠΈ
318
+ if (this.overG) {
319
+ this.overGTimer += deltaTime;
320
+
321
+ // 3초 이상 Over-G μƒνƒœμΌ 경우
322
+ if (this.overGTimer > 3.0) {
323
+ // 속도 κΈ‰κ²©νžˆ κ°μ†Œ (0ktκΉŒμ§€)
324
+ targetSpeed *= Math.max(0, 1 - (this.overGTimer - 3.0) * 0.5);
325
+
326
+ // μ‹œμ•Ό 흐림 νš¨κ³ΌλŠ” UIμ—μ„œ 처리
327
+ }
328
+ } else {
329
+ this.overGTimer = 0; // Over-G μƒνƒœκ°€ μ•„λ‹ˆλ©΄ 타이머 리셋
330
+ }
331
+
332
+ // 속도 λ³€ν™”λ₯Ό 천천히 적용 (μŠ€ν†¨ μƒνƒœμΌ λ•ŒλŠ” μ œμ™Έ)
333
+ if (this.stallWarning) {
334
+ // μŠ€ν†¨ μƒνƒœμ—μ„œλŠ” 속도가 λΉ λ₯΄κ²Œ κ°μ†Œ
335
+ this.speed = Math.max(0, this.speed - deltaTime * 200);
336
+ } else {
337
+ this.speed = THREE.MathUtils.lerp(this.speed, targetSpeed, deltaTime * 0.5);
338
+ }
339
 
340
  // μŠ€ν†¨ κ²½κ³ : 300kt μ΄ν•˜μ—μ„œ μŠ€ν†¨ μœ„ν—˜
341
  const speedKnots = this.speed * 1.94384; // m/s to knots
 
343
 
344
  // μŠ€ν†¨ μƒνƒœμ—μ„œμ˜ 물리 효과
345
  if (this.stallWarning) {
346
+ // λ°”λ‹₯으둜 μΆ”λ½ν•˜λ©° 가속도가 λΉ λ₯΄κ²Œ λΆ™μŒ
347
+ this.targetPitch = Math.min(Math.PI / 3, this.targetPitch + deltaTime * 2.0); // κΈ°μˆ˜κ°€ λΉ λ₯΄κ²Œ μ•„λž˜λ‘œ
348
+
349
+ // μ‘°μ’… 뢈λŠ₯ μƒνƒœ
350
+ this.rotation.x += (Math.random() - 0.5) * deltaTime * 0.5;
351
+ this.rotation.z += (Math.random() - 0.5) * deltaTime * 0.5;
352
+
353
+ // 쀑λ ₯에 μ˜ν•œ 가속
354
+ const gravityAcceleration = GAME_CONSTANTS.GRAVITY * deltaTime * 3.0; // 3λ°° 쀑λ ₯
355
+ this.velocity.y -= gravityAcceleration;
356
  }
357
 
358
  // 속도 벑터 계산
359
  const noseDirection = new THREE.Vector3(0, 0, 1);
360
  noseDirection.applyEuler(this.rotation);
 
361
 
362
+ if (!this.stallWarning) {
363
+ // 정상 λΉ„ν–‰ μ‹œ
364
+ this.velocity = noseDirection.multiplyScalar(this.speed);
365
+ } else {
366
+ // μŠ€ν†¨ μ‹œμ—λŠ” 쀑λ ₯이 주도적
367
+ this.velocity.x = noseDirection.x * this.speed * 0.3; // μ „λ°© 속도 κ°μ†Œ
368
+ this.velocity.z = noseDirection.z * this.speed * 0.3;
369
+ // y μ†λ„λŠ” μœ„μ—μ„œ 쀑λ ₯으둜 처리됨
370
+ }
371
 
372
+ // 정상 λΉ„ν–‰ μ‹œ 쀑λ ₯ 효과
373
  if (!this.stallWarning) {
374
+ const gravityEffect = GAME_CONSTANTS.GRAVITY * deltaTime * 0.15;
375
+ this.velocity.y -= gravityEffect;
376
+
377
+ // μ–‘λ ₯ 효과 (속도에 λΉ„λ‘€)
378
  const liftFactor = (this.speed / maxSpeed) * 0.8;
379
  const lift = gravityEffect * liftFactor;
380
  this.velocity.y += lift;
 
419
  this.warningBlinkState = !this.warningBlinkState;
420
  }
421
 
422
+ // 고도 계산
423
  this.altitude = this.position.y;
424
 
 
 
 
 
 
 
 
 
425
  // 경고음 μ—…λ°μ΄νŠΈ (μ—”μ§„ μ†Œλ¦¬λŠ” 계속 μœ μ§€)
426
  this.updateWarningAudios();
427
 
 
1048
 
1049
  if (this.fighter.stallWarning) {
1050
  warningText += 'STALL WARNING\n';
 
1051
  }
1052
 
1053
  if (this.fighter.overG) {
 
1059
  document.body.appendChild(warningContainer);
1060
  }
1061
  }
1062
+
1063
+ // μŠ€ν†¨ μƒνƒœμΌ λ•Œ ν•˜λ‹¨μ— "Press W to Escape" κ²½κ³  ν‘œμ‹œ
1064
+ if (this.fighter.stallWarning) {
1065
+ const stallEscapeWarning = document.createElement('div');
1066
+ stallEscapeWarning.className = 'stall-escape-warning';
1067
+ stallEscapeWarning.style.cssText = `
1068
+ position: fixed;
1069
+ bottom: 100px;
1070
+ left: 50%;
1071
+ transform: translateX(-50%);
1072
+ background: rgba(255, 0, 0, 0.8);
1073
+ color: #ffffff;
1074
+ font-size: 28px;
1075
+ font-weight: bold;
1076
+ padding: 15px 30px;
1077
+ border: 3px solid #ff0000;
1078
+ border-radius: 10px;
1079
+ z-index: 1600;
1080
+ text-align: center;
1081
+ animation: blink 0.5s infinite;
1082
+ `;
1083
+ stallEscapeWarning.innerHTML = 'PRESS W TO ESCAPE';
1084
+ document.body.appendChild(stallEscapeWarning);
1085
+
1086
+ // μ• λ‹ˆλ©”μ΄μ…˜ μŠ€νƒ€μΌ μΆ”κ°€
1087
+ if (!document.getElementById('blinkAnimation')) {
1088
+ const style = document.createElement('style');
1089
+ style.id = 'blinkAnimation';
1090
+ style.innerHTML = `
1091
+ @keyframes blink {
1092
+ 0%, 50% { opacity: 1; }
1093
+ 51%, 100% { opacity: 0.3; }
1094
+ }
1095
+ `;
1096
+ document.head.appendChild(style);
1097
+ }
1098
+ }
1099
+
1100
+ // Over-G 3초 이상일 λ•Œ μ‹œμ•Ό 흐림 효과
1101
+ if (this.fighter.overG && this.fighter.overGTimer > 3.0) {
1102
+ let blurEffect = document.getElementById('overGBlurEffect');
1103
+ if (!blurEffect) {
1104
+ blurEffect = document.createElement('div');
1105
+ blurEffect.id = 'overGBlurEffect';
1106
+ document.body.appendChild(blurEffect);
1107
+ }
1108
+
1109
+ // Over-G 지속 μ‹œκ°„μ— 따라 흐림 정도 증가
1110
+ const blurIntensity = Math.min((this.fighter.overGTimer - 3.0) * 0.3, 0.8);
1111
+ blurEffect.style.cssText = `
1112
+ position: fixed;
1113
+ top: 0;
1114
+ left: 0;
1115
+ width: 100%;
1116
+ height: 100%;
1117
+ background: radial-gradient(ellipse at center,
1118
+ transparent 20%,
1119
+ rgba(0, 0, 0, ${blurIntensity}) 50%,
1120
+ rgba(0, 0, 0, ${blurIntensity + 0.2}) 100%);
1121
+ pointer-events: none;
1122
+ z-index: 1400;
1123
+ `;
1124
+ } else {
1125
+ // Over-G μƒνƒœκ°€ μ•„λ‹ˆλ©΄ 효과 제거
1126
+ const blurEffect = document.getElementById('overGBlurEffect');
1127
+ if (blurEffect) {
1128
+ blurEffect.remove();
1129
+ }
1130
+ }
1131
  }
1132
 
1133
  updateRadar() {
 
1272
 
1273
  document.exitPointerLock();
1274
 
1275
+ // λͺ¨λ“  κ²½κ³  및 효과 제거
1276
+ const existingWarnings = document.querySelectorAll('.warning-message, .stall-escape-warning');
1277
  existingWarnings.forEach(w => w.remove());
1278
 
1279
+ const blurEffect = document.getElementById('overGBlurEffect');
1280
+ if (blurEffect) {
1281
+ blurEffect.remove();
1282
+ }
1283
+
1284
  const gameOverDiv = document.createElement('div');
1285
  gameOverDiv.className = 'start-screen';
1286
  gameOverDiv.style.display = 'flex';