akhaliq HF staff commited on
Commit
bc3b18c
·
verified ·
1 Parent(s): bd4669e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -91
app.py CHANGED
@@ -7,61 +7,56 @@ with demo:
7
  <html lang="en">
8
  <head>
9
  <meta charset="UTF-8">
10
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
11
- <title>Hugging Face Temple Run</title>
12
  <style>
13
- body { margin: 0; overflow: hidden; }
14
- canvas { display: block; }
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  #game-over-message {
16
  position: absolute;
17
  top: 50%;
18
  left: 50%;
19
  transform: translate(-50%, -50%);
20
- font-size: 48px;
21
  color: white;
22
  background: rgba(0, 0, 0, 0.7);
23
- padding: 20px;
 
24
  display: none;
25
  font-family: Arial, sans-serif;
 
 
26
  }
27
  #gpu-counter {
28
  position: absolute;
29
- top: 10px;
30
- left: 10px;
31
- font-size: 24px;
32
  color: white;
33
  background: rgba(0, 0, 0, 0.7);
34
- padding: 10px;
35
- font-family: Arial, sans-serif;
36
- }
37
- #controls {
38
- position: absolute;
39
- top: 0;
40
- right: 0;
41
- width: 200px;
42
- font-size: 16px;
43
- color: white;
44
- background: rgba(0, 0, 0, 0.8);
45
- padding: 15px;
46
  font-family: Arial, sans-serif;
47
- text-align: left;
48
- height: 100%;
49
- box-sizing: border-box;
50
  }
51
- #controls p { margin: 5px 0; }
52
- #controls strong { color: #ffcc00; }
53
  </style>
54
  </head>
55
  <body>
56
- <div id="game-over-message">Game Over!<br>Click to Restart</div>
57
- <div id="gpu-counter">GPUs Collected: 0</div>
58
- <div id="controls">
59
- <p><strong>Controls:</strong></p>
60
- <p>A / Left / Swipe Left: Move Left</p>
61
- <p>D / Right / Swipe Right: Move Right</p>
62
- <p>Space / Swipe Up: Jump</p>
63
- <p>Avoid obstacles, collect GPUs!</p>
64
- </div>
65
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
66
  <script>
67
  // Scene setup
@@ -71,7 +66,7 @@ with demo:
71
  renderer.setSize(window.innerWidth, window.innerHeight);
72
  document.body.appendChild(renderer.domElement);
73
 
74
- // Morning lighting
75
  const directionalLight = new THREE.DirectionalLight(0xffe0b2, 1);
76
  directionalLight.position.set(1, 1, 0.5).normalize();
77
  scene.add(directionalLight);
@@ -82,15 +77,15 @@ with demo:
82
  scene.background = new THREE.Color(0x87ceeb);
83
  scene.fog = new THREE.Fog(0x87ceeb, 10, 100);
84
 
85
- // Ground (endless path)
86
- const groundGeometry = new THREE.PlaneGeometry(20, 1000);
87
  const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x8c8c8c });
88
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
89
  ground.rotation.x = -Math.PI / 2;
90
- ground.position.z = -500; // Extend far into distance
91
  scene.add(ground);
92
 
93
- // Player (Hugging Face Emoji)
94
  const emojiCanvas = document.createElement('canvas');
95
  emojiCanvas.width = 256;
96
  emojiCanvas.height = 256;
@@ -100,16 +95,16 @@ with demo:
100
  emojiCtx.textBaseline = 'middle';
101
  emojiCtx.fillText('🤗', 128, 128);
102
  const emojiTexture = new THREE.CanvasTexture(emojiCanvas);
103
- const faceGeometry = new THREE.SphereGeometry(1, 32, 32);
104
  const faceMaterial = new THREE.MeshLambertMaterial({ map: emojiTexture });
105
  const face = new THREE.Mesh(faceGeometry, faceMaterial);
106
- face.position.set(0, 1, 0);
107
  scene.add(face);
