<style>
   .game-container {
       display: flex;
       flex-direction: column;
       align-items: center;
       background-color: #1a1a2e;
       border-radius: 12px;
       box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
       padding: 1rem;
       font-family: 'Inter', sans-serif;
       color: #e0e0e0;
   }
   #gameCanvas {
       border: 2px solid #4a90e2;
       background-color: #0f0f1a;
       border-radius: 8px;
       touch-action: none;
   }
   .game-info {
       display: flex;
       justify-content: space-between;
       width: 100%;
       margin-top: 1rem;
       padding: 0 1rem;
   }
   .game-controls {
       display: flex;
       justify-content: space-around;
       width: 100%;
       margin-top: 1rem;
   }
   .control-button {
       background-color: #4a90e2;
       border: none;
       color: white;
       padding: 1rem;
       font-size: 1.5rem;
       border-radius: 50%;
       cursor: pointer;
       transition: background-color 0.3s, transform 0.1s;
       box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
       width: 60px;
       height: 60px;
       display: flex;
       justify-content: center;
       align-items: center;
   }
   .control-button:hover {
       background-color: #63b3ed;
   }
   .control-button:active {
       background-color: #2b6cb0;
       transform: scale(0.95);
   }
</style>

<div class="game-container">
   <div class="game-info">
       <div class="score">Score: <span id="score">0</span></div>
       <div class="level">Level: <span id="level">1</span></div>
   </div>
   <canvas id="gameCanvas"></canvas>
   <div class="game-controls">
       <button id="leftBtn" class="control-button">←</button>
       <button id="rotateBtn" class="control-button">↻</button>
       <button id="rightBtn" class="control-button">→</button>
       <button id="downBtn" class="control-button">↓</button>
   </div>
</div>

