PauloRB.dev

Desenvolvedor de Software

Tutorial de Desenvolvimento: Criando um Jogo de Tetris | PauloRB.dev Tutorial de Desenvolvimento: Criando um Jogo de Tetris – PauloRB.dev
Tutorial de Desenvolvimento: Criando um Jogo de Tetris

Tutorial de Desenvolvimento: Criando um Jogo de Tetris

E vamos a mais um tutorial de outro joguinho clássico só que dessa vez vamos recriar o Tetris.

Link do repositório: https://github.com/paulodm145/tetris

Estrutura do Projeto

/projeto-tetris

├── index.html
├── styles.css
└── script.js

1. index.html

Este arquivo contém a estrutura básica da página do jogo.

<!DOCTYPE html>
<html lang="pt">
<head>
    <meta charset="UTF-8">
    <title>Tetris</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="tetris-container">
        <div id="score">Pontuação: <span>0</span></div>
        <div id="tetris"></div>
        <div class="buttons">
            <button id="restart">Reiniciar</button>
            <button id="pause">Pausar</button>
            <button id="reset-score">Zerar Pontuação</button>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

  • Cabeçalho: Contém as configurações básicas e a inclusão do arquivo CSS.
  • Corpo: Inclui o contêiner principal do jogo, o tabuleiro (#tetris), a exibição da pontuação e os botões de controle.

2. styles.css

Este arquivo contém os estilos do jogo.

body {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    background-color: #e0e0e0;
    font-family: Arial, sans-serif;
    margin: 0;
}

#tetris-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

#tetris {
    width: 300px;
    height: 600px;
    border: 2px solid #333;
    background-color: #fff;
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    grid-template-rows: repeat(20, 1fr);
    gap: 1px;
    margin-bottom: 20px;
}

#tetris div {
    background-color: #f0f0f0;
    box-sizing: border-box;
}

#score {
    font-size: 1.5em;
    color: #333;
    margin-bottom: 10px;
}

#score span {
    font-weight: bold;
}

.buttons {
    display: flex;
    gap: 10px;
}

button {
    padding: 10px 20px;
    font-size: 1em;
    color: #fff;
    background-color: #007bff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s;
}

button:hover {
    background-color: #0056b3;
}

  • Estilos Básicos: Define o layout da página e do contêiner do jogo.
  • Tabuleiro: Configura o tamanho e o estilo do tabuleiro de Tetris.
  • Botões: Estiliza os botões de controle com cores e transições.

3. script.js

Este arquivo contém a lógica do jogo de Tetris.

