WebashalarForML commited on
Commit
907d72d
·
verified ·
1 Parent(s): c0aa0bc

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +651 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: 3d 2 Game
3
- emoji: 😻
4
  colorFrom: blue
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: 3d-2-game
3
+ emoji: 🐳
4
  colorFrom: blue
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,651 @@
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>Pixel Quest 3D: Find Your Friend</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ overflow: hidden;
13
+ font-family: 'Press Start 2P', cursive;
14
+ image-rendering: pixelated;
15
+ }
16
+
17
+ canvas {
18
+ display: block;
19
+ image-rendering: pixelated;
20
+ }
21
+
22
+ @font-face {
23
+ font-family: 'Press Start 2P';
24
+ src: url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
25
+ }
26
+
27
+ .pixel-border {
28
+ border: 4px solid #fff;
29
+ box-shadow: 0 0 0 4px #000, inset 0 0 0 4px #000;
30
+ }
31
+
32
+ .quiz-option {
33
+ transition: all 0.1s;
34
+ border: 3px solid #fff;
35
+ box-shadow: 0 0 0 3px #000;
36
+ }
37
+
38
+ .quiz-option:hover {
39
+ background-color: #4a5568;
40
+ transform: translateY(-2px);
41
+ }
42
+
43
+ .quiz-option.correct {
44
+ background-color: #48bb78;
45
+ }
46
+
47
+ .quiz-option.wrong {
48
+ background-color: #f56565;
49
+ }
50
+
51
+ .pixel-text {
52
+ text-shadow: 3px 3px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
53
+ }
54
+
55
+ .health-bar {
56
+ height: 10px;
57
+ background-color: #4a5568;
58
+ border: 2px solid #000;
59
+ }
60
+
61
+ .health-fill {
62
+ height: 100%;
63
+ background-color: #48bb78;
64
+ transition: width 0.3s;
65
+ }
66
+ </style>
67
+ </head>
68
+ <body class="bg-gray-900">
69
+ <div id="game-container" class="relative w-full h-screen">
70
+ <!-- Start Screen -->
71
+ <div id="start-screen" class="absolute inset-0 flex flex-col items-center justify-center bg-gray-900 z-10">
72
+ <h1 class="text-4xl md:text-6xl text-green-400 mb-8 pixel-text">PIXEL QUEST 3D</h1>
73
+ <p class="text-xl text-white mb-12 pixel-text">Find Your Lost Friend!</p>
74
+ <div class="flex mb-8">
75
+ <div class="w-16 h-16 bg-red-500 pixel-border mr-4"></div>
76
+ <div class="w-16 h-16 bg-blue-500 pixel-border"></div>
77
+ </div>
78
+ <button id="start-btn" class="px-8 py-4 bg-green-500 hover:bg-green-600 text-white font-bold pixel-border transition-all transform hover:scale-105">
79
+ START ADVENTURE
80
+ </button>
81
+ <div class="mt-8 text-white text-sm pixel-text">
82
+ Controls: Arrow Keys to move, Space to jump
83
+ </div>
84
+ </div>
85
+
86
+ <!-- Quiz Modal -->
87
+ <div id="quiz-modal" class="hidden absolute inset-0 flex items-center justify-center z-20 bg-black bg-opacity-70">
88
+ <div class="bg-gray-800 p-6 rounded-lg w-11/12 max-w-md pixel-border">
89
+ <h2 id="quiz-question" class="text-xl text-white mb-6 pixel-text"></h2>
90
+ <div id="quiz-options" class="space-y-3"></div>
91
+ <div id="quiz-feedback" class="mt-4 text-yellow-300 hidden pixel-text"></div>
92
+ </div>
93
+ </div>
94
+
95
+ <!-- End Screen -->
96
+ <div id="end-screen" class="hidden absolute inset-0 flex flex-col items-center justify-center bg-gray-900 z-10">
97
+ <h1 id="end-title" class="text-4xl md:text-6xl text-green-400 mb-8 pixel-text">FRIEND FOUND!</h1>
98
+ <div class="flex items-center mb-8">
99
+ <div class="w-32 h-32 bg-red-500 pixel-border mr-4"></div>
100
+ <div class="w-32 h-32 bg-blue-500 pixel-border"></div>
101
+ </div>
102
+ <p id="final-score" class="text-xl text-white mb-12 pixel-text"></p>
103
+ <button id="restart-btn" class="px-8 py-4 bg-green-500 hover:bg-green-600 text-white font-bold pixel-border transition-all transform hover:scale-105">
104
+ PLAY AGAIN
105
+ </button>
106
+ </div>
107
+
108
+ <!-- Game Over Screen -->
109
+ <div id="game-over-screen" class="hidden absolute inset-0 flex flex-col items-center justify-center bg-gray-900 z-10">
110
+ <h1 class="text-4xl md:text-6xl text-red-500 mb-8 pixel-text">GAME OVER</h1>
111
+ <p id="game-over-score" class="text-xl text-white mb-12 pixel-text"></p>
112
+ <button id="game-over-restart-btn" class="px-8 py-4 bg-green-500 hover:bg-green-600 text-white font-bold pixel-border transition-all transform hover:scale-105">
113
+ TRY AGAIN
114
+ </button>
115
+ </div>
116
+
117
+ <!-- UI Elements -->
118
+ <div id="ui-container" class="absolute top-4 left-4 z-10 hidden">
119
+ <div class="bg-gray-800 bg-opacity-70 p-3 rounded pixel-border">
120
+ <p class="text-white pixel-text">Score: <span id="score-display">0</span></p>
121
+ <p class="text-white pixel-text">Quizzes: <span id="quiz-count">0</span>/4</p>
122
+ <div class="mt-2">
123
+ <p class="text-white pixel-text mb-1">Health:</p>
124
+ <div class="health-bar">
125
+ <div id="health-fill" class="health-fill" style="width: 100%"></div>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ <script>
133
+ // Game variables
134
+ let scene, camera, renderer;
135
+ let player, platforms = [], checkpoints = [], coins = [], obstacles = [];
136
+ let playerVelocity = { x: 0, y: 0, z: 0 };
137
+ let playerSpeed = 0.2;
138
+ let jumpForce = 0.4;
139
+ let gravity = 0.02;
140
+ let isJumping = false;
141
+ let gamePaused = false;
142
+ let score = 0;
143
+ let quizzesCompleted = 0;
144
+ let currentCheckpoint = null;
145
+ let friendFound = false;
146
+ let keys = {};
147
+ let worldWidth = 100;
148
+ let worldDepth = 20;
149
+ let friend;
150
+ let playerHealth = 100;
151
+ let lastObstacleHitTime = 0;
152
+ let obstacleHitCooldown = 1000; // 1 second cooldown
153
+
154
+ // Quiz questions
155
+ const quizQuestions = [
156
+ {
157
+ question: "What is your friend's favorite color?",
158
+ options: ["Blue", "Green", "Red", "Yellow"],
159
+ correct: 0
160
+ },
161
+ {
162
+ question: "Where did you first meet your friend?",
163
+ options: ["At school", "At the park", "At a party", "Online"],
164
+ correct: 1
165
+ },
166
+ {
167
+ question: "What's your friend's favorite food?",
168
+ options: ["Pizza", "Sushi", "Burgers", "Tacos"],
169
+ correct: 2
170
+ },
171
+ {
172
+ question: "What was your last adventure together?",
173
+ options: ["Hiking", "Movie marathon", "Road trip", "Camping"],
174
+ correct: 3
175
+ }
176
+ ];
177
+
178
+ // Initialize game
179
+ function init() {
180
+ // Scene setup
181
+ scene = new THREE.Scene();
182
+ scene.background = new THREE.Color(0x87CEEB); // Sky blue
183
+
184
+ // Camera (perspective for better 3D feel)
185
+ const aspect = window.innerWidth / window.innerHeight;
186
+ camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
187
+ camera.position.set(0, 5, 15);
188
+ camera.lookAt(0, 0, 0);
189
+
190
+ // Renderer
191
+ renderer = new THREE.WebGLRenderer({ antialias: false });
192
+ renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);
193
+ renderer.setSize(window.innerWidth, window.innerHeight);
194
+ renderer.shadowMap.enabled = true;
195
+ document.getElementById('game-container').appendChild(renderer.domElement);
196
+
197
+ // Lighting
198
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
199
+ scene.add(ambientLight);
200
+
201
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
202
+ directionalLight.position.set(10, 20, 10);
203
+ directionalLight.castShadow = true;
204
+ directionalLight.shadow.mapSize.width = 1024;
205
+ directionalLight.shadow.mapSize.height = 1024;
206
+ scene.add(directionalLight);
207
+
208
+ // Create world
209
+ createWorld();
210
+
211
+ // Create player
212
+ createPlayer();
213
+
214
+ // Create checkpoints
215
+ createCheckpoints();
216
+
217
+ // Create obstacles
218
+ createObstacles();
219
+
220
+ // Create friend
221
+ createFriend();
222
+
223
+ // Event listeners
224
+ window.addEventListener('resize', onWindowResize);
225
+ document.addEventListener('keydown', onKeyDown);
226
+ document.addEventListener('keyup', onKeyUp);
227
+
228
+ // Start button
229
+ document.getElementById('start-btn').addEventListener('click', startGame);
230
+ document.getElementById('restart-btn').addEventListener('click', restartGame);
231
+ document.getElementById('game-over-restart-btn').addEventListener('click', restartGame);
232
+ }
233
+
234
+ function createWorld() {
235
+ // Ground
236
+ const groundGeometry = new THREE.BoxGeometry(worldWidth, 1, worldDepth);
237
+ const groundMaterial = new THREE.MeshStandardMaterial({
238
+ color: 0x2e8b57,
239
+ roughness: 1.0
240
+ });
241
+ const ground = new THREE.Mesh(groundGeometry, groundMaterial);
242
+ ground.position.y = -0.5;
243
+ ground.receiveShadow = true;
244
+ scene.add(ground);
245
+
246
+ // Platforms
247
+ const platformPositions = [
248
+ { x: 10, y: 2, z: 0, width: 8, depth: 8 },
249
+ { x: 25, y: 3, z: 5, width: 6, depth: 6 },
250
+ { x: 40, y: 4, z: -3, width: 10, depth: 10 },
251
+ { x: 60, y: 2, z: 2, width: 12, depth: 8 },
252
+ { x: 80, y: 5, z: 0, width: 8, depth: 8 }
253
+ ];
254
+
255
+ platformPositions.forEach(pos => {
256
+ const platformGeometry = new THREE.BoxGeometry(pos.width, 1, pos.depth);
257
+ const platformMaterial = new THREE.MeshStandardMaterial({
258
+ color: 0x8b4513,
259
+ roughness: 1.0
260
+ });
261
+ const platform = new THREE.Mesh(platformGeometry, platformMaterial);
262
+ platform.position.set(pos.x, pos.y, pos.z);
263
+ platform.receiveShadow = true;
264
+ scene.add(platform);
265
+ platforms.push(platform);
266
+ });
267
+
268
+ // Coins
269
+ for (let i = 0; i < 20; i++) {
270
+ const coinGeometry = new THREE.CylinderGeometry(0.5, 0.5, 0.2, 16);
271
+ const coinMaterial = new THREE.MeshStandardMaterial({ color: 0xffd700 });
272
+ const coin = new THREE.Mesh(coinGeometry, coinMaterial);
273
+
274
+ // Position coins randomly above platforms or ground
275
+ let x, y, z;
276
+ if (Math.random() > 0.5) {
277
+ // On platforms
278
+ const platform = platforms[Math.floor(Math.random() * platforms.length)];
279
+ x = platform.position.x + (Math.random() - 0.5) * (platform.geometry.parameters.width - 2);
280
+ y = platform.position.y + 1;
281
+ z = platform.position.z + (Math.random() - 0.5) * (platform.geometry.parameters.depth - 2);
282
+ } else {
283
+ // On ground
284
+ x = Math.random() * worldWidth;
285
+ y = 0.5;
286
+ z = (Math.random() - 0.5) * (worldDepth - 4);
287
+ }
288
+
289
+ coin.position.set(x, y, z);
290
+ coin.rotation.x = Math.PI / 2;
291
+ coin.userData.isCoin = true;
292
+ scene.add(coin);
293
+ coins.push(coin);
294
+ }
295
+ }
296
+
297
+ function createPlayer() {
298
+ // Simple pixel-style character
299
+ const playerGeometry = new THREE.BoxGeometry(1, 2, 1);
300
+ const playerMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
301
+ player = new THREE.Mesh(playerGeometry, playerMaterial);
302
+ player.position.set(0, 1, 0);
303
+ player.castShadow = true;
304
+ scene.add(player);
305
+ }
306
+
307
+ function createCheckpoints() {
308
+ // Create 4 checkpoints along the path
309
+ const checkpointPositions = [
310
+ { x: 15, y: 0, z: 0 },
311
+ { x: 30, y: 0, z: 0 },
312
+ { x: 50, y: 0, z: 0 },
313
+ { x: 70, y: 0, z: 0 }
314
+ ];
315
+
316
+ checkpointPositions.forEach((pos, index) => {
317
+ const checkpointGeometry = new THREE.BoxGeometry(2, 2, 2);
318
+ const checkpointMaterial = new THREE.MeshStandardMaterial({
319
+ color: 0xffff00,
320
+ transparent: true,
321
+ opacity: 0.7
322
+ });
323
+ const checkpoint = new THREE.Mesh(checkpointGeometry, checkpointMaterial);
324
+ checkpoint.position.set(pos.x, pos.y + 1, pos.z);
325
+ checkpoint.userData.isCheckpoint = true;
326
+ checkpoint.userData.quizIndex = index;
327
+ scene.add(checkpoint);
328
+ checkpoints.push(checkpoint);
329
+ });
330
+ }
331
+
332
+ function createObstacles() {
333
+ // Create destroyable obstacles
334
+ const obstaclePositions = [
335
+ { x: 5, y: 1, z: 3, width: 1, height: 2, depth: 1 },
336
+ { x: 20, y: 1, z: -2, width: 1, height: 2, depth: 1 },
337
+ { x: 35, y: 1, z: 4, width: 1, height: 2, depth: 1 },
338
+ { x: 45, y: 1, z: -3, width: 1, height: 2, depth: 1 },
339
+ { x: 65, y: 1, z: 2, width: 1, height: 2, depth: 1 }
340
+ ];
341
+
342
+ obstaclePositions.forEach(pos => {
343
+ const obstacleGeometry = new THREE.BoxGeometry(pos.width, pos.height, pos.depth);
344
+ const obstacleMaterial = new THREE.MeshStandardMaterial({
345
+ color: 0x8b0000,
346
+ roughness: 1.0
347
+ });
348
+ const obstacle = new THREE.Mesh(obstacleGeometry, obstacleMaterial);
349
+ obstacle.position.set(pos.x, pos.y + pos.height/2, pos.z);
350
+ obstacle.castShadow = true;
351
+ obstacle.receiveShadow = true;
352
+ obstacle.userData.isObstacle = true;
353
+ obstacle.userData.health = 30; // Obstacle health
354
+ scene.add(obstacle);
355
+ obstacles.push(obstacle);
356
+ });
357
+ }
358
+
359
+ function createFriend() {
360
+ // Create the friend character at the end
361
+ const friendGeometry = new THREE.BoxGeometry(1, 2, 1);
362
+ const friendMaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff });
363
+ friend = new THREE.Mesh(friendGeometry, friendMaterial);
364
+ friend.position.set(worldWidth - 5, 1, 0);
365
+ friend.castShadow = true;
366
+ friend.userData.isFriend = true;
367
+ scene.add(friend);
368
+ }
369
+
370
+ function startGame() {
371
+ document.getElementById('start-screen').classList.add('hidden');
372
+ document.getElementById('ui-container').classList.remove('hidden');
373
+ animate();
374
+ }
375
+
376
+ function restartGame() {
377
+ // Reset game state
378
+ score = 0;
379
+ quizzesCompleted = 0;
380
+ friendFound = false;
381
+ gamePaused = false;
382
+ playerHealth = 100;
383
+
384
+ // Reset player position
385
+ player.position.set(0, 1, 0);
386
+ playerVelocity = { x: 0, y: 0, z: 0 };
387
+
388
+ // Reset UI
389
+ document.getElementById('score-display').textContent = '0';
390
+ document.getElementById('quiz-count').textContent = '0/4';
391
+ document.getElementById('health-fill').style.width = '100%';
392
+ document.getElementById('end-screen').classList.add('hidden');
393
+ document.getElementById('game-over-screen').classList.add('hidden');
394
+ document.getElementById('ui-container').classList.remove('hidden');
395
+
396
+ // Clear and recreate all game objects
397
+ clearScene();
398
+ createWorld();
399
+ createPlayer();
400
+ createCheckpoints();
401
+ createObstacles();
402
+ createFriend();
403
+
404
+ // Restart animation
405
+ animate();
406
+ }
407
+
408
+ function clearScene() {
409
+ // Remove all objects from scene except lights and camera
410
+ while(scene.children.length > 0) {
411
+ const obj = scene.children[0];
412
+ if (!(obj instanceof THREE.Light) && !(obj instanceof THREE.Camera)) {
413
+ scene.remove(obj);
414
+ }
415
+ }
416
+
417
+ // Clear arrays
418
+ platforms = [];
419
+ checkpoints = [];
420
+ coins = [];
421
+ obstacles = [];
422
+ }
423
+
424
+ function showQuiz(quizIndex) {
425
+ gamePaused = true;
426
+ currentCheckpoint = quizIndex;
427
+
428
+ const quiz = quizQuestions[quizIndex];
429
+ document.getElementById('quiz-question').textContent = quiz.question;
430
+
431
+ const optionsContainer = document.getElementById('quiz-options');
432
+ optionsContainer.innerHTML = '';
433
+
434
+ quiz.options.forEach((option, i) => {
435
+ const optionBtn = document.createElement('button');
436
+ optionBtn.className = 'w-full p-3 bg-gray-700 text-white quiz-option pixel-text';
437
+ optionBtn.textContent = option;
438
+ optionBtn.addEventListener('click', () => checkAnswer(i));
439
+ optionsContainer.appendChild(optionBtn);
440
+ });
441
+
442
+ document.getElementById('quiz-feedback').classList.add('hidden');
443
+ document.getElementById('quiz-modal').classList.remove('hidden');
444
+ }
445
+
446
+ function checkAnswer(answerIndex) {
447
+ const quiz = quizQuestions[currentCheckpoint];
448
+ const options = document.querySelectorAll('.quiz-option');
449
+
450
+ if (answerIndex === quiz.correct) {
451
+ // Correct answer
452
+ options[answerIndex].classList.add('correct');
453
+ document.getElementById('quiz-feedback').textContent = 'Correct!';
454
+ document.getElementById('quiz-feedback').classList.remove('hidden');
455
+
456
+ setTimeout(() => {
457
+ quizzesCompleted++;
458
+ document.getElementById('quiz-count').textContent = `${quizzesCompleted}/4`;
459
+ document.getElementById('quiz-modal').classList.add('hidden');
460
+ gamePaused = false;
461
+
462
+ // Remove the checkpoint
463
+ const checkpoint = checkpoints[currentCheckpoint];
464
+ scene.remove(checkpoint);
465
+ checkpoints[currentCheckpoint] = null;
466
+
467
+ // Add score
468
+ score += 100;
469
+ document.getElementById('score-display').textContent = score;
470
+ }, 1000);
471
+ } else {
472
+ // Wrong answer
473
+ options[answerIndex].classList.add('wrong');
474
+ options[quiz.correct].classList.add('correct');
475
+ document.getElementById('quiz-feedback').textContent = 'Try again!';
476
+ document.getElementById('quiz-feedback').classList.remove('hidden');
477
+ }
478
+ }
479
+
480
+ function onWindowResize() {
481
+ const aspect = window.innerWidth / window.innerHeight;
482
+ camera.aspect = aspect;
483
+ camera.updateProjectionMatrix();
484
+ renderer.setSize(window.innerWidth, window.innerHeight);
485
+ }
486
+
487
+ function onKeyDown(event) {
488
+ keys[event.code] = true;
489
+
490
+ // Jump
491
+ if (event.code === 'Space' && !isJumping && !gamePaused) {
492
+ playerVelocity.y = jumpForce;
493
+ isJumping = true;
494
+ }
495
+
496
+ // Attack (destroy obstacles)
497
+ if (event.code === 'KeyF' && !gamePaused) {
498
+ attackObstacle();
499
+ }
500
+ }
501
+
502
+ function onKeyUp(event) {
503
+ keys[event.code] = false;
504
+ }
505
+
506
+ function attackObstacle() {
507
+ const playerBox = new THREE.Box3().setFromObject(player);
508
+
509
+ obstacles.forEach((obstacle, index) => {
510
+ if (obstacle && new THREE.Box3().setFromObject(player).intersectsBox(new THREE.Box3().setFromObject(obstacle))) {
511
+ // Reduce obstacle health
512
+ obstacle.userData.health -= 10;
513
+
514
+ // If obstacle is destroyed
515
+ if (obstacle.userData.health <= 0) {
516
+ scene.remove(obstacle);
517
+ obstacles[index] = null;
518
+ score += 50;
519
+ document.getElementById('score-display').textContent = score;
520
+ }
521
+ }
522
+ });
523
+ }
524
+
525
+ function checkCollisions() {
526
+ // Check platform collisions
527
+ let onGround = false;
528
+ const playerBox = new THREE.Box3().setFromObject(player);
529
+
530
+ platforms.forEach(platform => {
531
+ const platformBox = new THREE.Box3().setFromObject(platform);
532
+ if (playerBox.intersectsBox(platformBox)) {
533
+ // Check if player is on top of platform
534
+ if (player.position.y > platform.position.y + 0.9) {
535
+ player.position.y = platform.position.y + 1 + player.geometry.parameters.height / 2;
536
+ playerVelocity.y = 0;
537
+ isJumping = false;
538
+ onGround = true;
539
+ }
540
+ }
541
+ });
542
+
543
+ // Ground collision
544
+ if (player.position.y <= 0) {
545
+ player.position.y = 0;
546
+ playerVelocity.y = 0;
547
+ isJumping = false;
548
+ onGround = true;
549
+ }
550
+
551
+ // Check coin collisions
552
+ coins.forEach((coin, index) => {
553
+ if (coin && new THREE.Box3().setFromObject(player).intersectsBox(new THREE.Box3().setFromObject(coin))) {
554
+ scene.remove(coin);
555
+ coins[index] = null;
556
+ score += 10;
557
+ document.getElementById('score-display').textContent = score;
558
+ }
559
+ });
560
+
561
+ // Check checkpoint collisions
562
+ checkpoints.forEach((checkpoint, index) => {
563
+ if (checkpoint && new THREE.Box3().setFromObject(player).intersectsBox(new THREE.Box3().setFromObject(checkpoint))) {
564
+ showQuiz(index);
565
+ }
566
+ });
567
+
568
+ // Check obstacle collisions (damage player)
569
+ const currentTime = Date.now();
570
+ obstacles.forEach(obstacle => {
571
+ if (obstacle && new THREE.Box3().setFromObject(player).intersectsBox(new THREE.Box3().setFromObject(obstacle))) {
572
+ if (currentTime - lastObstacleHitTime > obstacleHitCooldown) {
573
+ playerHealth -= 10;
574
+ lastObstacleHitTime = currentTime;
575
+ document.getElementById('health-fill').style.width = `${playerHealth}%`;
576
+
577
+ // Flash player red when hit
578
+ player.material.color.setHex(0xff0000);
579
+ setTimeout(() => {
580
+ player.material.color.setHex(0xff0000);
581
+ }, 200);
582
+
583
+ // Check if player died
584
+ if (playerHealth <= 0) {
585
+ gameOver();
586
+ }
587
+ }
588
+ }
589
+ });
590
+
591
+ // Check friend collision
592
+ if (!friendFound && new THREE.Box3().setFromObject(player).intersectsBox(new THREE.Box3().setFromObject(friend)) && quizzesCompleted === 4) {
593
+ friendFound = true;
594
+ gamePaused = true;
595
+
596
+ // Show end screen
597
+ document.getElementById('final-score').textContent = `Final Score: ${score}`;
598
+ document.getElementById('end-screen').classList.remove('hidden');
599
+ document.getElementById('ui-container').classList.add('hidden');
600
+ }
601
+
602
+ return onGround;
603
+ }
604
+
605
+ function gameOver() {
606
+ gamePaused = true;
607
+ document.getElementById('game-over-score').textContent = `Score: ${score}`;
608
+ document.getElementById('game-over-screen').classList.remove('hidden');
609
+ document.getElementById('ui-container').classList.add('hidden');
610
+ }
611
+
612
+ function animate() {
613
+ if (gamePaused) return;
614
+
615
+ requestAnimationFrame(animate);
616
+
617
+ // Player movement
618
+ if (keys['KeyA'] || keys['ArrowLeft']) {
619
+ playerVelocity.x = -playerSpeed;
620
+ player.rotation.y = Math.PI;
621
+ } else if (keys['KeyD'] || keys['ArrowRight']) {
622
+ playerVelocity.x = playerSpeed;
623
+ player.rotation.y = 0;
624
+ } else {
625
+ playerVelocity.x = 0;
626
+ }
627
+
628
+ // Apply gravity
629
+ playerVelocity.y -= gravity;
630
+
631
+ // Update player position
632
+ player.position.x += playerVelocity.x;
633
+ player.position.y += playerVelocity.y;
634
+
635
+ // Check collisions
636
+ checkCollisions();
637
+
638
+ // Update camera to follow player with better angle
639
+ camera.position.x = player.position.x;
640
+ camera.position.y = player.position.y + 5;
641
+ camera.position.z = player.position.z + 15;
642
+ camera.lookAt(player.position.x, player.position.y, player.position.z);
643
+
644
+ renderer.render(scene, camera);
645
+ }
646
+
647
+ // Start the game
648
+ init();
649
+ </script>
650
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=WebashalarForML/3d-2-game" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
651
+ </html>