gini1 commited on
Commit
975cece
โ€ข
1 Parent(s): 5ccac0e

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +205 -96
index.html CHANGED
@@ -1,7 +1,7 @@
1
  <!DOCTYPE html>
2
  <html>
3
  <head>
4
- <title>3D Survival Game</title>
5
  <meta charset="utf-8">
6
  <style>
7
  body {
@@ -33,19 +33,46 @@
33
  z-index: 100;
34
  border-radius: 5px;
35
  }
36
- #targetAlert {
37
  position: absolute;
38
  top: 50%;
39
  left: 50%;
40
  transform: translate(-50%, -50%);
41
- color: yellow;
42
- background: rgba(0,0,0,0.8);
43
- padding: 20px;
44
- font-family: Arial;
45
  font-size: 24px;
46
  z-index: 100;
 
 
 
 
 
 
 
 
 
 
 
 
47
  border-radius: 10px;
48
- display: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
  </style>
51
  </head>
@@ -54,11 +81,13 @@
54
  Click to start<br>
55
  WASD - Move<br>
56
  Mouse - Look around<br>
57
- Find and touch your clone to win!<br>
58
- Avoid the enemies!
59
  </div>
60
  <div id="timer">Safe Time: 10s</div>
61
- <div id="targetAlert">Find and touch your clone to win!</div>
 
 
62
 
63
  <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
64
 
@@ -78,17 +107,23 @@
78
 
79
  // ๊ธฐ๋ณธ ๋ณ€์ˆ˜
80
  let scene, camera, renderer, controls;
81
- let enemies = [], target;
 
82
  let isGameOver = false;
83
  let isSafePeriod = true;
84
  let startTime = 0;
85
- const SAFE_TIME = 10; // 10์ดˆ ์•ˆ์ „์‹œ๊ฐ„
 
 
 
 
 
86
 
87
  // Scene ์ดˆ๊ธฐํ™”
88
  function initScene() {
89
  scene = new THREE.Scene();
90
  scene.background = new THREE.Color(0x87ceeb);
91
- scene.fog = new THREE.Fog(0x87ceeb, 0, 300);
92
 
93
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
94
  camera.position.set(0, 5, 0);
@@ -111,11 +146,124 @@
111
  dirLight.shadow.camera.far = 300;
112
  scene.add(dirLight);
113
 
114
- // ๋ฐ˜์‚ฌ๊ด‘ ์ถ”๊ฐ€
115
  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
116
  scene.add(hemiLight);
117
  }
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  // ์ง€ํ˜• ์ƒ์„ฑ
120
  function createTerrain() {
121
  const geometry = new THREE.PlaneGeometry(300, 300, 50, 50);
@@ -138,78 +286,28 @@
138
  scene.add(terrain);
139
  }
140
 
141
- // ๋‚˜๋ฌด ์ƒ์„ฑ
142
- function createTrees() {
143
- const treeGeo = new THREE.CylinderGeometry(0, 4, 15, 8);
144
- const treeMat = new THREE.MeshStandardMaterial({
145
- color: 0x0d5c0d,
146
- roughness: 0.8,
147
- metalness: 0.2
148
- });
149
-
150
- for (let i = 0; i < 100; i++) {
151
- const tree = new THREE.Mesh(treeGeo, treeMat);
152
- tree.position.set(
153
- (Math.random() - 0.5) * 250,
154
- 7.5,
155
- (Math.random() - 0.5) * 250
156
- );
157
- tree.castShadow = true;
158
- tree.receiveShadow = true;
159
- scene.add(tree);
160
- }
161
- }
162
-
163
- // ๋ชฉํ‘œ๋ฌผ(Clone) ์ƒ์„ฑ
164
- function spawnTarget() {
165
- const loader = new GLTFLoader();
166
- loader.load('me.glb', (gltf) => {
167
- target = gltf.scene;
168
- target.scale.set(0.5, 0.5, 0.5);
169
- target.position.set(
170
- (Math.random() - 0.5) * 200,
171
- 0,
172
- (Math.random() - 0.5) * 200
173
- );
174
-
175
- target.traverse((node) => {
176
- if (node.isMesh) {
177
- node.material.metalness = 0.3;
178
- node.material.roughness = 0.5;
179
- node.castShadow = true;
180
- node.receiveShadow = true;
181
- }
182
- });
183
-
184
- scene.add(target);
185
-
186
- document.getElementById('targetAlert').style.display = 'block';
187
- setTimeout(() => {
188
- document.getElementById('targetAlert').style.display = 'none';
189
- }, 3000);
190
- });
191
- }
192
-
193
  // ์  ๋กœ๋“œ
