cutechicken commited on
Commit
678cd65
โ€ข
1 Parent(s): c3185e4

Update game.js

Browse files
Files changed (1) hide show
  1. game.js +162 -159
game.js CHANGED
@@ -105,41 +105,30 @@ class TankPlayer {
105
  }
106
 
107
  update(mouseX, mouseY) {
108
- if (!this.body || !this.turretGroup) return;
109
-
110
- const targetAngle = Math.atan2(mouseX, mouseY);
111
- const currentRotation = this.turretGroup.rotation.y;
112
- const rotationDiff = targetAngle - currentRotation;
113
-
114
- let normalizedDiff = rotationDiff;
115
- while (normalizedDiff > Math.PI) normalizedDiff -= Math.PI * 2;
116
- while (normalizedDiff < -Math.PI) normalizedDiff += Math.PI * 2;
117
-
118
- this.turretGroup.rotation.y += normalizedDiff * 0.1;
119
-
120
- // ์ด์•Œ ์—…๋ฐ์ดํŠธ
121
- for (let i = this.bullets.length - 1; i >= 0; i--) {
122
- const bullet = this.bullets[i];
123
- bullet.position.add(bullet.velocity);
124
-
125
- // ์ด์•Œ์ด ๋งต ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋ฉด ์ œ๊ฑฐ
126
- if (Math.abs(bullet.position.x) > MAP_SIZE/2 ||
127
- Math.abs(bullet.position.z) > MAP_SIZE/2) {
128
- scene.remove(bullet);
129
- this.bullets.splice(i, 1);
130
- }
131
- }
132
- }
133
 
134
  move(direction) {
135
- if (!this.body) return;
136
-
137
- const moveVector = new THREE.Vector3();
138
- moveVector.x = direction.x * this.moveSpeed;
139
- moveVector.z = direction.z * this.moveSpeed;
140
-
141
- moveVector.applyEuler(this.body.rotation);
142
- this.body.position.add(moveVector);
143
  }
144
 