108
- face.velocity = new THREE.Vector3(0, 0, -10); // Constant forward speed
109
- face.lane = 0; // -1 (left), 0 (center), 1 (right)
110
  face.jumping = false;
111
 
112
- // Collectibles (GPUs)
113
  const gpuCanvas = document.createElement('canvas');
114
  gpuCanvas.width = 128;
115
  gpuCanvas.height = 128;
@@ -128,7 +123,7 @@ with demo:
128
  const obstacleGeometry = new THREE.BoxGeometry(2, 2, 2);
129
  const obstacleMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 });
130
 
131
- // Audio setup
132
  const listener = new THREE.AudioListener();
133
  camera.add(listener);
134
  const collectSound = new THREE.PositionalAudio(listener);
@@ -140,54 +135,58 @@ with demo:
140
  collectSound.setVolume(0.5);
141
  });
142
 
143
- // Clock and game state
144
  const clock = new THREE.Clock();
145
  const gpuCounter = document.getElementById('gpu-counter');
146
  const gameOverMessage = document.getElementById('game-over-message');
147
  let gameOver = false;
148
 
149
- // Keyboard and touch controls
150
- const keys = {};
151
- window.addEventListener('keydown', (e) => { if (!gameOver) keys[e.key] = true; });
152
- window.addEventListener('keyup', (e) => { keys[e.key] = false; });
153
-
154
  let touchStartX = 0;
155
  let touchStartY = 0;
156
- window.addEventListener('touchstart', (e) => {
 
 
 
157
  touchStartX = e.touches[0].clientX;
158
  touchStartY = e.touches[0].clientY;
159
- });
160
- window.addEventListener('touchmove', (e) => {
 
 
161
  if (gameOver) return;
162
  const deltaX = e.touches[0].clientX - touchStartX;
163
  const deltaY = e.touches[0].clientY - touchStartY;
164
- if (Math.abs(deltaX) > 50) {
165
- if (deltaX > 0 && face.lane < 1) face.lane++;
166
- else if (deltaX < 0 && face.lane > -1) face.lane--;
 
167
  touchStartX = e.touches[0].clientX;
168
  }
169
- if (deltaY < -50 && !face.jumping) {
170
- face.jumping = true;
171
- face.velocity.y = 15;
 
 
172
  touchStartY = e.touches[0].clientY;
173
  }
174
- });
175
 