194
  function loadEnemies() {
195
  const loader = new GLTFLoader();
196
  loader.load('enemy.glb', (gltf) => {
 
197
  const enemyModel = gltf.scene;
198
 
199
  for (let i = 0; i < 5; i++) {
200
  const enemy = enemyModel.clone();
201
- enemy.scale.set(0.5, 0.5, 0.5);
202
 
203
  const angle = (i / 5) * Math.PI * 2;
204
- const radius = 100;
205
  enemy.position.set(
206
  Math.cos(angle) * radius,
207
- 0,
208
  Math.sin(angle) * radius
209
  );
210
 
211
  enemy.traverse((node) => {
212
  if (node.isMesh) {
 
213
  node.material.metalness = 0.3;
214
  node.material.roughness = 0.5;
215
  node.castShadow = true;
@@ -220,12 +318,20 @@
220
  scene.add(enemy);
221
  enemies.push({
222
  model: enemy,
 
223
  speed: 0.2,
224
  velocity: new THREE.Vector3(),
225
- rotation: new THREE.Euler()
226
  });
227
  }
228
- console.log('Enemies loaded');
 
 
 
 
 
 
 
229
  });
230
  }
231
 
@@ -240,12 +346,14 @@
240
  right: false
241
  };
242
 
 
243
  document.addEventListener('keydown', (event) => {
244
  switch(event.code) {
245
  case 'KeyW': moveState.forward = true; break;
246
  case 'KeyS': moveState.backward = true; break;
247
  case 'KeyA': moveState.left = true; break;
248
  case 'KeyD': moveState.right = true; break;
 
249
  }
250
  });
251
 
@@ -258,16 +366,20 @@
258
  }
259
  });
260
 
 
261
  document.addEventListener('click', () => {
262
- if (!startTime) {
263
- startTime = Date.now();
264
- setTimeout(spawnTarget, Math.random() * 5000 + 5000);
 
265
  }
266
- controls.lock();
267
  });
268
 
269
  controls.addEventListener('lock', () => {
270
  document.getElementById('info').style.display = 'none';
 
 
 
271
  });
272
 
273
  controls.addEventListener('unlock', () => {
@@ -281,30 +393,28 @@
281
  function updateEnemies() {
282
  if (!isSafePeriod) {
283
  enemies.forEach(enemy => {
 
284
  const direction = new THREE.Vector3();
285
  direction.subVectors(camera.position, enemy.model.position);
286
  direction.y = 0;
287
  direction.normalize();
288
 
289
- // ๋ถ€๋“œ๋Ÿฌ์šด ์†๋„ ๋ณ€ํ™”
290
  enemy.velocity.lerp(direction.multiplyScalar(enemy.speed), 0.02);
291
  enemy.model.position.add(enemy.velocity);
292
 
293
- // ๋ถ€๋“œ๋Ÿฌ์šด ํšŒ์ „
294
- const targetRotation = Math.atan2(direction.x, direction.z);
295
- enemy.model.rotation.y = THREE.MathUtils.lerp(
296
- enemy.model.rotation.y,
297
- targetRotation,
298
- 0.05
299
- );
300
 
301
- // ์ถฉ๋Œ ์ฒดํฌ
302
- if (enemy.model.position.distanceTo(camera.position) < 3) {
303
- gameOver(false);
 
 
304
  }
305
  });
306
  }
307
- }
 
308
 
309
  // ๊ฒŒ์ž„ ์˜ค๋ฒ„ ์ฒ˜๋ฆฌ
310
  function gameOver(won) {
@@ -312,7 +422,7 @@
312
  isGameOver = true;
313
  controls.unlock();
314
  setTimeout(() => {
315
- alert(won ? 'You found your clone and won!' : 'Game Over! You were caught!');
316
  location.reload();
317
  }, 100);
318
  }
@@ -322,7 +432,6 @@
322
  function init() {
323
  initScene();
324
  createTerrain();
325
- createTrees();
326
  loadEnemies();
327
  const moveState = initControls();
328
 
@@ -350,15 +459,15 @@
350
  if (moveState.left) controls.moveRight(-speed);
351
  if (moveState.right) controls.moveRight(speed);
352
 
 
 
 
353
  // ์  ์—…๋ฐ์ดํŠธ
354
  updateEnemies();
355
 
356
- // ๋ชฉํ‘œ๋ฌผ ์ฒดํฌ
357
- if (target) {
358
- target.rotation.y += 0.01;
359
- if (camera.position.distanceTo(target.position) < 3) {
360
- gameOver(true);
361
- }
362
  }
363
  }
364
 
@@ -379,4 +488,4 @@
379
  init();
380
  </script>
381
  </body>
382
- </html>
 
1
  <!DOCTYPE html>
2
  <html>
3
  <head>
4
+ <title>3D Shooter Game</title>
5
  <meta charset="utf-8">
6
  <style>
7
  body {
 
33
  z-index: 100;
34
  border-radius: 5px;
35
  }
36
+ #crosshair {
37
  position: absolute;
38
  top: 50%;
39
  left: 50%;
40
  transform: translate(-50%, -50%);
41
+ color: rgba(255, 255, 255, 0.8);
 
 
 
42
  font-size: 24px;
43
  z-index: 100;
44
+ user-select: none;
45
+ pointer-events: none;
46
+ }
47
+ #healthBar {
48
+ position: absolute;
49
+ bottom: 20px;
50
+ left: 20px;
51
+ width: 200px;
52
+ height: 20px;
53
+ background: rgba(0,0,0,0.5);
54
+ border: 2px solid white;
55
+ z-index: 100;
56
  border-radius: 10px;
57
+ overflow: hidden;
58
+ }
59
+ #health {
60
+ width: 100%;
61
+ height: 100%;
62
+ background: #ff3333;
63
+ transition: width 0.3s;
64
+ }
65
+ #ammo {
66
+ position: absolute;
67
+ bottom: 20px;
68
+ right: 20px;
69
+ color: white;
70
+ background: rgba(0,0,0,0.7);
71
+ padding: 10px;
72
+ font-family: Arial;
73
+ font-size: 18px;
74
+ z-index: 100;
75
+ border-radius: 5px;
76
  }