145
  rotate(angle) {
@@ -339,142 +328,156 @@ class Game {
339
  }
340
 
341
  async initialize() {
342
- try {
343
- // ์กฐ๋ช… ์„ค์ •
344
- const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
345
- this.scene.add(ambientLight);
346
-
347
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
348
- directionalLight.position.set(50, 50, 50);
349
- directionalLight.castShadow = true;
350
- directionalLight.shadow.mapSize.width = 2048;
351
- directionalLight.shadow.mapSize.height = 2048;
352
- this.scene.add(directionalLight);
353
-
354
- // ์ง€ํ˜• ์ƒ์„ฑ
355
- const ground = new THREE.Mesh(
356
- new THREE.PlaneGeometry(MAP_SIZE, MAP_SIZE),
357
- new THREE.MeshStandardMaterial({
358
- color: 0x333333,
359
- roughness: 0.9,
360
- metalness: 0.1
361
- })
362
- );
363
- ground.rotation.x = -Math.PI / 2;
364
- ground.receiveShadow = true;
365
- this.scene.add(ground);
366
-
367
- // ๊ฑด๋ฌผ ์ƒ์„ฑ
368
- await this.createBuildings();
369
-
370
- // ํƒฑํฌ ์ดˆ๊ธฐํ™”
371
- await this.tank.initialize(this.scene, this.loader);
372
- if (!this.tank.isLoaded) {
373
- throw new Error('Tank loading failed');
374
- }
375
-
376
- // FPS ์นด๋ฉ”๋ผ ์„ค์ •
377
- this.camera.position.set(-15, 10, -15);
378
- this.camera.lookAt(new THREE.Vector3(0, 0, 0));
379
-
380
- // ๋กœ๋”ฉ ์™„๋ฃŒ
381
- this.isLoading = false;
382
- document.getElementById('loading').style.display = 'none';
383
-
384
- // ๊ฒŒ์ž„ ์‹œ์ž‘
385
- this.animate();
386
- this.spawnEnemies();
387
- this.startGameTimer();
388
-
389
- } catch (error) {
390
- console.error('Game initialization error:', error);
391
- this.handleLoadingError();
392
- }
393
- }
394
 
395
  setupEventListeners() {
396
- // ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ
397
- document.addEventListener('keydown', (event) => {
398
- if (this.isLoading) return;
399
- switch(event.code) {
400
- case 'KeyW': this.keys.forward = true; break;
401
- case 'KeyS': this.keys.backward = true; break;
402
- case 'KeyA': this.keys.left = true; break;
403
- case 'KeyD': this.keys.right = true; break;
404
- case 'Escape':
405
- if (this.controls.isLocked) {
406
- this.controls.unlock();
407
- }
408
- break;
409
- }
410
- });
411
-
412
- document.addEventListener('keyup', (event) => {
413
- if (this.isLoading) return;
414
- switch(event.code) {
415
- case 'KeyW': this.keys.forward = false; break;
416
- case 'KeyS': this.keys.backward = false; break;
417
- case 'KeyA': this.keys.left = false; break;
418
- case 'KeyD': this.keys.right = false; break;
419
- }
420
- });
421
-
422
- // ๋ฐœ์‚ฌ ๋ฐ ํฌ์ธํ„ฐ ๋ฝ ์ด๋ฒคํŠธ
423
- document.addEventListener('click', () => {
424
- if (document.pointerLockElement !== document.body) {
425
- this.controls.lock();
426
- } else {
427
- const bullet = this.tank.shoot(this.scene);
428
- if (bullet) {
429
- // ์ด์•Œ ๋ฐœ์‚ฌ ํšจ๊ณผ์Œ์ด๋‚˜ ์‹œ๊ฐํšจ๊ณผ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
430
- }
431
- }
432
- });
433
-
434
- // ์ฐฝ ํฌ๊ธฐ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ
435
- window.addEventListener('resize', () => {
436
- this.camera.aspect = window.innerWidth / window.innerHeight;
437
- this.camera.updateProjectionMatrix();
438
- this.renderer.setSize(window.innerWidth, window.innerHeight);
439
- });
440
- }
441
-
442
- handleMovement() {
443
- if (!this.tank.isLoaded || !this.controls.isLocked) return;
444
 
445
- const direction = new THREE.Vector3();
446
- const cameraDirection = new THREE.Vector3();
447
- this.camera.getWorldDirection(cameraDirection);
448
 
449
- if (this.keys.forward) direction.z += 1;
450
- if (this.keys.backward) direction.z -= 1;
451
- if (this.keys.left) direction.x -= 1;
452
- if (this.keys.right) direction.x += 1;
453
 
454
- if (direction.length() > 0) {
455
- direction.normalize();
456
- // ์นด๋ฉ”๋ผ ๋ฐฉํ–ฅ์„ ๊ธฐ์ค€์œผ๋กœ ์ด๋™
457
- direction.applyAxisAngle(new THREE.Vector3(0, 1, 0), this.camera.rotation.y);
458
- this.tank.move(direction);
459
-
460
- // ํƒฑํฌ ๋ณธ์ฒด๋ฅผ ์นด๋ฉ”๋ผ ๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „
461
- if (Math.abs(direction.z) > 0 || Math.abs(direction.x) > 0) {
462
- this.tank.body.rotation.y = Math.atan2(direction.x, direction.z);
463
- }
464
  }
 
465
 
466
- // ์นด๋ฉ”๋ผ์™€ ํƒฑํฌ ๋™๊ธฐํ™”
467
- const tankPos = this.tank.getPosition();
468
- const cameraOffset = new THREE.Vector3(-15, 10, -15);
469
- cameraOffset.applyQuaternion(this.tank.body.quaternion);
470
- this.camera.position.copy(tankPos).add(cameraOffset);
471
- this.camera.lookAt(tankPos);
 
472
 
473
- // ํฌํƒ‘ ํšŒ์ „์„ ์นด๋ฉ”๋ผ์™€ ๋™๊ธฐํ™”
474
- if (this.tank.turret) {
475
- this.tank.turret.rotation.y = this.camera.rotation.y;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  }
477
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  createBuildings() {
479
  const buildingTypes = [
480
  { width: 10, height: 30, depth: 10, color: 0x808080 },
 
105
  }
106
 
107
  update(mouseX, mouseY) {
108
+ if (!this.body || !this.turretGroup) return;
109
+
110
+ // ์ด์•Œ ์—…๋ฐ์ดํŠธ๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ  ํฌํƒ‘ ํšŒ์ „์€ Game ํด๋ž˜์Šค์˜ handleMovement์—์„œ ์ฒ˜๋ฆฌ
111
+ for (let i = this.bullets.length - 1; i >= 0; i--) {
112
+ const bullet = this.bullets[i];
113
+ bullet.position.add(bullet.velocity);
114
+
115
+ // ์ด์•Œ์ด ๋งต ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋ฉด ์ œ๊ฑฐ
116
+ if (Math.abs(bullet.position.x) > MAP_SIZE/2 ||
117
+ Math.abs(bullet.position.z) > MAP_SIZE/2) {
118
+ scene.remove(bullet);
119
+ this.bullets.splice(i, 1);
120
+ }
121
+ }
122
+ }
 
 
 
 
 
 
 
 
 
 
123
 
124
  move(direction) {
125
+ if (!this.body) return;
126
+
127
+ const moveVector = new THREE.Vector3();
128
+ moveVector.x = direction.x * this.moveSpeed;
129
+ moveVector.z = direction.z * this.moveSpeed;
130
+
131
+ this.body.position.add(moveVector);
 
132
  }
133
 
134
  rotate(angle) {
 
328
  }
329
 
330
  async initialize() {
331
+ try {
332
+ // ์กฐ๋ช… ์„ค์ •
333
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
334
+ this.scene.add(ambientLight);
335
+
336
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
337
+ directionalLight.position.set(50, 50, 50);
338
+ directionalLight.castShadow = true;
339
+ directionalLight.shadow.mapSize.width = 2048;
340
+ directionalLight.shadow.mapSize.height = 2048;
341
+ this.scene.add(directionalLight);
342
+
343
+ // ์ง€ํ˜• ์ƒ์„ฑ
344
+ const ground = new THREE.Mesh(
345
+ new THREE.PlaneGeometry(MAP_SIZE, MAP_SIZE),
346
+ new THREE.MeshStandardMaterial({
347
+ color: 0x333333,
348
+ roughness: 0.9,
349
+ metalness: 0.1
350
+ })
351
+ );
352
+ ground.rotation.x = -Math.PI / 2;
353
+ ground.receiveShadow = true;
354
+ this.scene.add(ground);
355
+
356
+ // ๊ฑด๋ฌผ ์ƒ์„ฑ
357
+ await this.createBuildings();
358
+
359
+ // ํƒฑํฌ ์ดˆ๊ธฐํ™”
360
+ await this.tank.initialize(this.scene, this.loader);
361
+ if (!this.tank.isLoaded) {
362
+ throw new Error('Tank loading failed');
363
+ }
364
+
365
+ // ์นด๋ฉ”๋ผ ์„ค์ • ์ˆ˜์ •
366
+ this.camera.position.set(-20, 10, -20);
367
+ this.camera.lookAt(new THREE.Vector3(0, 0, 0));
368
+
369
+ // ๋กœ๋”ฉ ์™„๋ฃŒ
370
+ this.isLoading = false;
371
+ document.getElementById('loading').style.display = 'none';
372
+
373
+ // ๊ฒŒ์ž„ ์‹œ์ž‘
374
+ this.animate();
375
+ this.spawnEnemies();
376
+ this.startGameTimer();
377
+
378
+ } catch (error) {
379
+ console.error('Game initialization error:', error);
380
+ this.handleLoadingError();
381
+ }
382
+ }
383
 
384
  setupEventListeners() {
385
+ // ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ
386
+ document.addEventListener('keydown', (event) => {
387
+ if (this.isLoading) return;
388
+ switch(event.code) {
389
+ case 'KeyW': this.keys.forward = true; break;
390
+ case 'KeyS': this.keys.backward = true; break;
391
+ case 'KeyA': this.keys.left = true; break;
392
+ case 'KeyD': this.keys.right = true; break;
393
+ case 'Escape': break; // controls ๊ด€๋ จ ์ฝ”๋“œ ์ œ๊ฑฐ
394
+ }
395
+ });
396
+
397
+ document.addEventListener('keyup', (event) => {
398
+ if (this.isLoading) return;
399
+ switch(event.code) {
400
+ case 'KeyW': this.keys.forward = false; break;
401
+ case 'KeyS': this.keys.backward = false; break;
402
+ case 'KeyA': this.keys.left = false; break;
403
+ case 'KeyD': this.keys.right = false; break;
404
+ }
405
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
 
407
+ // ๋งˆ์šฐ์Šค ์›€์ง์ž„ ์ด๋ฒคํŠธ ์ถ”๊ฐ€
408
+ document.addEventListener('mousemove', (event) => {
409
+ if (this.isLoading) return;
410
 
411
+ // ํ™”๋ฉด ์ค‘์•™ ๊ธฐ์ค€์œผ๋กœ ๋งˆ์šฐ์Šค ์œ„์น˜ ๊ณ„์‚ฐ
412
+ const centerX = window.innerWidth / 2;
413
+ const centerY = window.innerHeight / 2;
 
414
 
415
+ this.mouse.x = (event.clientX - centerX) / centerX;
416
+ this.mouse.y = (event.clientY - centerY) / centerY;
417
+ });
418
+
419
+ // ๋ฐœ์‚ฌ ์ด๋ฒคํŠธ (ํฌ์ธํ„ฐ ๋ฝ ๊ด€๋ จ ์ฝ”๋“œ ์ œ๊ฑฐ)
420
+ document.addEventListener('click', () => {
421
+ const bullet = this.tank.shoot(this.scene);
422
+ if (bullet) {
423
+ // ์ด์•Œ ๋ฐœ์‚ฌ ํšจ๊ณผ์Œ์ด๋‚˜ ์‹œ๊ฐํšจ๊ณผ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ
 
424
  }
425
+ });
426
 
427
+ // ์ฐฝ ํฌ๊ธฐ ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ
428
+ window.addEventListener('resize', () => {
429
+ this.camera.aspect = window.innerWidth / window.innerHeight;
430
+ this.camera.updateProjectionMatrix();
431
+ this.renderer.setSize(window.innerWidth, window.innerHeight);
432
+ });
433
+ }
434
 
435
+ handleMovement() {
436
+ if (!this.tank.isLoaded) return;
437
+
438
+ const direction = new THREE.Vector3();
439
+
440
+ if (this.keys.forward) direction.z += 1;
441
+ if (this.keys.backward) direction.z -= 1;
442
+ if (this.keys.left) direction.x -= 1;
443
+ if (this.keys.right) direction.x += 1;
444
+
445
+ if (direction.length() > 0) {
446
+ direction.normalize();
447
+ // ํƒฑํฌ์˜ ํ˜„์žฌ ํšŒ์ „์„ ๊ธฐ์ค€์œผ๋กœ ์ด๋™
448
+ direction.applyEuler(this.tank.body.rotation);
449
+ this.tank.move(direction);
450
+
451
+ // ํƒฑํฌ ๋ณธ์ฒด ํšŒ์ „
452
+ if (Math.abs(direction.z) > 0 || Math.abs(direction.x) > 0) {
453
+ const angle = Math.atan2(direction.x, direction.z);
454
+ this.tank.body.rotation.y = angle;
455
  }
456
  }
457
+
458
+ // ๋งˆ์šฐ์Šค ์›€์ง์ž„์— ๋”ฐ๋ฅธ ํฌํƒ‘๊ณผ ์นด๋ฉ”๋ผ ํšŒ์ „
459
+ const rotationAngle = Math.atan2(this.mouse.x, -this.mouse.y);
460
+
461
+ // ํฌํƒ‘ ํšŒ์ „
462
+ if (this.tank.turretGroup) {
463
+ this.tank.turretGroup.rotation.y = rotationAngle;
464
+ }
465
+
466
+ // ์นด๋ฉ”๋ผ ์œ„์น˜ ๋ฐ ํšŒ์ „ ์—…๋ฐ์ดํŠธ
467
+ const tankPos = this.tank.getPosition();
468
+ const cameraDistance = 20;
469
+ const cameraHeight = 10;
470
+
471
+ // ์นด๋ฉ”๋ผ ์œ„์น˜ ๊ณ„์‚ฐ
472
+ const cameraOffset = new THREE.Vector3(
473
+ Math.sin(rotationAngle) * cameraDistance,
474
+ cameraHeight,
475
+ Math.cos(rotationAngle) * cameraDistance
476
+ );
477
+
478
+ this.camera.position.copy(tankPos).sub(cameraOffset);
479
+ this.camera.lookAt(tankPos);
480
+ }
481
  createBuildings() {
482
  const buildingTypes = [
483
  { width: 10, height: 30, depth: 10, color: 0x808080 },