gini1 commited on
Commit
e4c0247
1 Parent(s): 2c63faf

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +370 -22
index.html CHANGED
@@ -1,44 +1,392 @@
1
- keys[event.key.toLowerCase()] = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- function onKeyUp(event) {
5
- keys[event.key.toLowerCase()] = false;
 
 
 
 
 
6
  }
7
 
8
- function onMouseMove(event) {
9
- const rotSpeed = 0.002;
10
- player.rotation.y -= event.movementX * rotSpeed;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
12
 
13
- function movePlayer() {
14
- const speed = 0.1;
15
- const direction = new THREE.Vector3();
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- if (keys['w']) direction.z -= speed;
18
- if (keys['s']) direction.z += speed;
19
- if (keys['a']) direction.x -= speed;
20
- if (keys['d']) direction.x += speed;
 
 
 
 
 
 
 
 
 
 
21
 
22
- direction.applyAxisAngle(new THREE.Vector3(0, 1, 0), player.rotation.y);
23
- player.position.add(direction);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- // Camera follows player
26
- camera.position.x = player.position.x;
27
- camera.position.z = player.position.z + 5;
28
- camera.lookAt(player.position);
29
  }
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  function animate() {
32
  requestAnimationFrame(animate);
33
- movePlayer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  renderer.render(scene, camera);
35
  }
36
 
 
37
  window.addEventListener('resize', () => {
38
  camera.aspect = window.innerWidth / window.innerHeight;
39
  camera.updateProjectionMatrix();
40
- renderer.setSize(window.innerWidth, window.innerHeight);
 
 
 
 
41
  });
 
 
 
 
42
  </script>
43
  </body>
44
- </html>
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Survival Game</title>
5
+ <style>
6
+ body { margin: 0; font-family: Arial, sans-serif; }
7
+ canvas { display: block; }
8
+ #gameInfo {
9
+ position: absolute;
10
+ top: 10px;
11
+ left: 10px;
12
+ background: rgba(0,0,0,0.7);
13
+ color: white;
14
+ padding: 10px;
15
+ border-radius: 5px;
16
  }