77
  </style>
78
  </head>
 
81
  Click to start<br>
82
  WASD - Move<br>
83
  Mouse - Look around<br>
84
+ Left Click - Shoot<br>
85
+ R - Reload
86
  </div>
87
  <div id="timer">Safe Time: 10s</div>
88
+ <div id="crosshair">+</div>
89
+ <div id="healthBar"><div id="health"></div></div>
90
+ <div id="ammo">Ammo: 30/30</div>
91
 
92
  <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
93
 
 
107
 
108
  // ๊ธฐ๋ณธ ๋ณ€์ˆ˜
109
  let scene, camera, renderer, controls;
110
+ let enemies = [], bullets = [];
111
+ let enemyBullets = [];
112
  let isGameOver = false;
113
  let isSafePeriod = true;
114
  let startTime = 0;
115
+ let playerHealth = 100;
116
+ let ammo = 30;
117
+ const maxAmmo = 30;
118
+ const SAFE_TIME = 10;
119
+ const raycaster = new THREE.Raycaster();
120
+ const mouse = new THREE.Vector2();
121
 
122
  // Scene ์ดˆ๊ธฐํ™”
123
  function initScene() {
124
  scene = new THREE.Scene();
125
  scene.background = new THREE.Color(0x87ceeb);
126
+ scene.fog = new THREE.Fog(0x87ceeb, 0, 500);
127
 
128
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
129
  camera.position.set(0, 5, 0);
 
146
  dirLight.shadow.camera.far = 300;
147
  scene.add(dirLight);
148
 
149
+ // ๋ฐ˜์‚ฌ๊ด‘
150
  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
151
  scene.add(hemiLight);
152
  }
153
 
