C50BARZ commited on
Commit
aba6fe4
Β·
verified Β·
1 Parent(s): 6bf40f6

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +526 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Podsquad Tetris
3
- emoji: πŸ‘
4
  colorFrom: pink
5
- colorTo: blue
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: podsquad-tetris
3
+ emoji: 🐳
4
  colorFrom: pink
5
+ colorTo: green
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,526 @@
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></title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ @keyframes colorChange {
10
+ 0% { background-color: #ff6b6b; }
11
+ 25% { background-color: #48dbfb; }
12
+ 50% { background-color: #1dd1a1; }
13
+ 75% { background-color: #feca57; }
14
+ 100% { background-color: #ff6b6b; }
15
+ }
16
+
17
+ body {
18
+ animation: colorChange 15s infinite;
19
+ transition: background-color 1s ease;
20
+ font-family: 'Courier New', monospace;
21
+ }
22
+
23
+ #game-board {
24
+ border: 4px solid rgba(255, 255, 255, 0.3);
25
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
26
+ }
27
+
28
+ .block {
29
+ border: 1px solid rgba(255, 255, 255, 0.2);
30
+ box-sizing: border-box;
31
+ }
32
+
33
+ .block.I { background-color: #00d2d3; }
34
+ .block.J { background-color: #5f27cd; }
35
+ .block.L { background-color: #ff9f43; }
36
+ .block.O { background-color: #feca57; }
37
+ .block.S { background-color: #1dd1a1; }
38
+ .block.T { background-color: #ff6b6b; }
39
+ .block.Z { background-color: #48dbfb; }
40
+
41
+ .glow {
42
+ animation: glow 0.5s ease-in-out infinite alternate;
43
+ }
44
+
45
+ @keyframes glow {
46
+ from { box-shadow: 0 0 5px rgba(255, 255, 255, 0.5); }
47
+ to { box-shadow: 0 0 20px rgba(255, 255, 255, 0.9); }
48
+ }
49
+
50
+ #start-btn {
51
+ transition: all 0.3s ease;
52
+ }
53
+
54
+ #start-btn:hover {
55
+ transform: scale(1.05);
56
+ box-shadow: 0 0 15px rgba(255, 255, 255, 0.7);
57
+ }
58
+ </style>
59
+ </head>
60
+ <body class="min-h-screen flex flex-col items-center justify-center text-white overflow-hidden">
61
+ <div class="text-center mb-6">
62
+ <img src="https://s3-us-west-2.amazonaws.com/anchor-generated-image-bank/staging/podcast_uploaded_nologo400/41101904/41101904-1733754532018-f9830aaa53f19.jpg"
63
+ alt="Tetris Logo"
64
+ class="mx-auto w-64 h-auto rounded-lg shadow-lg mb-4">
65
+ <h1 class="text-4xl font-bold mb-2 text-shadow">COLORFUL TETRIS</h1>
66
+ <div class="flex justify-center gap-8 mb-4">
67
+ <div>
68
+ <p class="text-xl">Score: <span id="score" class="font-bold">0</span></p>
69
+ </div>
70
+ <div>
71
+ <p class="text-xl">Level: <span id="level" class="font-bold">1</span></p>
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ <div class="relative">
77
+ <canvas id="game-board" width="300" height="600" class="bg-black bg-opacity-30"></canvas>
78
+ <div id="game-over" class="hidden absolute inset-0 bg-black bg-opacity-70 flex flex-col items-center justify-center">
79
+ <h2 class="text-3xl font-bold mb-4">GAME OVER</h2>
80
+ <p class="text-xl mb-6">Final Score: <span id="final-score" class="font-bold">0</span></p>
81
+ <button id="restart-btn" class="px-6 py-3 bg-white text-black font-bold rounded-lg hover:bg-gray-200 transition">
82
+ Play Again
83
+ </button>
84
+ </div>
85
+ <div id="start-screen" class="absolute inset-0 bg-black bg-opacity-70 flex flex-col items-center justify-center">
86
+ <button id="start-btn" class="px-8 py-4 bg-gradient-to-r from-purple-500 to-pink-500 text-white font-bold text-xl rounded-lg glow">
87
+ START GAME
88
+ </button>
89
+ <div class="mt-8 text-center">
90
+ <p class="mb-2">Controls:</p>
91
+ <p>← β†’ : Move</p>
92
+ <p>↑ : Rotate</p>
93
+ <p>↓ : Soft Drop</p>
94
+ <p>Space : Hard Drop</p>
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <div class="mt-6 flex gap-4">
100
+ <button id="sound-toggle" class="px-4 py-2 bg-white bg-opacity-20 rounded-lg hover:bg-opacity-30 transition">
101
+ πŸ”ˆ Sound On
102
+ </button>
103
+ </div>
104
+
105
+ <audio id="bg-music" loop>
106
+ <source src="https://music.mota.press/music/tetris/project/bgms/bgm.mp3" type="audio/mpeg">
107
+ </audio>
108
+ <audio id="move-sound">
109
+ <source src="https://electronicenergysource.com/entirelibofsounds/Salvaged%20Files/1001%20Sound%20Effects/Video%20Game%20Sounds/Arcade%20Beep%2001.wav" type="audio/wav">
110
+ </audio>
111
+ <audio id="rotate-sound">
112
+ <source src="https://electronicenergysource.com/entirelibofsounds/Salvaged%20Files/1001%20Sound%20Effects/Video%20Game%20Sounds/Arcade%20Beep%2002.wav" type="audio/wav">
113
+ </audio>
114
+ <audio id="drop-sound">
115
+ <source src="https://electronicenergysource.com/entirelibofsounds/Salvaged%20Files/1001%20Sound%20Effects/Video%20Game%20Sounds/Arcade%20Beep%2003.wav" type="audio/wav">
116
+ </audio>
117
+ <audio id="clear-sound">
118
+ <source src="https://electronicenergysource.com/entirelibofsounds/Salvaged%20Files/1001%20Sound%20Effects/Video%20Game%20Sounds/Arcade%20Beep%2004.wav" type="audio/wav">
119
+ </audio>
120
+
121
+ <script>
122
+ document.addEventListener('DOMContentLoaded', () => {
123
+ // Game elements
124
+ const canvas = document.getElementById('game-board');
125
+ const ctx = canvas.getContext('2d');
126
+ const startScreen = document.getElementById('start-screen');
127
+ const gameOverScreen = document.getElementById('game-over');
128
+ const startBtn = document.getElementById('start-btn');
129
+ const restartBtn = document.getElementById('restart-btn');
130
+ const scoreDisplay = document.getElementById('score');
131
+ const finalScoreDisplay = document.getElementById('final-score');
132
+ const levelDisplay = document.getElementById('level');
133
+ const soundToggle = document.getElementById('sound-toggle');
134
+
135
+ // Audio elements
136
+ const bgMusic = document.getElementById('bg-music');
137
+ const moveSound = document.getElementById('move-sound');
138
+ const rotateSound = document.getElementById('rotate-sound');
139
+ const dropSound = document.getElementById('drop-sound');
140
+ const clearSound = document.getElementById('clear-sound');
141
+
142
+ // Game settings
143
+ const COLS = 10;
144
+ const ROWS = 20;
145
+ const BLOCK_SIZE = 30;
146
+ const COLORS = [
147
+ null,
148
+ '#00d2d3', // I
149
+ '#5f27cd', // J
150
+ '#ff9f43', // L
151
+ '#feca57', // O
152
+ '#1dd1a1', // S
153
+ '#ff6b6b', // T
154
+ '#48dbfb' // Z
155
+ ];
156
+
157
+ // Game state
158
+ let board = createBoard();
159
+ let piece = null;
160
+ let nextPiece = null;
161
+ let score = 0;
162
+ let level = 1;
163
+ let lines = 0;
164
+ let gameOver = false;
165
+ let dropInterval = 1000;
166
+ let lastTime = 0;
167
+ let dropCounter = 0;
168
+ let soundOn = true;
169
+ let animationId = null;
170
+
171
+ // Tetromino shapes
172
+ const SHAPES = {
173
+ I: [
174
+ [0, 0, 0, 0],
175
+ [1, 1, 1, 1],
176
+ [0, 0, 0, 0],
177
+ [0, 0, 0, 0]
178
+ ],
179
+ J: [
180
+ [2, 0, 0],
181
+ [2, 2, 2],
182
+ [0, 0, 0]
183
+ ],
184
+ L: [
185
+ [0, 0, 3],
186
+ [3, 3, 3],
187
+ [0, 0, 0]
188
+ ],
189
+ O: [
190
+ [4, 4],
191
+ [4, 4]
192
+ ],
193
+ S: [
194
+ [0, 5, 5],
195
+ [5, 5, 0],
196
+ [0, 0, 0]
197
+ ],
198
+ T: [
199
+ [0, 6, 0],
200
+ [6, 6, 6],
201
+ [0, 0, 0]
202
+ ],
203
+ Z: [
204
+ [7, 7, 0],
205
+ [0, 7, 7],
206
+ [0, 0, 0]
207
+ ]
208
+ };
209
+
210
+ // Create game board
211
+ function createBoard() {
212
+ return Array.from(Array(ROWS), () => Array(COLS).fill(0));
213
+ }
214
+
215
+ // Create a random piece
216
+ function createPiece() {
217
+ const keys = Object.keys(SHAPES);
218
+ const randKey = keys[Math.floor(Math.random() * keys.length)];
219
+ const matrix = SHAPES[randKey];
220
+
221
+ // Position the piece in the middle of the board
222
+ const pos = {
223
+ x: Math.floor((COLS - matrix[0].length) / 2),
224
+ y: 0
225
+ };
226
+
227
+ return {
228
+ matrix,
229
+ pos,
230
+ type: randKey
231
+ };
232
+ }
233
+
234
+ // Draw the game board
235
+ function drawBoard() {
236
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
237
+
238
+ // Draw existing blocks
239
+ board.forEach((row, y) => {
240
+ row.forEach((value, x) => {
241
+ if (value) {
242
+ ctx.fillStyle = COLORS[value];
243
+ ctx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
244
+
245
+ // Add border to blocks
246
+ ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
247
+ ctx.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
248
+ }
249
+ });
250
+ });
251
+
252
+ // Draw current piece
253
+ if (piece) {
254
+ piece.matrix.forEach((row, y) => {
255
+ row.forEach((value, x) => {
256
+ if (value) {
257
+ ctx.fillStyle = COLORS[value];
258
+ ctx.fillRect(
259
+ (piece.pos.x + x) * BLOCK_SIZE,
260
+ (piece.pos.y + y) * BLOCK_SIZE,
261
+ BLOCK_SIZE, BLOCK_SIZE
262
+ );
263
+
264
+ // Add border to current piece
265
+ ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
266
+ ctx.strokeRect(
267
+ (piece.pos.x + x) * BLOCK_SIZE,
268
+ (piece.pos.y + y) * BLOCK_SIZE,
269
+ BLOCK_SIZE, BLOCK_SIZE
270
+ );
271
+ }
272
+ });
273
+ });
274
+ }
275
+ }
276
+
277
+ // Merge the piece into the board
278
+ function merge() {
279
+ piece.matrix.forEach((row, y) => {
280
+ row.forEach((value, x) => {
281
+ if (value) {
282
+ board[y + piece.pos.y][x + piece.pos.x] = value;
283
+ }
284
+ });
285
+ });
286
+ }
287
+
288
+ // Check for collisions
289
+ function collide() {
290
+ const [m, o] = [piece.matrix, piece.pos];
291
+ for (let y = 0; y < m.length; ++y) {
292
+ for (let x = 0; x < m[y].length; ++x) {
293
+ if (m[y][x] !== 0 &&
294
+ (board[y + o.y] === undefined ||
295
+ board[y + o.y][x + o.x] === undefined ||
296
+ board[y + o.y][x + o.x] !== 0)) {
297
+ return true;
298
+ }
299
+ }
300
+ }
301
+ return false;
302
+ }
303
+
304
+ // Rotate the piece
305
+ function rotate() {
306
+ if (soundOn) rotateSound.play();
307
+
308
+ const matrix = piece.matrix;
309
+ const N = matrix.length;
310
+
311
+ // Transpose the matrix
312
+ for (let y = 0; y < N; ++y) {
313
+ for (let x = 0; x < y; ++x) {
314
+ [matrix[x][y], matrix[y][x]] = [matrix[y][x], matrix[x][y]];
315
+ }
316
+ }
317
+
318
+ // Reverse each row
319
+ matrix.forEach(row => row.reverse());
320
+
321
+ // If rotation causes collision, revert it
322
+ if (collide()) {
323
+ // Reverse each row again
324
+ matrix.forEach(row => row.reverse());
325
+
326
+ // Transpose again to revert
327
+ for (let y = 0; y < N; ++y) {
328
+ for (let x = 0; x < y; ++x) {
329
+ [matrix[x][y], matrix[y][x]] = [matrix[y][x], matrix[x][y]];
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ // Move the piece
336
+ function movePiece(dir) {
337
+ if (soundOn) moveSound.play();
338
+ piece.pos.x += dir;
339
+ if (collide()) {
340
+ piece.pos.x -= dir;
341
+ }
342
+ }
343
+
344
+ // Drop the piece
345
+ function dropPiece() {
346
+ if (soundOn) dropSound.play();
347
+ piece.pos.y++;
348
+ if (collide()) {
349
+ piece.pos.y--;
350
+ merge();
351
+ clearLines();
352
+ resetPiece();
353
+
354
+ // Check for game over
355
+ if (collide()) {
356
+ gameOver = true;
357
+ }
358
+ }
359
+ dropCounter = 0;
360
+ }
361
+
362
+ // Hard drop (instant drop)
363
+ function hardDrop() {
364
+ if (soundOn) dropSound.play();
365
+ while (!collide()) {
366
+ piece.pos.y++;
367
+ }
368
+ piece.pos.y--;
369
+ merge();
370
+ clearLines();
371
+ resetPiece();
372
+
373
+ // Check for game over
374
+ if (collide()) {
375
+ gameOver = true;
376
+ }
377
+ dropCounter = 0;
378
+ }
379
+
380
+ // Reset the piece after it lands
381
+ function resetPiece() {
382
+ piece = nextPiece || createPiece();
383
+ nextPiece = createPiece();
384
+ }
385
+
386
+ // Clear completed lines
387
+ function clearLines() {
388
+ let linesCleared = 0;
389
+
390
+ outer: for (let y = board.length - 1; y >= 0; --y) {
391
+ for (let x = 0; x < board[y].length; ++x) {
392
+ if (board[y][x] === 0) {
393
+ continue outer;
394
+ }
395
+ }
396
+
397
+ // Remove the line
398
+ const row = board.splice(y, 1)[0].fill(0);
399
+ board.unshift(row);
400
+ ++y; // Check the same row again
401
+ linesCleared++;
402
+ }
403
+
404
+ if (linesCleared > 0) {
405
+ if (soundOn) clearSound.play();
406
+ updateScore(linesCleared);
407
+ }
408
+ }
409
+
410
+ // Update score based on lines cleared
411
+ function updateScore(linesCleared) {
412
+ lines += linesCleared;
413
+
414
+ // Scoring based on original Tetris rules
415
+ const points = [0, 40, 100, 300, 1200];
416
+ score += points[linesCleared] * level;
417
+
418
+ // Level up every 10 lines
419
+ level = Math.floor(lines / 10) + 1;
420
+
421
+ // Increase speed with level (capped at 100ms)
422
+ dropInterval = Math.max(100, 1000 - (level - 1) * 100);
423
+
424
+ // Update displays
425
+ scoreDisplay.textContent = score;
426
+ levelDisplay.textContent = level;
427
+ }
428
+
429
+ // Game loop
430
+ function gameLoop(time = 0) {
431
+ const deltaTime = time - lastTime;
432
+ lastTime = time;
433
+
434
+ dropCounter += deltaTime;
435
+ if (dropCounter > dropInterval) {
436
+ dropPiece();
437
+ }
438
+
439
+ drawBoard();
440
+
441
+ if (!gameOver) {
442
+ animationId = requestAnimationFrame(gameLoop);
443
+ } else {
444
+ endGame();
445
+ }
446
+ }
447
+
448
+ // Start the game
449
+ function startGame() {
450
+ if (soundOn) bgMusic.play();
451
+
452
+ board = createBoard();
453
+ piece = createPiece();
454
+ nextPiece = createPiece();
455
+ score = 0;
456
+ level = 1;
457
+ lines = 0;
458
+ gameOver = false;
459
+ dropInterval = 1000;
460
+
461
+ scoreDisplay.textContent = score;
462
+ levelDisplay.textContent = level;
463
+
464
+ startScreen.classList.add('hidden');
465
+ gameOverScreen.classList.add('hidden');
466
+
467
+ lastTime = 0;
468
+ dropCounter = 0;
469
+ gameLoop();
470
+ }
471
+
472
+ // End the game
473
+ function endGame() {
474
+ cancelAnimationFrame(animationId);
475
+ if (soundOn) bgMusic.pause();
476
+ finalScoreDisplay.textContent = score;
477
+ gameOverScreen.classList.remove('hidden');
478
+ }
479
+
480
+ // Event listeners
481
+ startBtn.addEventListener('click', startGame);
482
+ restartBtn.addEventListener('click', startGame);
483
+
484
+ soundToggle.addEventListener('click', () => {
485
+ soundOn = !soundOn;
486
+ soundToggle.textContent = soundOn ? 'πŸ”ˆ Sound On' : 'πŸ”‡ Sound Off';
487
+
488
+ if (soundOn && !gameOver && !startScreen.classList.contains('hidden')) {
489
+ bgMusic.play();
490
+ } else {
491
+ bgMusic.pause();
492
+ }
493
+ });
494
+
495
+ // Keyboard controls
496
+ document.addEventListener('keydown', e => {
497
+ if (gameOver || startScreen.classList.contains('hidden') === false) return;
498
+
499
+ switch (e.keyCode) {
500
+ case 37: // Left arrow
501
+ movePiece(-1);
502
+ break;
503
+ case 39: // Right arrow
504
+ movePiece(1);
505
+ break;
506
+ case 40: // Down arrow
507
+ dropPiece();
508
+ break;
509
+ case 38: // Up arrow
510
+ rotate();
511
+ break;
512
+ case 32: // Space
513
+ hardDrop();
514
+ break;
515
+ case 80: // P
516
+ // Pause functionality could be added here
517
+ break;
518
+ }
519
+ });
520
+
521
+ // Initial draw
522
+ drawBoard();
523
+ });
524
+ </script>
525
+ <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=C50BARZ/podsquad-tetris" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
526
+ </html>