gini1 commited on
Commit
b01cf37
โ€ข
1 Parent(s): dd60cbe

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +428 -18
index.html CHANGED
@@ -1,19 +1,429 @@
1
- <!doctype html>
2
  <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
  <html>
3
+ <head>
4
+ <title>3D Open World Game</title>
5
+ <style>
6
+ body {
7
+ margin: 0;
8
+ font-family: Arial, sans-serif;
9
+ }
10
+ canvas {
11
+ display: block;
12
+ }
13
+ #info {
14
+ position: absolute;
15
+ top: 10px;
16
+ left: 10px;
17
+ background: rgba(0,0,0,0.7);
18
+ color: white;
19
+ padding: 10px;
20
+ border-radius: 5px;
21
+ }
22
+ #weather-controls {
23
+ position: absolute;
24
+ top: 10px;
25
+ right: 10px;
26
+ background: rgba(0,0,0,0.7);
27
+ color: white;
28
+ padding: 10px;
29
+ border-radius: 5px;
30
+ }
31
+ #fileUpload {
32
+ position: absolute;
33
+ top: 50%;
34
+ left: 50%;
35
+ transform: translate(-50%, -50%);
36
+ background: rgba(0,0,0,0.8);
37
+ color: white;
38
+ padding: 20px;
39
+ border-radius: 10px;
40
+ text-align: center;
41
+ }
42
+ #fileUpload.hidden {
43
+ display: none;
44
+ }
45
+ #startButton {
46
+ margin-top: 10px;
47
+ padding: 10px 20px;
48
+ background: #4CAF50;
49
+ border: none;
50
+ color: white;
51
+ border-radius: 5px;
52
+ cursor: pointer;
53
+ }
54
+ #startButton:disabled {
55
+ background: #666;
56
+ cursor: not-allowed;
57
+ }
58
+ </style>
59
+ <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
60
+ <script type="importmap">
61
+ {
62
+ "imports": {
63
+ "three": "https://unpkg.com/three@0.149.0/build/three.module.js",
64
+ "three/addons/": "https://unpkg.com/three@0.149.0/examples/jsm/"
65
+ }
66
+ }
67
+ </script>
68
+ </head>
69
+ <body>
70
+ <div id="info">
71
+ Controls:<br>
72
+ W/S/A/D - Move<br>
73
+ SPACE - Jump<br>
74
+ Mouse - Look Around<br>
75
+ HP: <span id="hp">100</span>
76
+ </div>
77
+ <div id="weather-controls">
78
+ Weather:
79
+ <select id="weather-select" onchange="changeWeather(this.value)">
80
+ <option value="clear">Clear</option>
81
+ <option value="rain">Rain</option>
82
+ <option value="fog">Fog</option>
83
+ </select>
84
+ </div>
85
+ <div id="fileUpload">
86
+ <h2>3D Open World Game</h2>
87
+ <p>Upload your character model (GLB file)</p>
88
+ <input type="file" id="glbFile" accept=".glb" />
89
+ <br>
90
+ <button id="startButton" disabled>Start Game</button>
91
+ </div>
92
+
93
+ <script type="module">
94
+ import * as THREE from 'three';
95
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
96
+ import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
97
+
98
+ let scene, camera, renderer, controls;
99
+ let character = null;
100
+ let uploadedModel = null;
101
+
102
+ // File upload handling
103
+ const fileInput = document.getElementById('glbFile');
104
+ const startButton = document.getElementById('startButton');
105
+ const uploadDiv = document.getElementById('fileUpload');
106
+
107
+ fileInput.addEventListener('change', function(e) {
108
+ const file = e.target.files[0];
109
+ if (file) {
110
+ uploadedModel = URL.createObjectURL(file);
111
+ startButton.disabled = false;
112
+ }
113
+ });
114
+
115
+ startButton.addEventListener('click', function() {
116
+ if (uploadedModel) {
117
+ uploadDiv.classList.add('hidden');
118
+ initGame();
119
+ }
120
+ });
121
+
122
+ function initGame() {
123
+ // ๊ธฐ๋ณธ ์„ค์ •
124
+ scene = new THREE.Scene();
125
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
126
+ renderer = new THREE.WebGLRenderer({ antialias: true });
127
+ renderer.setSize(window.innerWidth, window.innerHeight);
128
+ renderer.shadowMap.enabled = true;
129
+ document.body.appendChild(renderer.domElement);
130
+
131
+ // ๋ฌผ๋ฆฌ ์‹œ์Šคํ…œ ๋ณ€์ˆ˜
132
+ const gravity = -0.5;
133
+ let velocity = new THREE.Vector3();
134
+ let isJumping = false;
135
+ let canJump = true;
136
+ let playerHeight = 2;
137
+
138
+ // ์บ๋ฆญํ„ฐ ์ƒํƒœ
139
+ let hp = 100;
140
+ const hpElement = document.getElementById('hp');
141
+
142
+ // ํฌ์ธํ„ฐ ๋ฝ ์ปจํŠธ๋กค
143
+ controls = new PointerLockControls(camera, document.body);
144
+
145
+ // ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
146
+ const moveState = {
147
+ forward: false,
148
+ backward: false,
149
+ left: false,
150
+ right: false,
151
+ jump: false
152
+ };
153
+
154
+ document.addEventListener('keydown', (event) => {
155
+ switch (event.code) {
156
+ case 'KeyW': moveState.forward = true; break;
157
+ case 'KeyS': moveState.backward = true; break;
158
+ case 'KeyA': moveState.left = true; break;
159
+ case 'KeyD': moveState.right = true; break;
160
+ case 'Space':
161
+ if (canJump) {
162
+ moveState.jump = true;
163
+ velocity.y = 10;
164
+ isJumping = true;
165
+ canJump = false;
166
+ }
167
+ break;
168
+ }
169
+ });
170
+
171
+ document.addEventListener('keyup', (event) => {
172
+ switch (event.code) {
173
+ case 'KeyW': moveState.forward = false; break;
174
+ case 'KeyS': moveState.backward = false; break;
175
+ case 'KeyA': moveState.left = false; break;
176
+ case 'KeyD': moveState.right = false; break;
177
+ case 'Space': moveState.jump = false; break;
178
+ }
179
+ });
180
+
181
+ // ํด๋ฆญ์œผ๋กœ ๊ฒŒ์ž„ ์‹œ์ž‘
182
+ document.addEventListener('click', () => {
183
+ controls.lock();
184
+ });
185
+
186
+ // ๋‚ ์”จ ์‹œ์Šคํ…œ
187
+ let raindrops = [];
188
+ const rainCount = 1000;
189
+ const rainGeometry = new THREE.BufferGeometry();
190
+ const rainMaterial = new THREE.PointsMaterial({
191
+ color: 0xaaaaaa,
192
+ size: 0.1,
193
+ transparent: true
194
+ });
195
+
196
+ function createRain() {
197
+ const positions = new Float32Array(rainCount * 3);
198
+ for (let i = 0; i < rainCount * 3; i += 3) {
199
+ positions[i] = (Math.random() - 0.5) * 1000;
200
+ positions[i + 1] = Math.random() * 500;
201
+ positions[i + 2] = (Math.random() - 0.5) * 1000;
202
+ }
203
+ rainGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
204
+ const rain = new THREE.Points(rainGeometry, rainMaterial);
205
+ scene.add(rain);
206
+ return rain;
207
+ }
208
+
209
+ let rain = createRain();
210
+ rain.visible = false;
211
+
212
+ // ์•ˆ๊ฐœ ์„ค์ •
213
+ scene.fog = new THREE.Fog(0xcce0ff, 1, 1000);
214
+
215
+ // ๋‚ ์”จ ๋ณ€๊ฒฝ ํ•จ์ˆ˜
216
+ window.changeWeather = function(weather) {
217
+ switch(weather) {
218
+ case 'clear':
219
+ rain.visible = false;
220
+ scene.fog.far = 1000;
221
+ break;
222
+ case 'rain':
223
+ rain.visible = true;
224
+ scene.fog.far = 100;
225
+ break;
226
+ case 'fog':
227
+ rain.visible = false;
228
+ scene.fog.far = 50;
229
+ break;
230
+ }
231
+ };
232
+
233
+ // NPC ์‹œ์Šคํ…œ
234
+ class NPC {
235
+ constructor(position) {
236
+ const geometry = new THREE.CapsuleGeometry(1, 2, 4, 8);
237
+ const material = new THREE.MeshPhongMaterial({ color: 0xff0000 });
238
+ this.mesh = new THREE.Mesh(geometry, material);
239
+ this.mesh.position.copy(position);
240
+ this.mesh.castShadow = true;
241
+ this.velocity = new THREE.Vector3();
242
+ this.direction = new THREE.Vector3();
243
+ scene.add(this.mesh);
244
+ }
245
+
246
+ update(playerPosition) {
247
+ this.direction.subVectors(playerPosition, this.mesh.position);
248
+ this.direction.normalize();
249
+ this.velocity.add(this.direction.multiplyScalar(0.1));
250
+ this.velocity.multiplyScalar(0.95);
251
+ this.mesh.position.add(this.velocity);
252
+
253
+ const distance = this.mesh.position.distanceTo(playerPosition);
254
+ if (distance < 2) {
255
+ hp -= 1;
256
+ hpElement.textContent = hp;
257
+ if (hp <= 0) {
258
+ alert('Game Over!');
259
+ location.reload();
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ // NPC ์ƒ์„ฑ
266
+ const npcs = [];
267
+ for (let i = 0; i < 5; i++) {
268
+ const position = new THREE.Vector3(
269
+ (Math.random() - 0.5) * 100,
270
+ 2,
271
+ (Math.random() - 0.5) * 100
272
+ );
273
+ npcs.push(new NPC(position));
274
+ }
275
+
276
+ // ์ง€ํ˜• ์ƒ์„ฑ
277
+ const terrainGeometry = new THREE.PlaneGeometry(1000, 1000, 100, 100);
278
+ const terrainMaterial = new THREE.MeshStandardMaterial({
279
+ color: 0x3a8c3a,
280
+ wireframe: false
281
+ });
282
+ const terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
283
+ terrain.rotation.x = -Math.PI / 2;
284
+ terrain.receiveShadow = true;
285
+ scene.add(terrain);
286
+
287
+ // ์ง€ํ˜• ๋†’๋‚ฎ์ด ์„ค์ •
288
+ const vertices = terrainGeometry.attributes.position.array;
289
+ for (let i = 0; i < vertices.length; i += 3) {
290
+ vertices[i + 2] = Math.random() * 10;
291
+ }
292
+ terrainGeometry.attributes.position.needsUpdate = true;
293
+ terrainGeometry.computeVertexNormals();
294
+
295
+ // ์กฐ๋ช… ์„ค์ •
296
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
297
+ scene.add(ambientLight);
298
+
299
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
300
+ directionalLight.position.set(100, 100, 100);
301
+ directionalLight.castShadow = true;
302
+ scene.add(directionalLight);
303
+
304
+ // ํ™˜๊ฒฝ ์˜ค๋ธŒ์ ํŠธ ์ถ”๊ฐ€
305
+ function addEnvironmentObject(geometry, material, count, yOffset) {
306
+ for (let i = 0; i < count; i++) {
307
+ const mesh = new THREE.Mesh(geometry, material);
308
+ const x = (Math.random() - 0.5) * 900;
309
+ const z = (Math.random() - 0.5) * 900;
310
+ const y = yOffset;
311
+ mesh.position.set(x, y, z);
312
+ mesh.castShadow = true;
313
+ mesh.receiveShadow = true;
314
+ scene.add(mesh);
315
+ }
316
+ }
317
+
318
+ // ๋‚˜๋ฌด ์ƒ์„ฑ
319
+ const treeGeometry = new THREE.ConeGeometry(2, 8, 8);
320
+ const treeMaterial = new THREE.MeshStandardMaterial({ color: 0x0d5c0d });
321
+ addEnvironmentObject(treeGeometry, treeMaterial, 100, 4);
322
+
323
+ // ๋ฐ”์œ„ ์ƒ์„ฑ
324
+ const rockGeometry = new THREE.DodecahedronGeometry(2);
325
+ const rockMaterial = new THREE.MeshStandardMaterial({ color: 0x666666 });
326
+ addEnvironmentObject(rockGeometry, rockMaterial, 50, 1);
327
+
328
+ // ์บ๋ฆญํ„ฐ ๋ชจ๋ธ ๋กœ๋“œ
329
+ const loader = new GLTFLoader();
330
+ loader.load(uploadedModel, (gltf) => {
331
+ character = gltf.scene;
332
+ character.scale.set(0.5, 0.5, 0.5);
333
+ character.position.y = 2;
334
+ character.castShadow = true;
335
+ character.receiveShadow = true;
336
+ scene.add(character);
337
+
338
+ character.traverse((node) => {
339
+ if (node.isMesh) {
340
+ node.castShadow = true;
341
+ node.receiveShadow = true;
342
+ }
343
+ });
344
+ });
345
+
346
+ // ์นด๋ฉ”๋ผ ์ดˆ๊ธฐ ์œ„์น˜
347
+ camera.position.set(0, playerHeight, 0);
348
+
349
+ // ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฃจํ”„
350
+ function animate() {
351
+ requestAnimationFrame(animate);
352
+
353
+ if (controls.isLocked) {
354
+ const direction = new THREE.Vector3();
355
+ const rotation = camera.getWorldDirection(new THREE.Vector3());
356
+
357
+ if (moveState.forward) direction.add(rotation);
358
+ if (moveState.backward) direction.sub(rotation);
359
+ if (moveState.left) direction.cross(camera.up).negate();
360
+ if (moveState.right) direction.cross(camera.up);
361
+
362
+ direction.y = 0;
363
+ direction.normalize();
364
+
365
+ // ๋ฌผ๋ฆฌ ์‹œ์Šคํ…œ ์ ์šฉ
366
+ velocity.y += gravity;
367
+ camera.position.y += velocity.y * 0.1;
368
+
369
+ // ๋ฐ”๋‹ฅ ์ถฉ๋Œ ๊ฒ€์‚ฌ
370
+ if (camera.position.y <= playerHeight) {
371
+ camera.position.y = playerHeight;
372
+ velocity.y = 0;
373
+ isJumping = false;
374
+ canJump = true;
375
+ }
376
+
377
+ // ์ด๋™ ์†๋„ ์ ์šฉ
378
+ const moveSpeed = 0.5;
379
+ controls.moveRight(-direction.z * moveSpeed);
380
+ controls.moveForward(direction.x * moveSpeed);
381
+
382
+ // ์บ๋ฆญํ„ฐ ๋ชจ๋ธ ์—…๋ฐ์ดํŠธ
383
+ if (character) {
384
+ character.position.copy(camera.position);
385
+ character.position.y -= playerHeight;
386
+ if (direction.length() > 0) {
387
+ const angle = Math.atan2(direction.x, direction.z);
388
+ character.rotation.y = angle;
389
+ }
390
+ }
391
+
392
+ // ๋น„ ์—…๋ฐ์ดํŠธ
393
+ if (rain.visible) {
394
+ const positions = rain.geometry.attributes.position.array;
395
+ for (let i = 1; i < positions.length; i +=3) {
396
+ positions[i] -= 2;
397
+ if (positions[i] < 0) {
398
+ positions[i] = 500;
399
+ }
400
+ }
401
+ rain.geometry.attributes.position.needsUpdate = true;
402
+ }
403
+
404
+ // NPC ์—…๋ฐ์ดํŠธ
405
+ npcs.forEach(npc => npc.update(camera.position));
406
+ }
407
+
408
+ renderer.render(scene, camera);
409
+ }
410
+
411
+ // ์œˆ๋„์šฐ ๋ฆฌ์‚ฌ์ด์ฆˆ ์ฒ˜๋ฆฌ
412
+ window.addEventListener('resize', () => {
413
+ camera.aspect = window.innerWidth / window.innerHeight;
414
+ camera.updateProjectionMatrix();
415
+ renderer.setSize(window.innerWidth, window.innerHeight);
416
+ });
417
+
418
+ // ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ์ž‘
419
+ animate();
420
+ }
421
+
422
+ // ๋‚ ์”จ ๋ณ€๊ฒฝ ํ•จ์ˆ˜๋ฅผ ์ „์—ญ์œผ๋กœ ๋…ธ์ถœ
423
+ window.changeWeather = function(weather) {
424
+ // ์ด ํ•จ์ˆ˜๋Š” ๊ฒŒ์ž„ ์ดˆ๊ธฐํ™” ํ›„ ์žฌ์ •์˜๋ฉ๋‹ˆ๋‹ค
425
+ console.log('Game not initialized yet');
426
+ };
427
+ </script>
428
+ </body>
429
+ </html>