176
- // Spawn collectibles and obstacles
177
  function spawnItems() {
178
- if (Math.random() < 0.05) { // Spawn GPU
179
  const spriteMaterial = new THREE.SpriteMaterial({ map: gpuTexture });
180
  const sprite = new THREE.Sprite(spriteMaterial);
181
- sprite.scale.set(2, 2, 1);
182
  const lane = Math.floor(Math.random() * 3) - 1;
183
- sprite.position.set(lane * 4, 1, face.position.z - 50);
184
  scene.add(sprite);
185
  gpuSprites.push(sprite);
186
  }
187
- if (Math.random() < 0.03) { // Spawn obstacle
188
  const obstacle = new THREE.Mesh(obstacleGeometry, obstacleMaterial);
189
  const lane = Math.floor(Math.random() * 3) - 1;
190
- obstacle.position.set(lane * 4, 1, face.position.z - 50);
191
  scene.add(obstacle);
192
  obstacles.push(obstacle);
193
  }
@@ -201,36 +200,28 @@ with demo:
201
  if (!gameOver) {
202
  // Move player
203
  face.position.z += face.velocity.z * deltaTime;
204
- face.position.x = face.lane * 4; // Snap to lane
205
  if (face.jumping) {
206
  face.position.y += face.velocity.y * deltaTime;
207
  face.velocity.y -= 30 * deltaTime; // Gravity
208
- if (face.position.y <= 1) {
209
- face.position.y = 1;
210
  face.jumping = false;
211
  face.velocity.y = 0;
212
  }
213
  }
214
 
215
- // Handle controls
216
- if (keys['a'] || keys['ArrowLeft']) if (face.lane > -1) face.lane--;
217
- if (keys['d'] || keys['ArrowRight']) if (face.lane < 1) face.lane++;
218
- if ((keys[' '] || keys['ArrowUp']) && !face.jumping) {
219
- face.jumping = true;
220
- face.velocity.y = 15;
221
- }
222
-
223
  // Spawn items
224
  spawnItems();
225
 
226
  // Update collectibles
227
  gpuSprites.forEach((gpu, index) => {
228
- gpu.position.z += 10 * deltaTime; // Move toward player
229
- if (face.position.distanceTo(gpu.position) < 2) {
230
  scene.remove(gpu);
231
  gpuSprites.splice(index, 1);
232
  collectedGPUs++;
233
- gpuCounter.textContent = `GPUs Collected: ${collectedGPUs}`;
234
  collectSound.play();
235
  }
236
  if (gpu.position.z > face.position.z + 10) {
@@ -241,8 +232,8 @@ with demo:
241
 
242
  // Update obstacles
243
  obstacles.forEach((obstacle, index) => {
244
- obstacle.position.z += 10 * deltaTime;
245
- if (face.position.distanceTo(obstacle.position) < 2) {
246
  gameOver = true;
247
  gameOverMessage.style.display = 'block';
248
  face.velocity.z = 0;
@@ -254,7 +245,7 @@ with demo:
254
  });
255
 
256
  // Update camera
257
- camera.position.set(face.position.x, face.position.y + 5, face.position.z + 10);
258
  camera.lookAt(face.position);
259
  }
260
 
@@ -262,24 +253,32 @@ with demo:
262
  }
263
 
264
  // Restart game
265
- gameOverMessage.addEventListener('click', () => {
 
266
  if (gameOver) {
267
  gameOver = false;
268
  gameOverMessage.style.display = 'none';
269
- face.position.set(0, 1, 0);
270
- face.velocity.z = -10;
271
  collectedGPUs = 0;
272
- gpuCounter.textContent = `GPUs Collected: 0`;
273
  gpuSprites.forEach(gpu => scene.remove(gpu));
274
  obstacles.forEach(obstacle => scene.remove(obstacle));
275
  gpuSprites.length = 0;
276
  obstacles.length = 0;
277
  }
278
- });
 
 
 
 
 
 
 
279
 
280
  animate();
281
 
282
- // Handle window resize
283
  window.addEventListener('resize', () => {
284
  camera.aspect = window.innerWidth / window.innerHeight;
285
  camera.updateProjectionMatrix();
 
7
  <html lang="en">
8
  <head>
9
  <meta charset="UTF-8">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
11
+ <title>Hugging Face Temple Run Mobile</title>
12
  <style>
13
+ body {
14
+ margin: 0;
15
+ overflow: hidden;
16
+ background: #87ceeb;
17
+ display: flex;
18
+ justify-content: center;
19
+ align-items: center;
20
+ height: 100vh;
21
+ touch-action: none; /* Prevent default touch behaviors */
22
+ }
23
+ canvas {
24
+ display: block;
25
+ width: 100vw !important;
26
+ height: 100vh !important;
27
+ }
28
  #game-over-message {
29
  position: absolute;
30
  top: 50%;
31
  left: 50%;
32
  transform: translate(-50%, -50%);
33
+ font-size: 8vw; /* Responsive font size */
34
  color: white;
35
  background: rgba(0, 0, 0, 0.7);
36
+ padding: 5vw;
37
+ border-radius: 2vw;
38
  display: none;
39
  font-family: Arial, sans-serif;
40
+ text-align: center;
41
+ z-index: 10;
42
  }
43
  #gpu-counter {
44
  position: absolute;
45
+ top: 2vw;
46
+ left: 2vw;
47
+ font-size: 6vw;
48
  color: white;
49
  background: rgba(0, 0, 0, 0.7);
50
+ padding: 2vw;
51
+ border-radius: 1vw;
 
 
 
 
 
 
 
 
 
 
52
  font-family: Arial, sans-serif;
53
+ z-index: 10;
 
 
54
  }
 
 
55
  </style>
56
  </head>
57
  <body>
58
+ <div id="game-over-message">Game Over!<br>Tap to Restart</div>
59
+ <div id="gpu-counter">GPUs: 0</div>
 
 
 
 
 
 
 
60
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
61
  <script>
62
  // Scene setup
 
66
  renderer.setSize(window.innerWidth, window.innerHeight);
67
  document.body.appendChild(renderer.domElement);
68
 
69
+ // Lighting
70
  const directionalLight = new THREE.DirectionalLight(0xffe0b2, 1);
71
  directionalLight.position.set(1, 1, 0.5).normalize();
72
  scene.add(directionalLight);
 
77
  scene.background = new THREE.Color(0x87ceeb);
78
  scene.fog = new THREE.Fog(0x87ceeb, 10, 100);
79
 
80
+ // Ground
81
+ const groundGeometry = new THREE.PlaneGeometry(12, 1000); // Narrower for mobile
82
  const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x8c8c8c });
83
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
84
  ground.rotation.x = -Math.PI / 2;
85
+ ground.position.z = -500;
86
  scene.add(ground);
87
 
88
+ // Player
89
  const emojiCanvas = document.createElement('canvas');
90
  emojiCanvas.width = 256;
91
  emojiCanvas.height = 256;
 
95
  emojiCtx.textBaseline = 'middle';
96
  emojiCtx.fillText('🤗', 128, 128);
97
  const emojiTexture = new THREE.CanvasTexture(emojiCanvas);
98
+ const faceGeometry = new THREE.SphereGeometry(0.8, 32, 32);
99
  const faceMaterial = new THREE.MeshLambertMaterial({ map: emojiTexture });
100
  const face = new THREE.Mesh(faceGeometry, faceMaterial);
101
+ face.position.set(0, 0.8, 0);
102
  scene.add(face);
103
+ face.velocity = new THREE.Vector3(0, 0, -12); // Faster for mobile
104
+ face.lane = 0; // -1, 0, 1
105
  face.jumping = false;
106
 
107
+ // Collectibles
108
  const gpuCanvas = document.createElement('canvas');
109
  gpuCanvas.width = 128;
110
  gpuCanvas.height = 128;
 
123
  const obstacleGeometry = new THREE.BoxGeometry(2, 2, 2);
124
  const obstacleMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 });
