Spaces:
Running
Running
Update game.js
Browse files
game.js
CHANGED
|
@@ -836,6 +836,21 @@ class Enemy {
|
|
| 836 |
this.adjustTankTilt();
|
| 837 |
}
|
| 838 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 839 |
|
| 840 |
findAlternativePath(playerPosition) {
|
| 841 |
const currentPos = this.mesh.position.clone();
|
|
@@ -872,6 +887,13 @@ findAlternativePath(playerPosition) {
|
|
| 872 |
return null;
|
| 873 |
}
|
| 874 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 875 |
|
| 876 |
async initialize(loader) {
|
| 877 |
try {
|
|
@@ -898,22 +920,56 @@ findAlternativePath(playerPosition) {
|
|
| 898 |
|
| 899 |
// μμΌ νμΈ λ©μλ (κΈ°μ‘΄ μ½λ μμ )
|
| 900 |
checkLineOfSight(playerPosition) {
|
| 901 |
-
|
| 902 |
|
| 903 |
-
|
| 904 |
-
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
.
|
| 909 |
-
const distance = startPos.distanceTo(playerPosition);
|
| 910 |
|
| 911 |
-
|
| 912 |
-
|
| 913 |
|
| 914 |
-
|
| 915 |
-
|
| 916 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 917 |
// κ²½λ‘ μ ν¨μ± νμΈ
|
| 918 |
checkPathClear(start, end) {
|
| 919 |
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
|
@@ -1521,7 +1577,7 @@ class Game {
|
|
| 1521 |
this.obstacles = [];
|
| 1522 |
}
|
| 1523 |
|
| 1524 |
-
const BUILDING_COUNT =
|
| 1525 |
const buildingModels = [
|
| 1526 |
'models/house1.glb',
|
| 1527 |
'models/house2.glb',
|
|
@@ -2317,52 +2373,47 @@ updateCrosshair() {
|
|
| 2317 |
}
|
| 2318 |
|
| 2319 |
animate() {
|
| 2320 |
-
|
| 2321 |
-
|
| 2322 |
-
|
| 2323 |
-
|
| 2324 |
-
|
| 2325 |
-
|
| 2326 |
|
| 2327 |
-
|
| 2328 |
-
|
| 2329 |
-
|
| 2330 |
-
|
| 2331 |
-
|
| 2332 |
-
|
| 2333 |
-
}
|
| 2334 |
|
| 2335 |
-
|
| 2336 |
-
|
| 2337 |
-
|
| 2338 |
|
| 2339 |
-
|
| 2340 |
-
|
| 2341 |
-
|
| 2342 |
-
|
| 2343 |
-
|
| 2344 |
-
|
| 2345 |
-
|
| 2346 |
-
|
| 2347 |
-
|
| 2348 |
-
|
| 2349 |
-
|
| 2350 |
-
|
| 2351 |
-
|
| 2352 |
-
|
| 2353 |
-
|
| 2354 |
-
|
| 2355 |
-
|
| 2356 |
-
|
| 2357 |
-
|
| 2358 |
-
|
| 2359 |
-
|
| 2360 |
-
|
| 2361 |
-
|
| 2362 |
-
this.updateCrosshair();
|
| 2363 |
-
}
|
| 2364 |
-
|
| 2365 |
-
this.renderer.render(this.scene, this.camera);
|
| 2366 |
}
|
| 2367 |
|
| 2368 |
// Start game
|
|
|
|
| 836 |
this.adjustTankTilt();
|
| 837 |
}
|
| 838 |
|
| 839 |
+
checkLineOfSight(targetPosition) {
|
| 840 |
+
if (!this.mesh) return false;
|
| 841 |
+
|
| 842 |
+
const startPos = this.mesh.position.clone();
|
| 843 |
+
startPos.y += 2; // ν¬ν λμ΄
|
| 844 |
+
const direction = new THREE.Vector3()
|
| 845 |
+
.subVectors(targetPosition, startPos)
|
| 846 |
+
.normalize();
|
| 847 |
+
const distance = startPos.distanceTo(targetPosition);
|
| 848 |
+
|
| 849 |
+
const raycaster = new THREE.Raycaster(startPos, direction, 0, distance);
|
| 850 |
+
const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);
|
| 851 |
+
|
| 852 |
+
return intersects.length === 0;
|
| 853 |
+
}
|
| 854 |
|
| 855 |
findAlternativePath(playerPosition) {
|
| 856 |
const currentPos = this.mesh.position.clone();
|
|
|
|
| 887 |
return null;
|
| 888 |
}
|
| 889 |
|
| 890 |
+
checkPathClear(start, end) {
|
| 891 |
+
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
| 892 |
+
const distance = start.distanceTo(end);
|
| 893 |
+
const raycaster = new THREE.Raycaster(start, direction, 0, distance);
|
| 894 |
+
const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);
|
| 895 |
+
return intersects.length === 0;
|
| 896 |
+
}
|
| 897 |
|
| 898 |
async initialize(loader) {
|
| 899 |
try {
|
|
|
|
| 920 |
|
| 921 |
// μμΌ νμΈ λ©μλ (κΈ°μ‘΄ μ½λ μμ )
|
| 922 |
checkLineOfSight(playerPosition) {
|
| 923 |
+
if (!this.mesh) return false;
|
| 924 |
|
| 925 |
+
const startPos = this.mesh.position.clone();
|
| 926 |
+
startPos.y += 2; // ν¬ν λμ΄
|
| 927 |
+
const direction = new THREE.Vector3()
|
| 928 |
+
.subVectors(playerPosition, startPos)
|
| 929 |
+
.normalize();
|
| 930 |
+
const distance = startPos.distanceTo(playerPosition);
|
|
|
|
| 931 |
|
| 932 |
+
const raycaster = new THREE.Raycaster(startPos, direction, 0, distance);
|
| 933 |
+
const intersects = raycaster.intersectObjects(window.gameInstance.obstacles, true);
|
| 934 |
|
| 935 |
+
// μ₯μ λ¬Όκ³Όμ μΆ©λμ΄ μλμ§ νμΈ
|
| 936 |
+
return intersects.length === 0;
|
| 937 |
+
}
|
| 938 |
+
// λ체 κ²½λ‘ μ°ΎκΈ° λ©μλ
|
| 939 |
+
findAlternativePath(playerPosition) {
|
| 940 |
+
const currentPos = this.mesh.position.clone();
|
| 941 |
+
const directionToPlayer = new THREE.Vector3()
|
| 942 |
+
.subVectors(playerPosition, currentPos)
|
| 943 |
+
.normalize();
|
| 944 |
+
|
| 945 |
+
// μ’μ° 90λ λ°©ν₯ κ³μ°
|
| 946 |
+
const leftDirection = new THREE.Vector3()
|
| 947 |
+
.copy(directionToPlayer)
|
| 948 |
+
.applyAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
|
| 949 |
+
const rightDirection = new THREE.Vector3()
|
| 950 |
+
.copy(directionToPlayer)
|
| 951 |
+
.applyAxisAngle(new THREE.Vector3(0, 1, 0), -Math.PI / 2);
|
| 952 |
+
|
| 953 |
+
// μ’μ° 30λ―Έν° μ§μ νμΈ
|
| 954 |
+
const checkDistance = 30;
|
| 955 |
+
const leftPoint = currentPos.clone().add(leftDirection.multiplyScalar(checkDistance));
|
| 956 |
+
const rightPoint = currentPos.clone().add(rightDirection.multiplyScalar(checkDistance));
|
| 957 |
+
|
| 958 |
+
// κ° λ°©ν₯μ μ₯μ λ¬Ό 체ν¬
|
| 959 |
+
const leftClear = this.checkPathClear(currentPos, leftPoint);
|
| 960 |
+
const rightClear = this.checkPathClear(currentPos, rightPoint);
|
| 961 |
+
|
| 962 |
+
if (leftClear && rightClear) {
|
| 963 |
+
// λ λ€ κ°λ₯νλ©΄ λλ€ μ ν
|
| 964 |
+
return Math.random() < 0.5 ? leftPoint : rightPoint;
|
| 965 |
+
} else if (leftClear) {
|
| 966 |
+
return leftPoint;
|
| 967 |
+
} else if (rightClear) {
|
| 968 |
+
return rightPoint;
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
return null;
|
| 972 |
+
}
|
| 973 |
// κ²½λ‘ μ ν¨μ± νμΈ
|
| 974 |
checkPathClear(start, end) {
|
| 975 |
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
|
|
|
| 1577 |
this.obstacles = [];
|
| 1578 |
}
|
| 1579 |
|
| 1580 |
+
const BUILDING_COUNT = 70; // λ°μ λμ κ±΄λ¬Όλ‘ λ³κ²½
|
| 1581 |
const buildingModels = [
|
| 1582 |
'models/house1.glb',
|
| 1583 |
'models/house2.glb',
|
|
|
|
| 2373 |
}
|
| 2374 |
|
| 2375 |
animate() {
|
| 2376 |
+
if (this.isGameOver) {
|
| 2377 |
+
if (this.animationFrameId) {
|
| 2378 |
+
cancelAnimationFrame(this.animationFrameId);
|
| 2379 |
+
}
|
| 2380 |
+
return;
|
| 2381 |
+
}
|
| 2382 |
|
| 2383 |
+
this.animationFrameId = requestAnimationFrame(() => this.animate());
|
| 2384 |
+
// κ²μμ΄ μμλμ§ μμμΌλ©΄ λ λλ§λ§ μν
|
| 2385 |
+
if (!this.isStarted) {
|
| 2386 |
+
this.renderer.render(this.scene, this.camera);
|
| 2387 |
+
return;
|
| 2388 |
+
}
|
|
|
|
| 2389 |
|
| 2390 |
+
const currentTime = performance.now();
|
| 2391 |
+
const deltaTime = (currentTime - this.lastTime) / 1000;
|
| 2392 |
+
this.lastTime = currentTime;
|
| 2393 |
|
| 2394 |
+
if (!this.isLoading) {
|
| 2395 |
+
this.handleMovement();
|
| 2396 |
+
this.tank.update(this.mouse.x, this.mouse.y, this.scene);
|
| 2397 |
+
|
| 2398 |
+
const tankPosition = this.tank.getPosition();
|
| 2399 |
+
this.enemies.forEach(enemy => {
|
| 2400 |
+
enemy.update(tankPosition);
|
| 2401 |
+
|
| 2402 |
+
if (enemy.isLoaded && enemy.mesh.position.distanceTo(tankPosition) < ENEMY_CONFIG.ATTACK_RANGE) {
|
| 2403 |
+
enemy.shoot(tankPosition);
|
| 2404 |
+
}
|
| 2405 |
+
});
|
| 2406 |
+
this.updateEnemyLabels(); // μ λΌλ²¨ μ
λ°μ΄νΈ μΆκ°
|
| 2407 |
+
this.updateParticles();
|
| 2408 |
+
this.checkCollisions();
|
| 2409 |
+
this.updateUI();
|
| 2410 |
+
this.updateRadar(); // λ μ΄λ μ
λ°μ΄νΈ μΆκ°
|
| 2411 |
+
// ν¬λ‘μ€ν€μ΄ μ
λ°μ΄νΈ μΆκ°
|
| 2412 |
+
this.updateCrosshair();
|
| 2413 |
+
}
|
| 2414 |
+
|
| 2415 |
+
this.renderer.render(this.scene, this.camera);
|
| 2416 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2417 |
}
|
| 2418 |
|
| 2419 |
// Start game
|