manmohanai commited on
Commit
52ed030
·
verified ·
1 Parent(s): ea0ddaf

create 3d tetris game which we can rotate. The blocks should have emoji like simley etc. - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +517 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
  title: 3dimojitetris
3
- emoji: 🌖
4
- colorFrom: gray
5
- colorTo: red
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: 3dimojitetris
3
+ emoji: 🐳
4
+ colorFrom: green
5
+ colorTo: purple
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,517 @@
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 Emoji Tetris</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ body {
10
+ perspective: 1000px;
11
+ overflow: hidden;
12
+ background: linear-gradient(135deg, #1a1a2e, #16213e);
13
+ }
14
+
15
+ .game-container {
16
+ transform-style: preserve-3d;
17
+ transition: transform 0.5s ease;
18
+ }
19
+
20
+ .block {
21
+ transform-style: preserve-3d;
22
+ transition: all 0.2s ease;
23
+ position: relative;
24
+ }
25
+
26
+ .block-face {
27
+ position: absolute;
28
+ width: 100%;
29
+ height: 100%;
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ font-size: 1.5rem;
34
+ backface-visibility: hidden;
35
+ border: 1px solid rgba(255, 255, 255, 0.1);
36
+ box-sizing: border-box;
37
+ }
38
+
39
+ .front { transform: translateZ(25px); }
40
+ .back { transform: rotateY(180deg) translateZ(25px); }
41
+ .right { transform: rotateY(90deg) translateZ(25px); }
42
+ .left { transform: rotateY(-90deg) translateZ(25px); }
43
+ .top { transform: rotateX(90deg) translateZ(25px); }
44
+ .bottom { transform: rotateX(-90deg) translateZ(25px); }
45
+
46
+ @keyframes fall {
47
+ from { transform: translateY(-100px); }
48
+ to { transform: translateY(0); }
49
+ }
50
+
51
+ .falling {
52
+ animation: fall 0.3s ease-out;
53
+ }
54
+ </style>
55
+ </head>
56
+ <body class="min-h-screen flex flex-col items-center justify-center text-white font-mono">
57
+ <h1 class="text-4xl font-bold mb-4 text-center bg-clip-text text-transparent bg-gradient-to-r from-pink-500 to-violet-500">
58
+ 3D Emoji Tetris
59
+ </h1>
60
+
61
+ <div class="mb-4 flex gap-4">
62
+ <div class="text-center">
63
+ <p class="text-xl">Score</p>
64
+ <p id="score" class="text-3xl font-bold">0</p>
65
+ </div>
66
+ <div class="text-center">
67
+ <p class="text-xl">Level</p>
68
+ <p id="level" class="text-3xl font-bold">1</p>
69
+ </div>
70
+ </div>
71
+
72
+ <div class="relative w-full max-w-md h-96 flex items-center justify-center">
73
+ <div id="game" class="game-container w-64 h-96 relative">
74
+ <!-- Game grid will be generated here -->
75
+ </div>
76
+
77
+ <div id="game-over" class="absolute inset-0 bg-black bg-opacity-70 flex flex-col items-center justify-center hidden">
78
+ <h2 class="text-3xl font-bold mb-4">Game Over!</h2>
79
+ <p id="final-score" class="text-xl mb-6">Your score: 0</p>
80
+ <button id="restart" class="px-6 py-2 bg-pink-600 rounded-lg hover:bg-pink-700 transition">
81
+ Play Again
82
+ </button>
83
+ </div>
84
+ </div>
85
+
86
+ <div class="mt-6 text-center">
87
+ <p class="mb-2">Controls:</p>
88
+ <div class="grid grid-cols-3 gap-2 max-w-xs mx-auto">
89
+ <div class="bg-gray-800 p-2 rounded">← Left</div>
90
+ <div class="bg-gray-800 p-2 rounded">→ Right</div>
91
+ <div class="bg-gray-800 p-2 rounded">↑ Rotate</div>
92
+ <div class="bg-gray-800 p-2 rounded">↓ Down</div>
93
+ <div class="bg-gray-800 p-2 rounded">Space Drop</div>
94
+ <div class="bg-gray-800 p-2 rounded">R 3D Rotate</div>
95
+ </div>
96
+ </div>
97
+
98
+ <div id="next-piece" class="mt-6 text-center">
99
+ <p class="mb-2">Next Piece:</p>
100
+ <div id="next-piece-display" class="w-24 h-24 mx-auto grid grid-cols-4 gap-1"></div>
101
+ </div>
102
+
103
+ <script>
104
+ document.addEventListener('DOMContentLoaded', () => {
105
+ // Game constants
106
+ const COLS = 10;
107
+ const ROWS = 20;
108
+ const BLOCK_SIZE = 30;
109
+ const EMOJIS = ['😀', '😎', '🤩', '😍', '🤪', '🧐', '🥳', '🤯', '👻', '🤠', '👽', '🤖'];
110
+
111
+ // Game variables
112
+ let grid = Array(ROWS).fill().map(() => Array(COLS).fill(0));
113
+ let currentPiece = null;
114
+ let nextPiece = null;
115
+ let gameOver = false;
116
+ let score = 0;
117
+ let level = 1;
118
+ let gameRotation = 0;
119
+ let dropInterval = 1000;
120
+ let dropStart = null;
121
+ let animationFrameId = null;
122
+
123
+ // DOM elements
124
+ const gameEl = document.getElementById('game');
125
+ const scoreEl = document.getElementById('score');
126
+ const levelEl = document.getElementById('level');
127
+ const gameOverEl = document.getElementById('game-over');
128
+ const finalScoreEl = document.getElementById('final-score');
129
+ const restartBtn = document.getElementById('restart');
130
+ const nextPieceDisplay = document.getElementById('next-piece-display');
131
+
132
+ // Initialize game
133
+ function init() {
134
+ createGrid();
135
+ generateNewPiece();
136
+ generateNextPiece();
137
+ updateScore();
138
+ gameLoop();
139
+ addEventListeners();
140
+ }
141
+
142
+ // Create game grid
143
+ function createGrid() {
144
+ gameEl.innerHTML = '';
145
+ gameEl.style.width = `${COLS * BLOCK_SIZE}px`;
146
+ gameEl.style.height = `${ROWS * BLOCK_SIZE}px`;
147
+
148
+ for (let y = 0; y < ROWS; y++) {
149
+ for (let x = 0; x < COLS; x++) {
150
+ const cell = document.createElement('div');
151
+ cell.className = 'absolute border border-gray-800 bg-gray-900';
152
+ cell.style.width = `${BLOCK_SIZE}px`;
153
+ cell.style.height = `${BLOCK_SIZE}px`;
154
+ cell.style.left = `${x * BLOCK_SIZE}px`;
155
+ cell.style.top = `${y * BLOCK_SIZE}px`;
156
+ cell.dataset.x = x;
157
+ cell.dataset.y = y;
158
+ gameEl.appendChild(cell);
159
+ }
160
+ }
161
+ }
162
+
163
+ // Game pieces
164
+ const PIECES = [
165
+ { shape: [[1,1,1,1]], color: 'bg-red-500', emoji: EMOJIS[0] }, // I
166
+ { shape: [[1,1,1], [0,1,0]], color: 'bg-blue-500', emoji: EMOJIS[1] }, // T
167
+ { shape: [[1,1,0], [0,1,1]], color: 'bg-green-500', emoji: EMOJIS[2] }, // Z
168
+ { shape: [[0,1,1], [1,1,0]], color: 'bg-yellow-500', emoji: EMOJIS[3] }, // S
169
+ { shape: [[1,1], [1,1]], color: 'bg-purple-500', emoji: EMOJIS[4] }, // O
170
+ { shape: [[1,1,1], [1,0,0]], color: 'bg-pink-500', emoji: EMOJIS[5] }, // L
171
+ { shape: [[1,1,1], [0,0,1]], color: 'bg-indigo-500', emoji: EMOJIS[6] } // J
172
+ ];
173
+
174
+ // Generate a new random piece
175
+ function generateNewPiece() {
176
+ if (nextPiece) {
177
+ currentPiece = nextPiece;
178
+ } else {
179
+ const randomIndex = Math.floor(Math.random() * PIECES.length);
180
+ currentPiece = {
181
+ ...PIECES[randomIndex],
182
+ x: Math.floor(COLS / 2) - Math.floor(PIECES[randomIndex].shape[0].length / 2),
183
+ y: 0,
184
+ rotation: 0
185
+ };
186
+ }
187
+
188
+ generateNextPiece();
189
+
190
+ // Check if game over
191
+ if (collision()) {
192
+ gameOver = true;
193
+ gameOverEl.classList.remove('hidden');
194
+ finalScoreEl.textContent = `Your score: ${score}`;
195
+ }
196
+ }
197
+
198
+ // Generate next piece for preview
199
+ function generateNextPiece() {
200
+ const randomIndex = Math.floor(Math.random() * PIECES.length);
201
+ nextPiece = {
202
+ ...PIECES[randomIndex],
203
+ x: Math.floor(COLS / 2) - Math.floor(PIECES[randomIndex].shape[0].length / 2),
204
+ y: 0,
205
+ rotation: 0
206
+ };
207
+
208
+ updateNextPieceDisplay();
209
+ }
210
+
211
+ // Update next piece display
212
+ function updateNextPieceDisplay() {
213
+ nextPieceDisplay.innerHTML = '';
214
+ const shape = nextPiece.shape;
215
+
216
+ // Center the piece in the display
217
+ const offsetX = Math.floor((4 - shape[0].length) / 2);
218
+ const offsetY = Math.floor((4 - shape.length) / 2);
219
+
220
+ for (let y = 0; y < 4; y++) {
221
+ for (let x = 0; x < 4; x++) {
222
+ const cell = document.createElement('div');
223
+ cell.className = 'w-6 h-6 flex items-center justify-center';
224
+
225
+ if (y - offsetY >= 0 && y - offsetY < shape.length &&
226
+ x - offsetX >= 0 && x - offsetX < shape[0].length &&
227
+ shape[y - offsetY][x - offsetX]) {
228
+ cell.innerHTML = `<div class="w-full h-full ${nextPiece.color} flex items-center justify-center">${nextPiece.emoji}</div>`;
229
+ }
230
+
231
+ nextPieceDisplay.appendChild(cell);
232
+ }
233
+ }
234
+ }
235
+
236
+ // Draw the game
237
+ function draw() {
238
+ // Clear the grid
239
+ document.querySelectorAll('#game > div').forEach(cell => {
240
+ cell.innerHTML = '';
241
+ cell.className = 'absolute border border-gray-800 bg-gray-900';
242
+ cell.style.width = `${BLOCK_SIZE}px`;
243
+ cell.style.height = `${BLOCK_SIZE}px`;
244
+ });
245
+
246
+ // Draw locked pieces
247
+ for (let y = 0; y < ROWS; y++) {
248
+ for (let x = 0; x < COLS; x++) {
249
+ if (grid[y][x]) {
250
+ const cell = document.querySelector(`[data-x="${x}"][data-y="${y}"]`);
251
+ if (cell) {
252
+ cell.innerHTML = create3DBlock(grid[y][x].color, grid[y][x].emoji);
253
+ cell.classList.add(grid[y][x].color);
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ // Draw current piece
260
+ if (currentPiece) {
261
+ const shape = rotateShape(currentPiece.shape, currentPiece.rotation);
262
+ for (let y = 0; y < shape.length; y++) {
263
+ for (let x = 0; x < shape[y].length; x++) {
264
+ if (shape[y][x]) {
265
+ const posX = currentPiece.x + x;
266
+ const posY = currentPiece.y + y;
267
+ if (posY >= 0 && posX >= 0 && posX < COLS) {
268
+ const cell = document.querySelector(`[data-x="${posX}"][data-y="${posY}"]`);
269
+ if (cell) {
270
+ cell.innerHTML = create3DBlock(currentPiece.color, currentPiece.emoji);
271
+ cell.classList.add(currentPiece.color, 'falling');
272
+ }
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ }
279
+
280
+ // Create 3D block with emoji
281
+ function create3DBlock(color, emoji) {
282
+ return `
283
+ <div class="block w-full h-full">
284
+ <div class="block-face front ${color}">${emoji}</div>
285
+ <div class="block-face back ${color}">${emoji}</div>
286
+ <div class="block-face right ${color}">${emoji}</div>
287
+ <div class="block-face left ${color}">${emoji}</div>
288
+ <div class="block-face top ${color}">${emoji}</div>
289
+ <div class="block-face bottom ${color}">${emoji}</div>
290
+ </div>
291
+ `;
292
+ }
293
+
294
+ // Rotate shape
295
+ function rotateShape(shape, rotation) {
296
+ rotation = rotation % 4;
297
+ if (rotation < 0) rotation += 4;
298
+
299
+ if (rotation === 0) return shape;
300
+
301
+ let rotated = shape;
302
+ for (let i = 0; i < rotation; i++) {
303
+ rotated = rotated[0].map((_, index) =>
304
+ rotated.map(row => row[index]).reverse()
305
+ );
306
+ }
307
+
308
+ return rotated;
309
+ }
310
+
311
+ // Check for collisions
312
+ function collision() {
313
+ const shape = rotateShape(currentPiece.shape, currentPiece.rotation);
314
+ for (let y = 0; y < shape.length; y++) {
315
+ for (let x = 0; x < shape[y].length; x++) {
316
+ if (shape[y][x]) {
317
+ const posX = currentPiece.x + x;
318
+ const posY = currentPiece.y + y;
319
+
320
+ if (posY >= ROWS || posX < 0 || posX >= COLS || (posY >= 0 && grid[posY][posX])) {
321
+ return true;
322
+ }
323
+ }
324
+ }
325
+ }
326
+ return false;
327
+ }
328
+
329
+ // Lock piece in place
330
+ function lockPiece() {
331
+ const shape = rotateShape(currentPiece.shape, currentPiece.rotation);
332
+ for (let y = 0; y < shape.length; y++) {
333
+ for (let x = 0; x < shape[y].length; x++) {
334
+ if (shape[y][x]) {
335
+ const posY = currentPiece.y + y;
336
+ if (posY >= 0) {
337
+ grid[posY][currentPiece.x + x] = {
338
+ color: currentPiece.color,
339
+ emoji: currentPiece.emoji
340
+ };
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ // Check for completed lines
347
+ checkLines();
348
+
349
+ // Generate new piece
350
+ generateNewPiece();
351
+ }
352
+
353
+ // Check for completed lines
354
+ function checkLines() {
355
+ let linesCleared = 0;
356
+
357
+ for (let y = ROWS - 1; y >= 0; y--) {
358
+ if (grid[y].every(cell => cell !== 0)) {
359
+ // Remove the line
360
+ grid.splice(y, 1);
361
+ // Add new empty line at top
362
+ grid.unshift(Array(COLS).fill(0));
363
+ linesCleared++;
364
+ y++; // Check the same row again
365
+ }
366
+ }
367
+
368
+ if (linesCleared > 0) {
369
+ // Update score
370
+ score += [0, 40, 100, 300, 1200][linesCleared] * level;
371
+ // Increase level every 10 lines
372
+ const newLevel = Math.floor(score / 1000) + 1;
373
+ if (newLevel > level) {
374
+ level = newLevel;
375
+ dropInterval = Math.max(100, 1000 - (level - 1) * 100);
376
+ }
377
+ updateScore();
378
+ }
379
+ }
380
+
381
+ // Update score display
382
+ function updateScore() {
383
+ scoreEl.textContent = score;
384
+ levelEl.textContent = level;
385
+ }
386
+
387
+ // Game loop
388
+ function gameLoop(timestamp) {
389
+ if (gameOver) return;
390
+
391
+ if (!dropStart) dropStart = timestamp;
392
+ const delta = timestamp - dropStart;
393
+
394
+ if (delta > dropInterval) {
395
+ moveDown();
396
+ dropStart = null;
397
+ }
398
+
399
+ draw();
400
+ animationFrameId = requestAnimationFrame(gameLoop);
401
+ }
402
+
403
+ // Move piece down
404
+ function moveDown() {
405
+ currentPiece.y++;
406
+ if (collision()) {
407
+ currentPiece.y--;
408
+ lockPiece();
409
+ }
410
+ }
411
+
412
+ // Move piece left
413
+ function moveLeft() {
414
+ currentPiece.x--;
415
+ if (collision()) {
416
+ currentPiece.x++;
417
+ }
418
+ }
419
+
420
+ // Move piece right
421
+ function moveRight() {
422
+ currentPiece.x++;
423
+ if (collision()) {
424
+ currentPiece.x--;
425
+ }
426
+ }
427
+
428
+ // Rotate piece
429
+ function rotatePiece() {
430
+ currentPiece.rotation++;
431
+ if (collision()) {
432
+ // Try wall kicks
433
+ const originalX = currentPiece.x;
434
+ const kicks = [-1, 1, -2, 2];
435
+ for (const kick of kicks) {
436
+ currentPiece.x += kick;
437
+ if (!collision()) return;
438
+ currentPiece.x = originalX;
439
+ }
440
+ currentPiece.rotation--;
441
+ }
442
+ }
443
+
444
+ // Drop piece instantly
445
+ function hardDrop() {
446
+ while (!collision()) {
447
+ currentPiece.y++;
448
+ }
449
+ currentPiece.y--;
450
+ lockPiece();
451
+ }
452
+
453
+ // Rotate game view
454
+ function rotateGameView() {
455
+ gameRotation = (gameRotation + 90) % 360;
456
+ gameEl.style.transform = `rotateY(${gameRotation}deg)`;
457
+ }
458
+
459
+ // Event listeners
460
+ function addEventListeners() {
461
+ document.addEventListener('keydown', e => {
462
+ if (gameOver) return;
463
+
464
+ switch (e.key) {
465
+ case 'ArrowLeft':
466
+ moveLeft();
467
+ break;
468
+ case 'ArrowRight':
469
+ moveRight();
470
+ break;
471
+ case 'ArrowDown':
472
+ moveDown();
473
+ break;
474
+ case 'ArrowUp':
475
+ rotatePiece();
476
+ break;
477
+ case ' ':
478
+ hardDrop();
479
+ break;
480
+ case 'r':
481
+ case 'R':
482
+ rotateGameView();
483
+ break;
484
+ }
485
+ });
486
+
487
+ restartBtn.addEventListener('click', () => {
488
+ // Reset game
489
+ grid = Array(ROWS).fill().map(() => Array(COLS).fill(0));
490
+ currentPiece = null;
491
+ nextPiece = null;
492
+ gameOver = false;
493
+ score = 0;
494
+ level = 1;
495
+ dropInterval = 1000;
496
+ gameRotation = 0;
497
+ gameEl.style.transform = 'rotateY(0deg)';
498
+ gameOverEl.classList.add('hidden');
499
+
500
+ // Start new game
501
+ generateNewPiece();
502
+ generateNextPiece();
503
+ updateScore();
504
+ dropStart = null;
505
+ if (animationFrameId) {
506
+ cancelAnimationFrame(animationFrameId);
507
+ }
508
+ gameLoop();
509
+ });
510
+ }
511
+
512
+ // Start the game
513
+ init();
514
+ });
515
+ </script>
516
+ <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=manmohanai/3dimojitetris" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
517
+ </html>