154
+ // ์ด์•Œ ์ƒ์„ฑ
155
+ function createBullet(isEnemy = false) {
156
+ const bulletGeometry = new THREE.SphereGeometry(0.1, 8, 8);
157
+ const bulletMaterial = new THREE.MeshBasicMaterial({
158
+ color: isEnemy ? 0xff0000 : 0xffff00
159
+ });
160
+ const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
161
+
162
+ if (!isEnemy) {
163
+ bullet.position.copy(camera.position);
164
+ const direction = new THREE.Vector3();
165
+ camera.getWorldDirection(direction);
166
+ bullet.velocity = direction.multiplyScalar(2);
167
+ }
168
+
169
+ scene.add(bullet);
170
+ return bullet;
171
+ }
172
+
173
+ // ๋ฐœ์‚ฌ
174
+ function shoot() {
175
+ if (ammo <= 0) return;
176
+
177
+ ammo--;
178
+ updateAmmoDisplay();
179
+
180
+ const bullet = createBullet();
181
+ bullets.push(bullet);
182
+
183
+ // ๋ฐœ์‚ฌ ์‚ฌ์šด๋“œ๋‚˜ ์ดํŽ™ํŠธ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ
184
+ }
185
+
186
+ // ์  ๋ฐœ์‚ฌ
187
+ function enemyShoot(enemy) {
188
+ const bullet = createBullet(true);
189
+ bullet.position.copy(enemy.model.position);
190
+
191
+ const direction = new THREE.Vector3();
192
+ direction.subVectors(camera.position, enemy.model.position);
193
+ direction.normalize();
194
+ bullet.velocity = direction.multiplyScalar(1);
195
+
196
+ enemyBullets.push(bullet);
197
+ }
198
+
199
+ // ์ด์•Œ ์—…๋ฐ์ดํŠธ
200
+ function updateBullets() {
201
+ // ํ”Œ๋ ˆ์ด์–ด ์ด์•Œ
202
+ for (let i = bullets.length - 1; i >= 0; i--) {
203
+ bullets[i].position.add(bullets[i].velocity);
204
+
205
+ // ์ ๊ณผ์˜ ์ถฉ๋Œ ์ฒดํฌ
206
+ enemies.forEach(enemy => {
207
+ if (bullets[i].position.distanceTo(enemy.model.position) < 2) {
208
+ scene.remove(bullets[i]);
209
+ bullets.splice(i, 1);
210
+ enemy.health -= 25;
211
+
212
+ if (enemy.health <= 0) {
213
+ scene.remove(enemy.model);
214
+ enemies = enemies.filter(e => e !== enemy);
215
+ }
216
+ return;
217
+ }
218
+ });
219
+
220
+ // ์ˆ˜๋ช… ์ œํ•œ
221
+ if (bullets[i] && bullets[i].position.distanceTo(camera.position) > 100) {
222
+ scene.remove(bullets[i]);
223
+ bullets.splice(i, 1);
224
+ }
225
+ }
226
+
227
+ // ์  ์ด์•Œ
228
+ for (let i = enemyBullets.length - 1; i >= 0; i--) {
229
+ enemyBullets[i].position.add(enemyBullets[i].velocity);
230
+
231
+ // ํ”Œ๋ ˆ์ด์–ด์™€์˜ ์ถฉ๋Œ ์ฒดํฌ
232
+ if (enemyBullets[i].position.distanceTo(camera.position) < 2) {
233
+ scene.remove(enemyBullets[i]);
234
+ enemyBullets.splice(i, 1);
235
+ playerHealth -= 10;
236
+ updateHealthBar();
237
+
238
+ if (playerHealth <= 0) {
239
+ gameOver(false);
240
+ }
241
+ continue;
242
+ }
243
+
244
+ // ์ˆ˜๋ช… ์ œํ•œ
245
+ if (enemyBullets[i] && enemyBullets[i].position.distanceTo(camera.position) > 100) {
246
+ scene.remove(enemyBullets[i]);
247
+ enemyBullets.splice(i, 1);
248
+ }
249
+ }
250
+ }
251
+
252
+ function updateHealthBar() {
253
+ const healthBar = document.getElementById('health');
254
+ healthBar.style.width = `${playerHealth}%`;
255
+ }
256
+
257
+ function updateAmmoDisplay() {
258
+ document.getElementById('ammo').textContent = `Ammo: ${ammo}/${maxAmmo}`;
259
+ }
260
+
261
+ // ์žฌ์žฅ์ „
262
+ function reload() {
263
+ ammo = maxAmmo;
264
+ updateAmmoDisplay();
265
+ }
266
+
267
  // ์ง€ํ˜• ์ƒ์„ฑ
268
  function createTerrain() {
269
  const geometry = new THREE.PlaneGeometry(300, 300, 50, 50);
 
286
  scene.add(terrain);
287
  }
