enzostvs HF staff commited on
Commit
3ee26fa
·
verified ·
1 Parent(s): eb42271

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +435 -18
index.html CHANGED
@@ -1,19 +1,436 @@
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 lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>3D Snake Game</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ overflow: hidden;
11
+ }
12
+ #score {
13
+ position: absolute;
14
+ top: 10px;
15
+ left: 10px;
16
+ color: white;
17
+ font-family: Arial, sans-serif;
18
+ font-size: 20px;
19
+ }
20
+ #gameOver {
21
+ position: absolute;
22
+ top: 50%;
23
+ left: 50%;
24
+ transform: translate(-50%, -50%);
25
+ color: white;
26
+ font-family: Arial, sans-serif;
27
+ font-size: 36px;
28
+ display: none;
29
+ }
30
+ #bonusActive {
31
+ position: absolute;
32
+ top: 40px;
33
+ left: 10px;
34
+ color: gold;
35
+ font-family: Arial, sans-serif;
36
+ font-size: 20px;
37
+ display: none;
38
+ }
39
+ </style>
40
+ </head>
41
+ <body>
42
+ <div id="score">Score: 0</div>
43
+ <div id="bonusActive">SPEED BOOST ACTIVE!</div>
44
+ <div id="gameOver">Game Over! Press Space to restart</div>
45
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
46
+ <script>
47
+ // Game variables
48
+ let scene, camera, renderer;
49
+ let snake = [],
50
+ food,
51
+ goldenFood;
52
+ let direction = { x: 1, y: 0, z: 0 };
53
+ let gridSize = 20;
54
+ let speed = 5; // Moves per second
55
+ let baseSpeed = 5; // Default speed
56
+ let lastTime = 0;
57
+ let score = 0;
58
+ let isGameOver = false;
59
+ let bonusActive = false;
60
+ let bonusEndTime = 0;
61
+ let goldenFoodChance = 0.2; // 20% chance
62
+ let bonusSpeedMultiplier = 1.5; // 50% faster
63
+ let bonusDuration = 5000; // 5 seconds
64
+ // Camera rotation variables
65
+ let cameraRotationSpeed = 0.0005; // Speed of rotation
66
+ let cameraRotationRadius = 40; // Distance from center
67
+ let cameraRotationAngle = 0; // Current angle
68
+ let cameraRotationActive = true; // Toggle rotation
69
+ let cameraHeight = 30; // Height of camera
70
+
71
+ // Initialize the game
72
+ function init() {
73
+ // Create scene
74
+ scene = new THREE.Scene();
75
+ scene.background = new THREE.Color(0x333333);
76
+
77
+ // Create camera
78
+ camera = new THREE.PerspectiveCamera(
79
+ 75,
80
+ window.innerWidth / window.innerHeight,
81
+ 0.1,
82
+ 1000
83
+ );
84
+ // Set initial camera position
85
+ camera.position.set(0, cameraHeight, cameraRotationRadius);
86
+ camera.lookAt(0, 0, 0);
87
+
88
+ // Create renderer
89
+ renderer = new THREE.WebGLRenderer({ antialias: true });
90
+ renderer.setSize(window.innerWidth, window.innerHeight);
91
+ document.body.appendChild(renderer.domElement);
92
+
93
+ // Add lights
94
+ const ambientLight = new THREE.AmbientLight(0x404040);
95
+ scene.add(ambientLight);
96
+
97
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
98
+ directionalLight.position.set(10, 20, 15);
99
+ scene.add(directionalLight);
100
+
101
+ // Add grid for reference
102
+ const gridHelper = new THREE.GridHelper(gridSize, gridSize);
103
+ scene.add(gridHelper);
104
+
105
+ // Create snake
106
+ createSnake();
107
+
108
+ // Create food
109
+ createFood();
110
+
111
+ // Add event listeners
112
+ document.addEventListener("keydown", handleKeyDown);
113
+ window.addEventListener("resize", onWindowResize);
114
+
115
+ // Start animation loop
116
+ animate();
117
+ }
118
+
119
+ // Create initial snake
120
+ function createSnake() {
121
+ // Start with a single segment
122
+ const geometry = new THREE.BoxGeometry(0.9, 0.9, 0.9);
123
+ const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
124
+ const segment = new THREE.Mesh(geometry, material);
125
+ segment.position.set(0, 0.5, 0);
126
+ scene.add(segment);
127
+ snake.push({ mesh: segment, position: { x: 0, y: 0, z: 0 } });
128
+ }
129
+
130
+ // Create food
131
+ function createFood() {
132
+ // Remove old food if exists
133
+ if (food) scene.remove(food.mesh);
134
+
135
+ const geometry = new THREE.SphereGeometry(0.5);
136
+ const material = new THREE.MeshPhongMaterial({ color: 0xff0000 });
137
+ const mesh = new THREE.Mesh(geometry, material);
138
+
139
+ // Random position
140
+ let position = getRandomPosition();
141
+
142
+ // Make sure food doesn't spawn on snake
143
+ while (isPositionOccupied(position)) {
144
+ position = getRandomPosition();
145
+ }
146
+
147
+ mesh.position.set(position.x, 0.5, position.z);
148
+ scene.add(mesh);
149
+ food = { mesh: mesh, position: position };
150
+
151
+ // Random chance to create golden food
152
+ if (Math.random() < goldenFoodChance) {
153
+ setTimeout(createGoldenFood, Math.random() * 5000 + 2000);
154
+ }
155
+ }
156
+
157
+ // Create golden bonus food
158
+ function createGoldenFood() {
159
+ if (isGameOver || goldenFood) return;
160
+
161
+ const geometry = new THREE.SphereGeometry(0.6);
162
+ const material = new THREE.MeshPhongMaterial({
163
+ color: 0xffd700,
164
+ emissive: 0xffd700,
165
+ emissiveIntensity: 0.5,
166
+ });
167
+ const mesh = new THREE.Mesh(geometry, material);
168
+
169
+ // Random position
170
+ let position = getRandomPosition();
171
+
172
+ // Make sure golden food doesn't spawn on snake or regular food
173
+ while (
174
+ isPositionOccupied(position) ||
175
+ (food &&
176
+ position.x === food.position.x &&
177
+ position.z === food.position.z)
178
+ ) {
179
+ position = getRandomPosition();
180
+ }
181
+
182
+ mesh.position.set(position.x, 0.5, position.z);
183
+ scene.add(mesh);
184
+ goldenFood = { mesh: mesh, position: position };
185
+
186
+ // Make golden food disappear after some time
187
+ setTimeout(() => {
188
+ if (goldenFood) {
189
+ scene.remove(goldenFood.mesh);
190
+ goldenFood = null;
191
+ }
192
+ }, 5000);
193
+ }
194
+
195
+ // Get random grid position
196
+ function getRandomPosition() {
197
+ const halfGrid = Math.floor(gridSize / 2);
198
+ return {
199
+ x: Math.floor(Math.random() * gridSize) - halfGrid,
200
+ y: 0,
201
+ z: Math.floor(Math.random() * gridSize) - halfGrid,
202
+ };
203
+ }
204
+
205
+ // Check if position is occupied by snake
206
+ function isPositionOccupied(position) {
207
+ return snake.some(
208
+ (segment) =>
209
+ segment.position.x === position.x &&
210
+ segment.position.z === position.z
211
+ );
212
+ }
213
+
214
+ // Move the snake
215
+ function moveSnake() {
216
+ if (isGameOver) return;
217
+
218
+ // Calculate new head position
219
+ const head = snake[0];
220
+ const newPosition = {
221
+ x: head.position.x + direction.x,
222
+ y: 0,
223
+ z: head.position.z + direction.z,
224
+ };
225
+
226
+ // Handle wrap-around at boundaries
227
+ const halfGrid = Math.floor(gridSize / 2);
228
+ if (newPosition.x < -halfGrid) {
229
+ newPosition.x = halfGrid - 1;
230
+ } else if (newPosition.x >= halfGrid) {
231
+ newPosition.x = -halfGrid;
232
+ }
233
+
234
+ if (newPosition.z < -halfGrid) {
235
+ newPosition.z = halfGrid - 1;
236
+ } else if (newPosition.z >= halfGrid) {
237
+ newPosition.z = -halfGrid;
238
+ }
239
+
240
+ // Check self-collision
241
+ if (isPositionOccupied(newPosition)) {
242
+ gameOver();
243
+ return;
244
+ }
245
+
246
+ // Check if food is eaten
247
+ if (
248
+ newPosition.x === food.position.x &&
249
+ newPosition.z === food.position.z
250
+ ) {
251
+ // Add new head
252
+ const geometry = new THREE.BoxGeometry(0.9, 0.9, 0.9);
253
+ const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
254
+ const segment = new THREE.Mesh(geometry, material);
255
+ segment.position.set(newPosition.x, 0.5, newPosition.z);
256
+ scene.add(segment);
257
+
258
+ // Add to beginning of snake array
259
+ snake.unshift({ mesh: segment, position: { ...newPosition } });
260
+
261
+ // Create new food
262
+ createFood();
263
+
264
+ // Update score
265
+ score += 10;
266
+ document.getElementById("score").textContent = "Score: " + score;
267
+ }
268
+ // Check if golden food is eaten
269
+ else if (
270
+ goldenFood &&
271
+ newPosition.x === goldenFood.position.x &&
272
+ newPosition.z === goldenFood.position.z
273
+ ) {
274
+ // Add new head
275
+ const geometry = new THREE.BoxGeometry(0.9, 0.9, 0.9);
276
+ const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
277
+ const segment = new THREE.Mesh(geometry, material);
278
+ segment.position.set(newPosition.x, 0.5, newPosition.z);
279
+ scene.add(segment);
280
+
281
+ // Add to beginning of snake array
282
+ snake.unshift({ mesh: segment, position: { ...newPosition } });
283
+
284
+ // Remove golden food
285
+ scene.remove(goldenFood.mesh);
286
+ goldenFood = null;
287
+
288
+ // Update score (higher bonus for golden food)
289
+ score += 25;
290
+ document.getElementById("score").textContent = "Score: " + score;
291
+
292
+ // Activate speed boost
293
+ bonusActive = true;
294
+ speed = baseSpeed * bonusSpeedMultiplier;
295
+ bonusEndTime = Date.now() + bonusDuration;
296
+
297
+ // Show bonus message
298
+ document.getElementById("bonusActive").style.display = "block";
299
+
300
+ // Set timer to end bonus
301
+ setTimeout(() => {
302
+ bonusActive = false;
303
+ speed = baseSpeed;
304
+ document.getElementById("bonusActive").style.display = "none";
305
+ }, bonusDuration);
306
+ } else {
307
+ // Move body segments
308
+ for (let i = snake.length - 1; i > 0; i--) {
309
+ snake[i].position = { ...snake[i - 1].position };
310
+ snake[i].mesh.position.set(
311
+ snake[i].position.x,
312
+ 0.5,
313
+ snake[i].position.z
314
+ );
315
+ }
316
+
317
+ // Move head
318
+ head.position = { ...newPosition };
319
+ head.mesh.position.set(newPosition.x, 0.5, newPosition.z);
320
+ }
321
+ }
322
+
323
+ // Handle keyboard controls
324
+ function handleKeyDown(event) {
325
+ if (isGameOver) {
326
+ // Restart game with space
327
+ if (event.code === "Space") {
328
+ restartGame();
329
+ }
330
+ return;
331
+ }
332
+
333
+ switch (event.code) {
334
+ case "ArrowUp":
335
+ case "KeyW":
336
+ if (direction.z !== 1) direction = { x: 0, y: 0, z: -1 };
337
+ break;
338
+ case "ArrowDown":
339
+ case "KeyS":
340
+ if (direction.z !== -1) direction = { x: 0, y: 0, z: 1 };
341
+ break;
342
+ case "ArrowLeft":
343
+ case "KeyA":
344
+ if (direction.x !== 1) direction = { x: -1, y: 0, z: 0 };
345
+ break;
346
+ case "ArrowRight":
347
+ case "KeyD":
348
+ if (direction.x !== -1) direction = { x: 1, y: 0, z: 0 };
349
+ break;
350
+ case "KeyR": // Toggle camera rotation with 'R' key
351
+ cameraRotationActive = !cameraRotationActive;
352
+ if (!cameraRotationActive) {
353
+ // Reset camera to fixed position when disabled
354
+ camera.position.set(0, cameraHeight, cameraRotationRadius);
355
+ camera.lookAt(0, 0, 0);
356
+ }
357
+ break;
358
+ }
359
+ }
360
+
361
+ // Handle game over
362
+ function gameOver() {
363
+ isGameOver = true;
364
+ document.getElementById("gameOver").style.display = "block";
365
+ }
366
+
367
+ // Restart the game
368
+ function restartGame() {
369
+ // Remove all snake segments
370
+ for (let segment of snake) {
371
+ scene.remove(segment.mesh);
372
+ }
373
+
374
+ // Remove golden food if it exists
375
+ if (goldenFood) {
376
+ scene.remove(goldenFood.mesh);
377
+ goldenFood = null;
378
+ }
379
+
380
+ // Reset game state
381
+ snake = [];
382
+ direction = { x: 1, y: 0, z: 0 };
383
+ score = 0;
384
+ isGameOver = false;
385
+ bonusActive = false;
386
+ speed = baseSpeed;
387
+
388
+ // Hide game over and bonus messages
389
+ document.getElementById("gameOver").style.display = "none";
390
+ document.getElementById("bonusActive").style.display = "none";
391
+ document.getElementById("score").textContent = "Score: 0";
392
+
393
+ // Create new snake and food
394
+ createSnake();
395
+ createFood();
396
+ }
397
+ // Handle window resize
398
+ function onWindowResize() {
399
+ camera.aspect = window.innerWidth / window.innerHeight;
400
+ camera.updateProjectionMatrix();
401
+ renderer.setSize(window.innerWidth, window.innerHeight);
402
+ }
403
+
404
+ // Animation loop
405
+ function animate(time) {
406
+ requestAnimationFrame(animate);
407
+
408
+ // Move snake at consistent speed
409
+ if (time - lastTime > 1000 / speed) {
410
+ moveSnake();
411
+ lastTime = time;
412
+ }
413
+
414
+ // Rotate camera around the scene
415
+ if (cameraRotationActive) {
416
+ cameraRotationAngle += cameraRotationSpeed * (bonusActive ? 2 : 1); // Rotate faster during bonus
417
+
418
+ // Update camera position in a circular path
419
+ camera.position.x =
420
+ Math.sin(cameraRotationAngle) * cameraRotationRadius;
421
+ camera.position.z =
422
+ Math.cos(cameraRotationAngle) * cameraRotationRadius;
423
+ camera.position.y = cameraHeight;
424
+
425
+ // Always look at the center
426
+ camera.lookAt(0, 0, 0);
427
+ }
428
+
429
+ renderer.render(scene, camera);
430
+ }
431
+
432
+ // Start the game
433
+ init();
434
+ </script>
435
+ </body>
436
  </html>