document.addEventListener('DOMContentLoaded', () => {
    const grid = document.querySelector('#tetris');
    const width = 10;
    let timerId;
    let score = 0;
    const colors = ['orange', 'red', 'purple', 'green', 'blue'];

    // Criar a grade e preencher com divs
    function createBoard() {
        for (let i = 0; i < 200; i++) { // 200 divs para o tabuleiro
            let square = document.createElement('div');
            grid.appendChild(square);
        }
        for (let i = 0; i < 10; i++) { // 10 divs para a linha de base
            let square = document.createElement('div');
            square.classList.add('taken');
            grid.appendChild(square);
        }
    }
    createBoard();

    let squares = Array.from(grid.querySelectorAll('div'));
    const scoreDisplay = document.querySelector('#score span');
    let nextRandom = 0; // inicialização correta de nextRandom

    // Os Tetrominos e suas rotações
    const lTetromino = [
        [1, width+1, width*2+1, 2],
        [width, width+1, width+2, width*2+2],
        [1, width+1, width*2+1, width*2],
        [width, width*2, width*2+1, width*2+2]
    ];

    const zTetromino = [
        [0, width, width+1, width*2+1],
        [width+1, width+2, width*2, width*2+1],
        [0, width, width+1, width*2+1],
        [width+1, width+2, width*2, width*2+1]
    ];

    const tTetromino = [
        [1, width, width+1, width+2],
        [1, width+1, width+2, width*2+1],
        [width, width+1, width+2, width*2+1],
        [1, width, width+1, width*2+1]
    ];

    const oTetromino = [
        [0, 1, width, width+1],
        [0, 1, width, width+1],
        [0, 1, width, width+1],
        [0, 1, width, width+1]
    ];

    const iTetromino = [
        [1, width+1, width*2+1, width*3+1],
        [width, width+1, width+2, width+3],
        [1, width+1, width*2+1, width*3+1],
        [width, width+1, width+2, width+3]
    ];

    const theTetrominos = [lTetromino, zTetromino, tTetromino, oTetromino, iTetromino];

    let currentPosition = 4;
    let currentRotation = 0;
    let random = Math.floor(Math.random() * theTetrominos.length);
    let current = theTetrominos[random][currentRotation];

    // Desenhar o Tetromino
    function draw() {
        current.forEach(index => {
            squares[currentPosition + index].style.backgroundColor = colors[random];
        });
    }

    // Desfazer o desenho do Tetromino
    function undraw() {
        current.forEach(index => {
            squares[currentPosition + index].style.backgroundColor = '';
        });
    }

    // Fazer o Tetromino cair a cada segundo
    timerId = setInterval(moveDown, 1000);

    // Mover Tetromino para baixo
    function moveDown() {
        undraw();
        currentPosition += width;
        draw();
        freeze();
    }

    // Congelar quando o Tetromino atinge o fundo da grade
    function freeze() {
        if (current.some(index => squares[currentPosition + index + width].classList.contains('taken'))) {
            current.forEach(index => squares[currentPosition + index].classList.add('taken'));
            random = nextRandom;
            nextRandom = Math.floor(Math.random() * theTetrominos.length);
            current = theTetrominos[random][currentRotation];
            currentPosition = 4;
            draw();
            addScore();
            gameOver();
        }
    }

    // Adicionar pontuação
    function addScore() {
        for (let i = 0; i < 199; i += width) {
            const row = [i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9];

            if (row.every(index => squares[index].classList.contains('taken'))) {
                score += 10;
                scoreDisplay.innerText = score;
                row.forEach(index => {
                    squares[index].classList.remove('taken');
                    squares[index].style.backgroundColor = '';
                });
                const squaresRemoved = squares.splice(i, width);
                squares = squaresRemoved.concat(squares);
                squares.forEach(cell => grid.appendChild(cell));
            }
        }
    }

    // Verificar o fim do jogo
    function gameOver() {
        if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
            scoreDisplay.innerText = 'Fim de jogo';
            clearInterval(timerId);
        }
    }

    document.addEventListener('keyup', control);
    function control(e) {
        if (e.keyCode === 37) {
            moveLeft();
        } else if (e.keyCode === 38) {
            rotate();
        } else if (e.keyCode === 39) {
            moveRight();
        } else if (e.keyCode === 40) {
            moveDown();
        }
    }

    function moveLeft() {
        undraw();
        const isAtLeftEdge = current.some(index => (currentPosition + index) % width === 0);
        if (!isAtLeftEdge) currentPosition -= 1;
        if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
            currentPosition += 1;
        }
        draw();
    }

    function moveRight() {
        undraw();
        const isAtRightEdge = current.some(index => (currentPosition + index) % width === width - 1);
        if (!isAtRightEdge) currentPosition += 1;
        if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
            currentPosition -= 1;
        }
        draw();
    }

    function rotate() {
        undraw();
        currentRotation++;
        if (currentRotation === current.length) {
            currentRotation = 0;
        }
        current = theTetrominos[random][currentRotation];
        draw();
    }

    document.querySelector('#restart').addEventListener('click', () => {
        clearInterval(timerId);
        score = 0;
        scoreDisplay.innerText = score;
        nextRandom = 0;
        createBoard();
        random = Math.floor(Math.random() * theTetrominos.length);
        current = theTetrominos[random][currentRotation];
        currentPosition = 4;
        draw();
        timerId = setInterval(moveDown, 1000);
    });

    document.querySelector('#pause').addEventListener('click', () => {
        if (timerId) {
            clearInterval(timerId);
            timerId = null;
            document.querySelector('#pause').innerText = 'Retomar';
        } else {
            timerId = setInterval(moveDown, 1000);
            document.querySelector('#pause').innerText = 'Pausar';
        }
    });

    document.querySelector('#reset-score').addEventListener('click', () => {
        score = 0;
        scoreDisplay.innerText = score;
    });
});

  • Variáveis e Seletores: Definem elementos do DOM e variáveis necessárias para o jogo.
  • createBoard(): Cria o tabuleiro do jogo preenchendo-o com células.
  • Tetrominos: Define as formas e rotações dos Tetrominos.
  • Desenho e Movimentação: Funções para desenhar, mover, rotacionar e congelar os Tetrominos.
  • Controle de Teclado: Adiciona eventos de teclado para mover e rotacionar os Tetrominos.
  • Funções de Controle: Funções para reiniciar, pausar e zerar a pontuação do jogo.

Como Executar

  1. Faça o download ou clone este repositório.
  2. Abra o arquivo index.html em um navegador web.
  3. O jogo será carregado e estará pronto para jogar.
  4. Utilize as teclas de seta para mover e rotacionar os Tetrominos:
    • Seta para esquerda: Move o Tetromino para a esquerda.
    • Seta para direita: Move o Tetromino para a direita.
    • Seta para cima: Rotaciona o Tetromino.
    • Seta para baixo: Move o Tetromino para baixo.
  5. Use os botões de controle para reiniciar, pausar e zerar a pontuação do jogo.

Mais Posts

Gerando Dados Fictícios para Análise de Compras em Python

Gerando Dados Fictícios para Análise de Compras em Python

Ao realizar estudos de análise de dados ou ao testar sistemas que lidam com grandes volumes de informações, é comum... Leia mais

Como instalar a Linguagem ELIXIR no Linux.

Como instalar a Linguagem ELIXIR no Linux.

Elixir é uma linguagem de programação dinâmica e funcional, desenvolvida por José Valim em 2011, projetada para construir aplicações escaláveis... Leia mais

Como Instalar e Acessar o PostgreSQL no WSL com DBeaver

Como Instalar e Acessar o PostgreSQL no WSL com DBeaver

PostgreSQL é um dos sistemas de gerenciamento de banco de dados mais populares, conhecido por sua robustez e recursos avançados.... Leia mais

Instalando e Gerenciando o SQLite no Linux

Instalando e Gerenciando o SQLite no Linux

Introdução ao SQLite O SQLite é um sistema de banco de dados leve, sem servidor e autocontido, amplamente utilizado em... Leia mais