<script>
   (function() {
       const canvas = document.getElementById('gameCanvas');
       const ctx = canvas.getContext('2d');
       const scoreElement = document.getElementById('score');
       const levelElement = document.getElementById('level');
       const leftBtn = document.getElementById('leftBtn');
       const rotateBtn = document.getElementById('rotateBtn');
       const rightBtn = document.getElementById('rightBtn');
       const downBtn = document.getElementById('downBtn');

       const TILE_SIZE = 30;
       const COLUMNS = 10;
       const ROWS = 20;

       canvas.width = COLUMNS * TILE_SIZE;
       canvas.height = ROWS * TILE_SIZE;

       const SHAPES = [
           // I
           [[1, 1, 1, 1]],
           // O
           [[1, 1], [1, 1]],
           // T
           [[0, 1, 0], [1, 1, 1]],
           // S
           [[0, 1, 1], [1, 1, 0]],
           // Z
           [[1, 1, 0], [0, 1, 1]],
           // L
           [[0, 0, 1], [1, 1, 1]],
           // J
           [[1, 0, 0], [1, 1, 1]]
       ];

       const COLORS = ['cyan', 'yellow', 'purple', 'green', 'red', 'orange', 'blue'];

       let board = Array.from({ length: ROWS }, () => Array(COLUMNS).fill(0));
       let currentPiece, currentColor, currentX, currentY;
       let score = 0;
       let level = 1;
       let dropCounter = 0;
       let dropInterval = 1000;
       let lastTime = 0;

       function getRandomPiece() {
           const index = Math.floor(Math.random() * SHAPES.length);
           return {
               shape: SHAPES[index],
               color: COLORS[index]
           };
       }

       function spawnPiece() {
           const newPiece = getRandomPiece();
           currentPiece = newPiece.shape;
           currentColor = newPiece.color;
           currentX = Math.floor(COLUMNS / 2) - Math.floor(currentPiece[0].length / 2);
           currentY = 0;
           if (checkCollision()) {
               // Game over
               ctx.fillStyle = 'rgba(0,0,0,0.7)';
               ctx.fillRect(0, 0, canvas.width, canvas.height);
               ctx.fillStyle = '#fff';
               ctx.font = '24px Inter';
               ctx.textAlign = 'center';
               ctx.fillText('Game Over', canvas.width / 2, canvas.height / 2 - 20);
               ctx.fillText('Score: ' + score, canvas.width / 2, canvas.height / 2 + 10);
               
               setTimeout(() => {
                   board = Array.from({ length: ROWS }, () => Array(COLUMNS).fill(0));
                   score = 0;
                   level = 1;
                   dropInterval = 1000;
                   updateUI();
                   spawnPiece();
               }, 3000);
           }
       }

       function checkCollision(x = currentX, y = currentY, piece = currentPiece) {
           for (let r = 0; r < piece.length; r++) {
               for (let c = 0; c < piece[r].length; c++) {
                   if (piece[r][c] !== 0) {
                       const newX = x + c;
                       const newY = y + r;
                       if (newX < 0 || newX >= COLUMNS || newY >= ROWS || (board[newY] && board[newY][newX] !== 0)) {
                           return true;
                       }
                   }
               }
           }
           return false;
       }

       function mergePiece() {
           for (let r = 0; r < currentPiece.length; r++) {
               for (let c = 0; c < currentPiece[r].length; c++) {
                   if (currentPiece[r][c] !== 0) {
                       board[currentY + r][currentX + c] = 1;
                   }
               }
           }
       }

       function clearLines() {
           let linesCleared = 0;
           let newBoard = [];
           for (let r = 0; r < ROWS; r++) {
               if (board[r].every(cell => cell !== 0)) {
                   linesCleared++;
               } else {
                   newBoard.push(board[r]);
               }
           }

           // Fill the top with empty rows
           while (newBoard.length < ROWS) {
               newBoard.unshift(Array(COLUMNS).fill(0));
           }
           
           board = newBoard;

           if (linesCleared > 0) {
               let multiplier = 0;
               if (linesCleared === 1) multiplier = 1;
               else if (linesCleared === 2) multiplier = 2;
               else if (linesCleared === 3) multiplier = 4;
               else if (linesCleared === 4) multiplier = 8;
               
               score += (linesCleared * COLUMNS * 10) * multiplier;

               if (score >= level * 10000) {
                   level++;
                   dropInterval /= 1.5;
               }
               updateUI();
           }
       }
       
       function rotatePiece() {
           const newPiece = currentPiece[0].map((_, colIndex) => currentPiece.map(row => row[colIndex]).reverse());
           if (!checkCollision(currentX, currentY, newPiece)) {
               currentPiece = newPiece;
           }
       }

       function draw() {
           ctx.clearRect(0, 0, canvas.width, canvas.height);
           // Draw board
           for (let r = 0; r < ROWS; r++) {
               for (let c = 0; c < COLUMNS; c++) {
                   if (board[r][c] !== 0) {
                       ctx.fillStyle = '#4a90e2';
                       ctx.fillRect(c * TILE_SIZE, r * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                       ctx.strokeStyle = '#2b6cb0';
                       ctx.lineWidth = 2;
                       ctx.strokeRect(c * TILE_SIZE, r * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                   }
               }
           }
           // Draw current piece
           if (currentPiece) {
               ctx.fillStyle = currentColor;
               for (let r = 0; r < currentPiece.length; r++) {
                   for (let c = 0; c < currentPiece[r].length; c++) {
                       if (currentPiece[r][c] !== 0) {
                           ctx.fillRect((currentX + c) * TILE_SIZE, (currentY + r) * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                           ctx.strokeStyle = '#0f0f1a';
                           ctx.lineWidth = 2;
                           ctx.strokeRect((currentX + c) * TILE_SIZE, (currentY + r) * TILE_SIZE, TILE_SIZE, TILE_SIZE);
                       }
                   }
               }
           }
       }
       
       function updateUI() {
           scoreElement.textContent = score;
           levelElement.textContent = level;
       }

       function gameLoop(time = 0) {
           const deltaTime = time - lastTime;
           lastTime = time;
           dropCounter += deltaTime;
           
           if (dropCounter > dropInterval) {
               currentY++;
               if (checkCollision()) {
                   currentY--;
                   mergePiece();
                   clearLines();
                   spawnPiece();
               }
               dropCounter = 0;
           }
           draw();
           requestAnimationFrame(gameLoop);
       }

       // --- Button Controls ---
       leftBtn.addEventListener('click', () => {
           currentX--;
           if (checkCollision()) {
               currentX++;
           }
           draw();
       });
       rightBtn.addEventListener('click', () => {
           currentX++;
           if (checkCollision()) {
               currentX--;
           }
           draw();
       });
       rotateBtn.addEventListener('click', () => {
           rotatePiece();
           draw();
       });
       downBtn.addEventListener('click', () => {
           currentY++;
           if (checkCollision()) {
               currentY--;
               mergePiece();
               clearLines();
               spawnPiece();
           }
           dropCounter = 0;
           draw();
       });

       // Initial setup
       spawnPiece();
       updateUI();
       gameLoop();
   })();
</script>
 

We need your consent to load the translations

We use a third-party service to translate the website content that may collect data about your activity. Please review the details in the privacy policy and accept the service to view the translations.