125
 
126
+ // Audio
127
  const listener = new THREE.AudioListener();
128
  camera.add(listener);
129
  const collectSound = new THREE.PositionalAudio(listener);
 
135
  collectSound.setVolume(0.5);
136
  });
137
 
138
+ // Game state
139
  const clock = new THREE.Clock();
140
  const gpuCounter = document.getElementById('gpu-counter');
141
  const gameOverMessage = document.getElementById('game-over-message');
142
  let gameOver = false;
143
 
144
+ // Touch controls
 
 
 
 
145
  let touchStartX = 0;
146
  let touchStartY = 0;
147
+ let swipeThreshold = 30; // Pixels for swipe detection
148
+
149
+ document.addEventListener('touchstart', (e) => {
150
+ e.preventDefault();
151
  touchStartX = e.touches[0].clientX;
152
  touchStartY = e.touches[0].clientY;
153
+ }, { passive: false });
154
+
155
+ document.addEventListener('touchmove', (e) => {
156
+ e.preventDefault();
157
  if (gameOver) return;
158
  const deltaX = e.touches[0].clientX - touchStartX;
159
  const deltaY = e.touches[0].clientY - touchStartY;
160
+
161
+ if (Math.abs(deltaX) > swipeThreshold) {
162
+ if (deltaX > 0 && face.lane < 1) face.lane++; // Right
163
+ else if (deltaX < 0 && face.lane > -1) face.lane--; // Left
164
  touchStartX = e.touches[0].clientX;
165
  }
166
+ if (Math.abs(deltaY) > swipeThreshold) {
167
+ if (deltaY < 0 && !face.jumping) { // Up
168
+ face.jumping = true;
169
+ face.velocity.y = 15;
170
+ }
171
  touchStartY = e.touches[0].clientY;
172
  }
173
+ }, { passive: false });
174
 