17
+ #safeTimer {
18
+ position: absolute;
19
+ top: 50%;
20
+ left: 50%;
21
+ transform: translate(-50%, -50%);
22
+ background: rgba(0,0,0,0.7);
23
+ color: white;
24
+ padding: 20px;
25
+ border-radius: 10px;
26
+ font-size: 24px;
27
+ display: none;
28
+ }
29
+ #weaponInfo {
30
+ position: absolute;
31
+ bottom: 20px;
32
+ left: 50%;
33
+ transform: translateX(-50%);
34
+ background: rgba(0,0,0,0.7);
35
+ color: white;
36
+ padding: 10px;
37
+ border-radius: 5px;
38
+ font-size: 18px;
39
+ display: none;
40
+ }
41
+ </style>
42
+ <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
43
+ <script type="importmap">
44
+ {
45
+ "imports": {
46
+ "three": "https://unpkg.com/three@0.149.0/build/three.module.js",
47
+ "three/addons/": "https://unpkg.com/three@0.149.0/examples/jsm/"
48
+ }
49
+ }
50
+ </script>
51
+ </head>
52
+ <body>
53
+ <div id="gameInfo">
54
+ Controls:<br>
55
+ W/S/A/D - Move<br>
56
+ SPACE - Jump<br>
57
+ Mouse - Look Around<br>
58
+ Survive and find the weapon!
59
+ </div>
60
+ <div id="safeTimer"></div>
61
+ <div id="weaponInfo">Weapon appeared! Get it to win!</div>
62
+
63
+ <script type="module">
64
+ import * as THREE from 'three';
65
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
66
+ import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
67
+
68
+ let scene, camera, renderer, controls;
69
+ let playerModel, enemies = [], weapon;
70
+ let isSafePeriod = true;
71
+ let gameStartTime = Date.now();
72
+ const SAFE_PERIOD = 10; // 10초 안전 시간
73
+ const MAP_SIZE = 2000; // 더 큰 맵 크기
74
+ const ENEMY_COUNT = 8; // 적의 수 증가
75
+ let weaponSpawned = false;
76
+
77
+ // 게임 초기화
78
+ function init() {
79
+ // 기본 설정
80
+ scene = new THREE.Scene();
81
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, MAP_SIZE * 0.6);
82
+ renderer = new THREE.WebGLRenderer({ antialias: true });
83
+ renderer.setSize(window.innerWidth, window.innerHeight);
84
+ renderer.shadowMap.enabled = true;
85
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
86
+ document.body.appendChild(renderer.domElement);
87
+
88
+ // 포인터 락 컨트롤
89
+ controls = new PointerLockControls(camera, document.body);
90
+
91
+ // 클릭으로 게임 시작
92
+ document.addEventListener('click', () => {
93
+ controls.lock();
94
+ });
95
+
96
+ // 지형 생성
97
+ createTerrain();
98
+
99
+ // 조명 설정
100
+ setupLights();
101
+
102
+ // 플레이어 모델 로드
103
+ loadPlayerModel();
104
+
105
+ // 적 모델 로드
106
+ loadEnemies();
107
+
108
+ // 환경 요소 추가
109
+ createEnvironment();
110
+
111
+ // 무기 스폰 타이머 설정
112
+ setTimeout(spawnWeapon, getRandomTime(15000, 30000));
113
+
114
+ // 키보드 컨트롤 설정
115
+ setupControls();
116
+
117
+ // 카메라 초기 위치
118
+ camera.position.set(0, 5, 0);
119
+ }
120
+
121
+ // 지형 생성 함수
122
+ function createTerrain() {
123
+ const geometry = new THREE.PlaneGeometry(MAP_SIZE, MAP_SIZE, 200, 200);
124
+ const material = new THREE.MeshStandardMaterial({
125
+ color: 0x3a8c3a,
126
+ wireframe: false
127
+ });
128
+
129
+ // 높낮이 설정
130
+ const vertices = geometry.attributes.position.array;
131
+ for (let i = 0; i < vertices.length; i += 3) {
132
+ vertices[i + 2] = Math.pow(Math.sin(vertices[i] * 0.02) + Math.cos(vertices[i + 1] * 0.02), 2) * 15;
133
+ }
134
+ geometry.attributes.position.needsUpdate = true;
135
+ geometry.computeVertexNormals();
136
+
137
+ const terrain = new THREE.Mesh(geometry, material);
138
+ terrain.rotation.x = -Math.PI / 2;
139
+ terrain.receiveShadow = true;
140
+ scene.add(terrain);
141
+ }
142
+
143
+ // 조명 설정
144
+ function setupLights() {
145
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
146
+ scene.add(ambientLight);
147
+
148
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
149
+ directionalLight.position.set(1000, 1000, 1000);
150
+ directionalLight.castShadow = true;
151
+ directionalLight.shadow.mapSize.width = 2048;
152
+ directionalLight.shadow.mapSize.height = 2048;
153
+ directionalLight.shadow.camera.near = 0.5;
154
+ directionalLight.shadow.camera.far = 3000;
155
+ directionalLight.shadow.camera.left = -1000;
156
+ directionalLight.shadow.camera.right = 1000;
157
+ directionalLight.shadow.camera.top = 1000;
158
+ directionalLight.shadow.camera.bottom = -1000;
159
+ scene.add(directionalLight);
160
+ }
161
+
162
+ // 플레이어 모델 로드
163
+ function loadPlayerModel() {
164
+ const loader = new GLTFLoader();
165
+ loader.load('me.glb', (gltf) => {
166
+ playerModel = gltf.scene;
167
+ playerModel.scale.set(0.5, 0.5, 0.5);
168
+ playerModel.castShadow = true;
169
+ playerModel.receiveShadow = true;
170
+ scene.add(playerModel);
171
 
172
+ playerModel.traverse((node) => {
173
+ if (node.isMesh) {
174
+ node.castShadow = true;
175
+ node.receiveShadow = true;
176
+ }
177
+ });
178
+ });
179
  }