288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  // ์  ๋กœ๋“œ
290
  function loadEnemies() {
291
  const loader = new GLTFLoader();
292
  loader.load('enemy.glb', (gltf) => {
293
+ console.log('Enemy model loaded successfully');
294
  const enemyModel = gltf.scene;
295
 
296
  for (let i = 0; i < 5; i++) {
297
  const enemy = enemyModel.clone();
298
+ enemy.scale.set(1, 1, 1); // ํฌ๊ธฐ ์ฆ๊ฐ€
299
 
300
  const angle = (i / 5) * Math.PI * 2;
301
+ const radius = 50; // ๋” ๊ฐ€๊น๊ฒŒ ์‹œ์ž‘
302
  enemy.position.set(
303
  Math.cos(angle) * radius,
304
+ 2, // ์ง€๋ฉด์—์„œ ์•ฝ๊ฐ„ ์œ„๋กœ
305
  Math.sin(angle) * radius
306
  );
307
 
308
  enemy.traverse((node) => {
309
  if (node.isMesh) {
310
+ node.material = node.material.clone(); // ์žฌ์งˆ ๋ณต์ œ
311
  node.material.metalness = 0.3;
312
  node.material.roughness = 0.5;
313
  node.castShadow = true;
 
318
  scene.add(enemy);
319
  enemies.push({
320
  model: enemy,
321
+ health: 100,
322
  speed: 0.2,
323
  velocity: new THREE.Vector3(),
324
+ lastShot: 0
325
  });
326
  }
327
+ },
328
+ // ๋กœ๋”ฉ ์ง„ํ–‰์ƒํ™ฉ
329
+ (xhr) => {
330
+ console.log((xhr.loaded / xhr.total * 100) + '% loaded');
331
+ },
332
+ // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
333
+ (error) => {
334
+ console.error('Error loading enemy model:', error);
335
  });
336
  }
337
 
 
346
  right: false
347
  };
348
 
349
+ // ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ
350
  document.addEventListener('keydown', (event) => {
351
  switch(event.code) {
352
  case 'KeyW': moveState.forward = true; break;
353
  case 'KeyS': moveState.backward = true; break;
354
  case 'KeyA': moveState.left = true; break;
355
  case 'KeyD': moveState.right = true; break;
356
+ case 'KeyR': reload(); break;
357
  }
358
  });
359
 
 
366
  }
367
  });
368
 
369
+ // ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ
370
  document.addEventListener('click', () => {
371
+ if (controls.isLocked) {
372
+ shoot();
373
+ } else {
374
+ controls.lock();
375
  }
 
376
  });
377
 
378
  controls.addEventListener('lock', () => {
379
  document.getElementById('info').style.display = 'none';
380
+ if (!startTime) {
381
+ startTime = Date.now();
382
+ }
383
  });
384
 
385
  controls.addEventListener('unlock', () => {
 
393
  function updateEnemies() {
394
  if (!isSafePeriod) {
395
  enemies.forEach(enemy => {
396
+ // ์ด๋™ ๋กœ์ง
397
  const direction = new THREE.Vector3();
398
  direction.subVectors(camera.position, enemy.model.position);
399
  direction.y = 0;
400
  direction.normalize();
401
 
 
402
  enemy.velocity.lerp(direction.multiplyScalar(enemy.speed), 0.02);
403
  enemy.model.position.add(enemy.velocity);
404
 
405
+ // ํšŒ์ „
406
+ enemy.model.lookAt(camera.position);
 
 
 
 
 
407
 
408
+ // ๋ฐœ์‚ฌ ๋กœ์ง
409
+ const now = Date.now();
410
+ if (now - enemy.lastShot > 2000) { // 2์ดˆ๋งˆ๋‹ค ๋ฐœ์‚ฌ
411
+ enemyShoot(enemy);
412
+ enemy.lastShot = now;
413
  }
414
  });
415
  }
416
+
417
+ }
418
 
419
  // ๊ฒŒ์ž„ ์˜ค๋ฒ„ ์ฒ˜๋ฆฌ
420
  function gameOver(won) {
 
422
  isGameOver = true;
423
  controls.unlock();
424
  setTimeout(() => {
425
+ alert(won ? 'You won!' : 'Game Over! You were eliminated!');
426
  location.reload();
427
  }, 100);
428
  }
 
432
  function init() {
433
  initScene();
434
  createTerrain();
 
435
  loadEnemies();
436
  const moveState = initControls();
437
 
 
459
  if (moveState.left) controls.moveRight(-speed);
460
  if (moveState.right) controls.moveRight(speed);
461
 
462
+ // ์ด์•Œ ์—…๋ฐ์ดํŠธ
463
+ updateBullets();
464
+
465
  // ์  ์—…๋ฐ์ดํŠธ
466
  updateEnemies();
467
 
468
+ // ์Šน๋ฆฌ ์กฐ๊ฑด ์ฒดํฌ
469
+ if (!isSafePeriod && enemies.length === 0) {
470
+ gameOver(true);
 
 
 
471
  }
472
  }
473
 
 
488
  init();
489
  </script>
490
  </body>
491
+ </html>