175
+ // Spawn items
176
  function spawnItems() {
177
+ if (Math.random() < 0.05) { // GPU
178
  const spriteMaterial = new THREE.SpriteMaterial({ map: gpuTexture });
179
  const sprite = new THREE.Sprite(spriteMaterial);
180
+ sprite.scale.set(1.5, 1.5, 1);
181
  const lane = Math.floor(Math.random() * 3) - 1;
182
+ sprite.position.set(lane * 3, 0.75, face.position.z - 40);
183
  scene.add(sprite);
184
  gpuSprites.push(sprite);
185
  }
186
+ if (Math.random() < 0.03) { // Obstacle
187
  const obstacle = new THREE.Mesh(obstacleGeometry, obstacleMaterial);
188
  const lane = Math.floor(Math.random() * 3) - 1;
189
+ obstacle.position.set(lane * 3, 1, face.position.z - 40);
190
  scene.add(obstacle);
191
  obstacles.push(obstacle);
192
  }
 
200
  if (!gameOver) {
201
  // Move player
202
  face.position.z += face.velocity.z * deltaTime;
203
+ face.position.x = face.lane * 3; // Snap to lane
204
  if (face.jumping) {
205
  face.position.y += face.velocity.y * deltaTime;
206
  face.velocity.y -= 30 * deltaTime; // Gravity
207
+ if (face.position.y <= 0.8) {
208
+ face.position.y = 0.8;
209
  face.jumping = false;
210
  face.velocity.y = 0;
211
  }
212
  }
213
 
 
 
 
 
 
 
 
 
214
  // Spawn items
215
  spawnItems();
216
 
217
  // Update collectibles
218
  gpuSprites.forEach((gpu, index) => {
219
+ gpu.position.z += 12 * deltaTime;
220
+ if (face.position.distanceTo(gpu.position) < 1.5) {
221
  scene.remove(gpu);
222
  gpuSprites.splice(index, 1);
223
  collectedGPUs++;
224
+ gpuCounter.textContent = `GPUs: ${collectedGPUs}`;
225
  collectSound.play();
226
  }
227
  if (gpu.position.z > face.position.z + 10) {
 
232
 
233
  // Update obstacles
234
  obstacles.forEach((obstacle, index) => {
235
+ obstacle.position.z += 12 * deltaTime;
236
+ if (face.position.distanceTo(obstacle.position) < 1.5) {
237
  gameOver = true;
238
  gameOverMessage.style.display = 'block';
239
  face.velocity.z = 0;
 
245
  });
246
 
247
  // Update camera
248
+ camera.position.set(face.position.x, face.position.y + 4, face.position.z + 8);
249
  camera.lookAt(face.position);
250
  }
251
 
 
253
  }
254
 
255
  // Restart game
256
+ gameOverMessage.addEventListener('touchstart', (e) => {
257
+ e.preventDefault();
258
  if (gameOver) {
259
  gameOver = false;
260
  gameOverMessage.style.display = 'none';
261
+ face.position.set(0, 0.8, 0);
262
+ face.velocity.z = -12;
263
  collectedGPUs = 0;
264
+ gpuCounter.textContent = `GPUs: 0`;
265
  gpuSprites.forEach(gpu => scene.remove(gpu));
266
  obstacles.forEach(obstacle => scene.remove(obstacle));
267
  gpuSprites.length = 0;
268
  obstacles.length = 0;
269
  }
270
+ }, { passive: false });
271
+
272
+ // Fullscreen on mobile
273
+ document.body.addEventListener('touchstart', () => {
274
+ if (document.documentElement.requestFullscreen) {
275
+ document.documentElement.requestFullscreen();
276
+ }
277
+ }, { once: true });
278
 
279
  animate();
280
 
281
+ // Handle resize/orientation change
282
  window.addEventListener('resize', () => {
283
  camera.aspect = window.innerWidth / window.innerHeight;
284
  camera.updateProjectionMatrix();