cutechicken commited on
Commit
6628cc6
ยท
verified ยท
1 Parent(s): 8688635

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +150 -165
game.js CHANGED
@@ -1134,128 +1134,112 @@ class AIM9Missile {
1134
  this.isLoaded = true;
1135
  }
1136
 
1137
- update(deltaTime, playerPosition) {
1138
- if (!this.mesh || !this.target || !this.target.position) {
1139
- this.destroy();
1140
- return 'expired';
1141
- }
1142
-
1143
- this.lifeTime -= deltaTime;
1144
- if (this.lifeTime <= 0) {
1145
- this.destroy();
1146
- return 'expired';
1147
- }
1148
-
1149
- // missileswing.ogg๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์žฌ์ƒ
1150
- if (!this.swingAudioPlayed && this.lifeTime < 29.5) { // ๋ฐœ์‚ฌ 0.5์ดˆ ํ›„ ์žฌ์ƒ
1151
- try {
1152
- this.swingAudio = new Audio('sounds/missileswing.ogg');
1153
- this.swingAudio.volume = 0.5;
1154
- this.swingAudio.play().catch(e => {});
1155
- this.swingAudioPlayed = true;
1156
- } catch (e) {
1157
- console.log('Missile swing audio failed:', e);
1158
- }
1159
- }
1160
-
1161
- // ํƒ€๊ฒŸ ์ถ”์  - ํ–ฅ์ƒ๋œ ํ˜ธ๋ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜
1162
- const toTarget = this.target.position.clone().sub(this.position);
1163
- const distance = toTarget.length();
1164
-
1165
- // ๋ช…์ค‘ ์ฒดํฌ - ๋ฒ”์œ„ ์ฆ๊ฐ€
1166
- if (distance < 50) { // 30์—์„œ 50์œผ๋กœ ์ฆ๊ฐ€
1167
- // ๋ช…์ค‘!
1168
- this.onHit();
1169
- return 'hit';
1170
- }
1171
-
1172
- // ์˜ˆ์ธก ์‚ฌ๊ฒฉ: ํƒ€๊ฒŸ์˜ ๋ฏธ๋ž˜ ์œ„์น˜ ์˜ˆ์ธก
1173
- if (this.target.velocity) {
1174
- const timeToImpact = distance / this.speed;
1175
- const predictedPosition = this.target.position.clone().add(
1176
- this.target.velocity.clone().multiplyScalar(timeToImpact * 0.5)
1177
- );
1178
- toTarget.copy(predictedPosition.sub(this.position));
1179
- }
1180
-
1181
- toTarget.normalize();
1182
- const currentDirection = this.velocity.clone().normalize();
1183
-
1184
- // ๋น„๋ก€ ํ•ญ๋ฒ• ์œ ๋„ (Proportional Navigation)
1185
- const closing_velocity = this.velocity.length();
1186
- const line_of_sight_rate = currentDirection.clone().cross(toTarget);
1187
- const navigation_constant = 4.0; // N = 4 (์ผ๋ฐ˜์ ์ธ ๋ฏธ์‚ฌ์ผ ์ƒ์ˆ˜)
1188
-
1189
- // ๊ฐ€์†๋„ ๋ช…๋ น ๊ณ„์‚ฐ
1190
- const commanded_acceleration = line_of_sight_rate.multiplyScalar(
1191
- navigation_constant * closing_velocity
1192
- );
1193
-
1194
- // ๋ถ€๋“œ๋Ÿฌ์šด ๋ฐฉํ–ฅ ์ „ํ™˜ with ๋น„๋ก€ ํ•ญ๋ฒ•
1195
- const newDirection = currentDirection.clone();
1196
- const maxTurnRate = this.turnRate * deltaTime;
1197
-
1198
- // ๊ฐ€์†๋„๋ฅผ ๋ฐฉํ–ฅ ๋ณ€ํ™”๋กœ ๋ณ€ํ™˜
1199
- const deltaDirection = commanded_acceleration.multiplyScalar(deltaTime / this.speed);
1200
- newDirection.add(deltaDirection);
1201
-
1202
- // ์ง์ ‘ ์ถ”์ ๋„ ํ˜ผํ•ฉ (๊ทผ๊ฑฐ๋ฆฌ์—์„œ ๋” ์ •ํ™•ํ•œ ์ถ”์ )
1203
- if (distance < 500) {
1204
- const directWeight = 1.0 - (distance / 500);
1205
- newDirection.lerp(toTarget, directWeight * maxTurnRate);
1206
- }
1207
-
1208
- newDirection.normalize();
1209
-
1210
- // ์†๋„ ์—…๋ฐ์ดํŠธ - ๊ฐ€์† ์ถ”๊ฐ€
1211
- if (this.lifeTime > 25) {
1212
- // ์ดˆ๊ธฐ 5์ดˆ๊ฐ„ ๊ฐ€์†
1213
- this.speed = Math.min(this.speed + deltaTime * 200, 1543.2); // ์ตœ๋Œ€ 3000kt
1214
- }
1215
-
1216
- this.velocity = newDirection.multiplyScalar(this.speed);
1217
-
1218
- // ์œ„์น˜ ์—…๋ฐ์ดํŠธ
1219
- this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
1220
- this.mesh.position.copy(this.position);
1221
-
1222
- // ๋ฏธ์‚ฌ์ผ ํšŒ์ „
1223
- const lookAtTarget = this.position.clone().add(this.velocity);
1224
- this.mesh.lookAt(lookAtTarget);
1225
-
1226
- // ์ถ”๋ ฅ ์—ฐ๊ธฐ ์ƒ์„ฑ
1227
- this.smokeEmitTime += deltaTime;
1228
- if (this.smokeEmitTime >= 0.02) { // 0.02์ดˆ๋งˆ๋‹ค ์—ฐ๊ธฐ ์ƒ์„ฑ
1229
- this.smokeEmitTime = 0;
1230
- this.createSmokeParticle();
1231
- }
1232
-
1233
- // ์—ฐ๊ธฐ ํŒŒํ‹ฐํด ์—…๋ฐ์ดํŠธ
1234
- for (let i = this.smokeTrail.length - 1; i >= 0; i--) {
1235
- const smoke = this.smokeTrail[i];
1236
- smoke.life -= deltaTime;
1237
-
1238
- if (smoke.life <= 0) {
1239
- this.scene.remove(smoke.mesh);
1240
- this.smokeTrail.splice(i, 1);
1241
- } else {
1242
- // ์—ฐ๊ธฐ ํ™•์‚ฐ ๋ฐ ํŽ˜์ด๋“œ
1243
- smoke.mesh.scale.multiplyScalar(1.02);
1244
- smoke.mesh.material.opacity = smoke.life / 3.0;
1245
-
1246
- // ์•ฝ๊ฐ„์˜ ์ƒ์Šน ํšจ๊ณผ
1247
- smoke.mesh.position.y += deltaTime * 2;
1248
- }
1249
- }
1250
-
1251
- // ์ง€๋ฉด ์ถฉ๋Œ
1252
- if (this.position.y <= 0) {
1253
- this.destroy();
1254
- return 'expired';
1255
- }
1256
-
1257
- return 'flying';
1258
- }
1259
 