180
 
181
+ // 로드 및 생성
182
+ function loadEnemies() {
183
+ const loader = new GLTFLoader();
184
+ loader.load('enemy.glb', (gltf) => {
185
+ const enemyModel = gltf.scene;
186
+
187
+ for (let i = 0; i < ENEMY_COUNT; i++) {
188
+ const enemy = enemyModel.clone();
189
+ enemy.scale.set(0.5, 0.5, 0.5);
190
+ enemy.position.set(
191
+ (Math.random() - 0.5) * MAP_SIZE * 0.8,
192
+ 5,
193
+ (Math.random() - 0.5) * MAP_SIZE * 0.8
194
+ );
195
+ enemy.castShadow = true;
196
+ enemy.receiveShadow = true;
197
+ scene.add(enemy);
198
+
199
+ enemies.push({
200
+ model: enemy,
201
+ velocity: new THREE.Vector3(),
202
+ speed: 0.3 + Math.random() * 0.3
203
+ });
204
+ }
205
+ });
206
  }
207
 
208
+ // 환경 요소 생성
209
+ function createEnvironment() {
210
+ // 나무 생성
211
+ const treeGeometry = new THREE.CylinderGeometry(0, 4, 20, 8);
212
+ const treeMaterial = new THREE.MeshStandardMaterial({ color: 0x0d5c0d });
213
+ for (let i = 0; i < 500; i++) {
214
+ const tree = new THREE.Mesh(treeGeometry, treeMaterial);
215
+ tree.position.set(
216
+ (Math.random() - 0.5) * MAP_SIZE * 0.9,
217
+ 10,
218
+ (Math.random() - 0.5) * MAP_SIZE * 0.9
219
+ );
220
+ tree.castShadow = true;
221
+ tree.receiveShadow = true;
222
+ scene.add(tree);
223
+ }
224
 
225
+ // 바위 생성
226
+ const rockGeometry = new THREE.DodecahedronGeometry(3);
227
+ const rockMaterial = new THREE.MeshStandardMaterial({ color: 0x666666 });
228
+ for (let i = 0; i < 200; i++) {
229
+ const rock = new THREE.Mesh(rockGeometry, rockMaterial);
230
+ rock.position.set(
231
+ (Math.random() - 0.5) * MAP_SIZE * 0.9,
232
+ 3,
233
+ (Math.random() - 0.5) * MAP_SIZE * 0.9
234
+ );
235
+ rock.castShadow = true;
236
+ rock.receiveShadow = true;
237
+ scene.add(rock);
238
+ }
239
 
240
+ // 안개 추가
241
+ scene.fog = new THREE.Fog(0xcce0ff, 0, MAP_SIZE * 0.3);
242
+ }
243
+
244
+ // 무기 생성
245
+ function spawnWeapon() {
246
+ const weaponGeometry = new THREE.BoxGeometry(2, 0.5, 8);
247
+ const weaponMaterial = new THREE.MeshStandardMaterial({
248
+ color: 0xffd700,
249
+ metalness: 0.7,
250
+ roughness: 0.3,
251
+ emissive: 0xffd700,
252
+ emissiveIntensity: 0.5
253
+ });
254
+ weapon = new THREE.Mesh(weaponGeometry, weaponMaterial);
255
+ weapon.position.set(
256
+ (Math.random() - 0.5) * MAP_SIZE * 0.6,
257
+ 5,
258
+ (Math.random() - 0.5) * MAP_SIZE * 0.6
259
+ );
260
+ weapon.rotation.y = Math.random() * Math.PI * 2;
261
+ weapon.castShadow = true;
262
+ scene.add(weapon);
263
+ weaponSpawned = true;
264
+
265
+ // 무기 출현 알림 표시
266
+ const weaponInfo = document.getElementById('weaponInfo');
267
+ weaponInfo.style.display = 'block';
268
+ setTimeout(() => weaponInfo.style.display = 'none', 5000);
269
+ }
270
 
271
+ // 랜덤 시간 생성
272
+ function getRandomTime(min, max) {
273
+ return Math.floor(Math.random() * (max - min)) + min;
 
274
  }
275
 
276
+ // 컨트롤 설정
277
+ function setupControls() {
278
+ const moveState = {
279
+ forward: false,
280
+ backward: false,
281
+ left: false,
282
+ right: false,
283
+ jump: false
284
+ };
285
+
286
+ document.addEventListener('keydown', (event) => {
287
+ switch (event.code) {
288
+ case 'KeyW': moveState.forward = true; break;
289
+ case 'KeyS': moveState.backward = true; break;
290
+ case 'KeyA': moveState.left = true; break;
291
+ case 'KeyD': moveState.right = true; break;
292
+ }
293
+ });
294
+
295
+ document.addEventListener('keyup', (event) => {
296
+ switch (event.code) {
297
+ case 'KeyW': moveState.forward = false; break;
298
+ case 'KeyS': moveState.backward = false; break;
299
+ case 'KeyA': moveState.left = false; break;
300
+ case 'KeyD': moveState.right = false; break;
301
+ }
302
+ });
303
+ }
304
+
305
+ // 게임 승리
306
+ function victory() {
307
+ alert('Congratulations! You found the weapon and won!');
308
+ location.reload();
309
+ }
310
+
311
+ // 게임 오버
312
+ function gameOver() {
313
+ alert('Game Over! You were caught!');
314
+ location.reload();
315
+ }
316
+
317
+ // 애니메이션 루프
318
  function animate() {
319
  requestAnimationFrame(animate);
320
+
321
+ if (controls.isLocked) {
322
+ // 안전 시간 체크
323
+ const elapsedTime = Math.floor((Date.now() - gameStartTime) / 1000);
324
+ const remainingTime = SAFE_PERIOD - elapsedTime;
325
+
326
+ const safeTimer = document.getElementById('safeTimer');
327
+ if (remainingTime > 0) {
328
+ safeTimer.style.display = 'block';
329
+ safeTimer.textContent = `Safe Period: ${remainingTime}s`;
330
+ isSafePeriod = true;
331
+ } else {
332
+ safeTimer.style.display = 'none';
333
+ isSafePeriod = false;
334
+ }
335
+
336
+ // 적 업데이트
337
+ enemies.forEach(enemy => {
338
+ if (!isSafePeriod) {
339
+ const direction = new THREE.Vector3();
340
+ direction.subVectors(camera.position, enemy.model.position);
341
+ direction.y = 0;
342
+ direction.normalize();
343
+
344
+ enemy.velocity.add(direction.multiplyScalar(enemy.speed));
345
+ enemy.velocity.multiplyScalar(0.98);
346
+ enemy.model.position.add(enemy.velocity);
347
+
348
+ // 적과의 충돌 체크
349
+ if (enemy.model.position.distanceTo(camera.position) < 3) {
350
+ gameOver();
351
+ }
352
+
353
+ // 적 회전
354
+ enemy.model.lookAt(camera.position);
355
+ }
356
+ });
357
+
358
+ // 무기와의 충돌 체크
359
+ if (weaponSpawned && weapon) {
360
+ if (weapon.position.distanceTo(camera.position) < 3) {
361
+ victory();
362
+ }
363
+ }
364
+
365
+ // 플레이어 모델 업데이트
366
+ if (playerModel) {
367
+ playerModel.position.copy(camera.position);
368
+ playerModel.position.y -= 2;
369
+ playerModel.rotation.y = camera.rotation.y;
370
+ }
371
+ }
372
+
373
  renderer.render(scene, camera);
374
  }
375
 
376
+ // 윈도우 리사이즈 처리
377
  window.addEventListener('resize', () => {
378
  camera.aspect = window.innerWidth / window.innerHeight;
379
  camera.updateProjectionMatrix();
380
+ renderer.setSize(window.innerWidth, window
381
+
382
+
383
+
384
+ renderer.setSize(window.innerWidth, window.innerHeight);
385
  });
386
+
387
+ // 게임 시작
388
+ init();
389
+ animate();
390
  </script>
391
  </body>
392
+ </html>