1260
  createSmokeParticle() {
1261
  // ๋ฏธ์‚ฌ์ผ ๋’ค์ชฝ ์œ„์น˜ ๊ณ„์‚ฐ
@@ -1431,52 +1415,53 @@ class EnemyFighter {
1431
  this.isLoaded = true;
1432
  }
1433
 
1434
- update(playerPosition, deltaTime) {
1435
- if (!this.mesh || !this.isLoaded) return;
1436
-
1437
- // ํšŒํ”ผ ํƒ€์ด๋จธ ์—…๋ฐ์ดํŠธ
1438
- if (this.temporaryEvadeMode && this.evadeTimer > 0) {
1439
- this.evadeTimer -= deltaTime;
1440
- if (this.evadeTimer <= 0) {
1441
- this.temporaryEvadeMode = false;
1442
- }
1443
- }
1444
-
1445
- const distanceToPlayer = this.position.distanceTo(playerPosition);
1446
-
1447
- // ์ƒํƒœ ๊ฒฐ์ •
1448
- if (this.temporaryEvadeMode) {
1449
- this.aiState = 'evade';
1450
- } else if (distanceToPlayer <= 3000) {
1451
- this.aiState = 'combat';
1452
- } else {
1453
- this.aiState = 'patrol';
1454
- }
1455
-
1456
- // ์ถฉ๋Œ ํšŒํ”ผ ๊ณ„์‚ฐ
1457
- this.calculateAvoidance();
1458
- this.checkCollisionPrediction(deltaTime);
1459
-
1460
- // AI ํ–‰๋™ ์‹คํ–‰
1461
- switch (this.aiState) {
1462
- case 'patrol':
1463
- this.executePatrol(deltaTime);
1464
- break;
1465
- case 'combat':
1466
- this.executeCombat(playerPosition, deltaTime);
1467
- break;
1468
- case 'evade':
1469
- this.executeEmergencyEvade(deltaTime);
1470
- break;
1471
  }
1472
-
1473
- // ๋ฌผ๋ฆฌ ์—…๋ฐ์ดํŠธ
1474
- this.updatePhysics(deltaTime);
1475
-
1476
- // ํƒ„ํ™˜ ์—…๋ฐ์ดํŠธ
1477
- this.updateBullets(deltaTime);
1478
  }
1479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1480
  executePatrol(deltaTime) {
1481
  // ๋ชฉํ‘œ ์ง€์ ๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ ํ™•์ธ
1482
  if (!this.targetPosition || this.position.distanceTo(this.targetPosition) < 500) {
 
1134
  this.isLoaded = true;
1135
  }
1136
 
1137
+ // AIM-9 ๋ฏธ์‚ฌ์ผ ํด๋ž˜์Šค - update ๋ฉ”์„œ๋“œ ์ˆ˜์ •
1138
+ update(deltaTime, playerPosition) {
1139
+ if (!this.mesh || !this.target || !this.target.position) {
1140
+ this.destroy();
1141
+ return 'expired';
1142
+ }
1143
+
1144
+ this.lifeTime -= deltaTime;
1145
+ if (this.lifeTime <= 0) {
1146
+ this.destroy();
1147
+ return 'expired';
1148
+ }
1149
+
1150
+ // missileswing.ogg๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์žฌ์ƒ
1151
+ if (!this.swingAudioPlayed && this.lifeTime < 29.5) {
1152
+ try {
1153
+ this.swingAudio = new Audio('sounds/missileswing.ogg');
1154
+ this.swingAudio.volume = 0.5;
1155
+ this.swingAudio.play().catch(e => {});
1156
+ this.swingAudioPlayed = true;
1157
+ } catch (e) {
1158
+ console.log('Missile swing audio failed:', e);
1159
+ }
1160
+ }
1161
+
1162
+ // ํƒ€๊ฒŸ ์ถ”์  - ์™„๋ฒฝํ•œ ์ถ”์  ์•Œ๊ณ ๋ฆฌ์ฆ˜
1163
+ const toTarget = this.target.position.clone().sub(this.position);
1164
+ const distance = toTarget.length();
1165
+
1166
+ // ๋ช…์ค‘ ์ฒดํฌ - ๋ฒ”์œ„ ์ฆ๊ฐ€
1167
+ if (distance < 50) {
1168
+ // ๋ช…์ค‘!
1169
+ this.onHit();
1170
+ return 'hit';
1171
+ }
1172
+
1173
+ // ์™„๋ฒฝํ•œ ์ถ”์  - ํƒ€๊ฒŸ์˜ ํ˜„์žฌ ์œ„์น˜๋ฅผ ์ •ํ™•ํžˆ ์ถ”์ 
1174
+ toTarget.normalize();
1175
+
1176
+ // ์ฆ‰๊ฐ์ ์ธ ๋ฐฉํ–ฅ ์ „ํ™˜ - ํšŒ์ „์œจ ์ œํ•œ ์—†์Œ
1177
+ const newDirection = toTarget.clone();
1178
+
1179
+ // ์†๋„ ์ฆ๊ฐ€ - ๋” ๋น ๋ฅธ ์ถ”์ 
1180
+ if (this.lifeTime > 25) {
1181
+ // ์ดˆ๊ธฐ 5์ดˆ๊ฐ„ ๊ฐ€์†
1182
+ this.speed = Math.min(this.speed + deltaTime * 300, 2057.6); // ์ตœ๋Œ€ 4000kt
1183
+ } else {
1184
+ // ์ดํ›„์—๋„ ๋†’์€ ์†๋„ ์œ ์ง€
1185
+ this.speed = Math.min(this.speed + deltaTime * 100, 2057.6);
1186
+ }
1187
+
1188
+ // ํƒ€๊ฒŸ๊ณผ์˜ ๊ฑฐ๋ฆฌ์— ๋”ฐ๋ผ ์†๋„ ์ถ”๊ฐ€ ์ฆ๊ฐ€
1189
+ if (distance < 1000) {
1190
+ // ๊ทผ๊ฑฐ๋ฆฌ์—์„œ ๋”์šฑ ๋น ๋ฅด๊ฒŒ
1191
+ this.speed = Math.min(this.speed * 1.2, 2572); // ์ตœ๋Œ€ 5000kt
1192
+ }
1193
+
1194
+ this.velocity = newDirection.multiplyScalar(this.speed);
1195
+
1196
+ // ์œ„์น˜ ์—…๋ฐ์ดํŠธ
1197
+ this.position.add(this.velocity.clone().multiplyScalar(deltaTime));
1198
+ this.mesh.position.copy(this.position);
1199
+
1200
+ // ๋ฏธ์‚ฌ์ผ ํšŒ์ „ - ์ •ํ™•ํžˆ ํƒ€๊ฒŸ์„ ํ–ฅํ•จ
1201
+ this.mesh.lookAt(this.target.position);
1202
+
1203
+ // ์ถ”๋ ฅ ์—ฐ๊ธฐ ์ƒ์„ฑ
1204
+ this.smokeEmitTime += deltaTime;
1205
+ if (this.smokeEmitTime >= 0.02) {
1206
+ this.smokeEmitTime = 0;
1207
+ this.createSmokeParticle();
1208
+ }
1209
+
1210
+ // ์—ฐ๊ธฐ ํŒŒํ‹ฐํด ์—…๋ฐ์ดํŠธ
1211
+ for (let i = this.smokeTrail.length - 1; i >= 0; i--) {
1212
+ const smoke = this.smokeTrail[i];
1213
+ smoke.life -= deltaTime;
1214
+
1215
+ if (smoke.life <= 0) {
1216
+ this.scene.remove(smoke.mesh);
1217
+ this.smokeTrail.splice(i, 1);
1218
+ } else {
1219
+ // ์—ฐ๊ธฐ ํ™•์‚ฐ ๋ฐ ํŽ˜์ด๋“œ
1220
+ smoke.mesh.scale.multiplyScalar(1.02);
1221
+ smoke.mesh.material.opacity = smoke.life / 3.0;
1222
+
1223
+ // ์•ฝ๊ฐ„์˜ ์ƒ์Šน ํšจ๊ณผ
1224
+ smoke.mesh.position.y += deltaTime * 2;
1225
+ }
1226
+ }
1227
+
1228
+ // ์ง€๋ฉด ์ถฉ๋Œ
1229
+ if (this.position.y <= 0) {
1230
+ this.destroy();
1231
+ return 'expired';
1232
+ }
1233
+
1234
+ // ํƒ€๊ฒŸ์ด ์ง€๋ฉด์— ์žˆ์œผ๋ฉด ๋ฏธ์‚ฌ์ผ๋„ ๋”ฐ๋ผ๊ฐ
1235
+ if (this.target.position.y <= 50 && distance < 200) {
1236
+ // ํƒ€๊ฒŸ์ด ์ง€๋ฉด ๊ทผ์ฒ˜์— ์žˆ๊ณ  ๊ฑฐ๋ฆฌ๊ฐ€ ๊ฐ€๊นŒ์šฐ๋ฉด ์ฆ‰์‹œ ๋ช…์ค‘
1237
+ this.onHit();
1238
+ return 'hit';
1239
+ }
1240
+
1241
+ return 'flying';
1242
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1243
 
1244
  createSmokeParticle() {
1245
  // ๋ฏธ์‚ฌ์ผ ๋’ค์ชฝ ์œ„์น˜ ๊ณ„์‚ฐ
 
1415
  this.isLoaded = true;
1416
  }
1417
 
1418
+ // EnemyFighter ํด๋ž˜์Šค์˜ update ๋ฉ”์„œ๋“œ์—์„œ ๋ฏธ์‚ฌ์ผ ํšŒํ”ผ ๋กœ์ง ์ œ๊ฑฐ
1419
+ update(playerPosition, deltaTime) {
1420
+ if (!this.mesh || !this.isLoaded) return;
1421
+
1422
+ // ํšŒํ”ผ ํƒ€์ด๋จธ ์—…๋ฐ์ดํŠธ (๋ฏธ์‚ฌ์ผ ํšŒํ”ผ ์ œ์™ธ)
1423
+ if (this.temporaryEvadeMode && this.evadeTimer > 0) {
1424
+ this.evadeTimer -= deltaTime;
1425
+ if (this.evadeTimer <= 0) {
1426
+ this.temporaryEvadeMode = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1427
  }
 
 
 
 
 
 
1428
  }
1429
 
1430
+ const distanceToPlayer = this.position.distanceTo(playerPosition);
1431
+
1432
+ // ์ƒํƒœ ๊ฒฐ์ • (๋ฏธ์‚ฌ์ผ ํƒ์ง€ ์ œ๊ฑฐ)
1433
+ if (this.temporaryEvadeMode) {
1434
+ this.aiState = 'evade';
1435
+ } else if (distanceToPlayer <= 3000) {
1436
+ this.aiState = 'combat';
1437
+ } else {
1438
+ this.aiState = 'patrol';
1439
+ }
1440
+
1441
+ // ์ถฉ๋Œ ํšŒํ”ผ ๊ณ„์‚ฐ (๋‹ค๋ฅธ ์ ๊ธฐ์™€์˜ ์ถฉ๋Œ๋งŒ)
1442
+ this.calculateAvoidance();
1443
+ this.checkCollisionPrediction(deltaTime);
1444
+
1445
+ // AI ํ–‰๋™ ์‹คํ–‰
1446
+ switch (this.aiState) {
1447
+ case 'patrol':
1448
+ this.executePatrol(deltaTime);
1449
+ break;
1450
+ case 'combat':
1451
+ this.executeCombat(playerPosition, deltaTime);
1452
+ break;
1453
+ case 'evade':
1454
+ this.executeEmergencyEvade(deltaTime);
1455
+ break;
1456
+ }
1457
+
1458
+ // ๋ฌผ๋ฆฌ ์—…๋ฐ์ดํŠธ
1459
+ this.updatePhysics(deltaTime);
1460
+
1461
+ // ํƒ„ํ™˜ ์—…๋ฐ์ดํŠธ
1462
+ this.updateBullets(deltaTime);
1463
+ }
1464
+
1465
  executePatrol(deltaTime) {
1466
  // ๋ชฉํ‘œ ์ง€์ ๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ ํ™•์ธ
1467
  if (!this.targetPosition || this.position.distanceTo(this.targetPosition) < 500) {