Tetris
Este tutorial ensina como criar o jogo Tetris do zero usando C++ e SFML. Vamos começar com conceitos básicos e construir o conhecimento passo a passo, explicando cada parte de forma clara e detalhada.
O que é Tetris
Imagine um jogo onde peças de diferentes formatos caem do céu como chuva, e você precisa organizá-las de forma inteligente para que se encaixem perfeitamente. É como um quebra-cabeças em movimento, onde:
Peças geométricas (chamadas de "tetrominós") caem de cima para baixo
Você pode mover as peças para esquerda e direita
Você pode girar as peças para encaixá-las melhor
Quando uma linha horizontal fica completamente preenchida, ela desaparece
O objetivo é durar o máximo de tempo possível sem deixar as peças chegarem ao topo
Este jogo é perfeito para aprender conceitos fundamentais de programação como arrays bidimensionais, rotação de objetos, detecção de colisões e manipulação de dados.
A Matemática Secreta dos Tetrominós
O que são Tetrominós?
Tetrominós são formas geométricas feitas de exatamente 4 quadrados conectados. Existem apenas 7 formas diferentes possíveis:
Como Representar Formas com Números
A parte mais inteligente do nosso Tetris é como representamos cada peça usando apenas números. Em vez de desenhar cada forma, usamos um sistema de coordenadas em uma grade 4x4:
Vamos entender como isso funciona:
Como converter números em posições:
Para transformar um número em coordenadas (x, y):
Por exemplo, o número 5:
x = 5 % 2 = 1 (coluna 1)
y = 5 / 2 = 2 (linha 2)
Isso significa que a posição 5 está na coluna 1, linha 2 da nossa grade 4x4.
A Estrutura do Jogo
O Campo de Jogo - Uma Grade Inteligente
O campo de jogo é como uma folha de papel quadriculado, onde cada quadradinho pode estar vazio (0) ou preenchido com uma cor (1 a 7):
Por que 20x10?
É o tamanho clássico do Tetris original
Oferece desafio suficiente sem ser impossível
Permite que as peças tenham espaço para manobrar
Representando as Peças Ativas
Cada peça tem 4 blocos, então usamos duas estruturas de dados:
Por que duas arrays?
a[4]: Posição atual da peça (onde ela está agora)
b[4]: Posição anterior da peça (onde ela estava antes)
Se um movimento for inválido, copiamos b para a (desfazemos o movimento)
As Principais Mecânicas do Jogo
1. Verificação de Colisões - A Função Mais Importante
Esta é a função que decide se um movimento é válido ou não:
O que esta função verifica:
2. Movimento Horizontal - Esquerda e Direita
O movimento horizontal é simples mas usa um truque inteligente:
A estratégia "Tentar e Desfazer":
Salvar a posição atual em
b
Mover a peça para a nova posição em
a
Verificar se a nova posição é válida
Se não for válida, copiar
b
de volta paraa
3. Rotação - A Parte Mais Matemática
A rotação é baseada em matemática de transformação de coordenadas. Giramos cada bloco 90 graus ao redor do segundo bloco da peça:
Como funciona a rotação matemática:
4. Queda Automática - O Tick do Jogo
As peças caem sozinhas seguindo um cronômetro:
A Lógica de Eliminar Linhas
Detectando Linhas Completas
A parte mais inteligente do Tetris é como removemos linhas completas. Usamos um algoritmo de "compactação":
Como Funciona o Algoritmo
Por que isso funciona:
Começamos de baixo para cima
Copiamos cada linha para a posição
k
Se a linha não está completa, movemos
k
para cimaSe a linha está completa,
k
não se move (linha será sobrescrita)Linhas completas "desaparecem" naturalmente
Exemplo prático:
Gerando Peças Aleatórias
Como Criar Peças Novas
Quando uma peça é fixada, criamos uma nova peça aleatória:
Por que Começar no Topo?
As peças novas sempre aparecem no topo da tela porque:
figures[n][i] representa posições de 0 a 15
figures[n][i] / 2 dá valores de 0 a 7 (linhas do topo)
Isso garante que as peças sempre começam visíveis
O Sistema de Cores
Cada Peça Tem Sua Cor
Mapeamento de cores:
0: Vazio (preto)
1-7: Diferentes cores para cada tipo de peça
Como Desenhar com Cores
Cada cor é uma seção de 18x18 pixels na textura.
Otimizações Inteligentes
Por que Usar Arrays de Tamanho Fixo?
Vantagens:
Cada tetrominó tem exatamente 4 blocos
Arrays de tamanho fixo são mais rápidos
Menos uso de memória
Código mais simples
Por que Não Usar Vetores Dinâmicos?
Para um jogo simples como Tetris:
A complexidade extra não vale a pena
Arrays fixos são mais eficientes
O código fica mais fácil de entender
A Matemática do Timing
Controlando a Velocidade
Como funciona:
timer
acumula o tempo passadodelay
define quantos segundos entre cada quedaQuando
timer > delay
, a peça desce um nível
Calculando FPS
Se o jogo roda a 60 FPS:
delay = 0.3 segundos
Peça cai a cada 0.3 × 60 = 18 frames
Isso dá tempo suficiente para o jogador pensar e agir
Detecção de Game Over
Quando o Jogo Termina?
O jogo termina quando uma nova peça não consegue ser colocada no topo:
Embora o código atual não implemente explicitamente o game over, a lógica está lá: se check()
retornar false para uma peça recém-criada, significa que o campo está cheio.
Conceitos Avançados
Por que Usar Coordenadas Relativas?
Quando geramos peças, usamos coordenadas relativas (0-15) que depois convertemos para coordenadas absolutas da tela. Isso permite:
Fácil mudança de tamanho: Alterar o tamanho dos blocos não quebra o jogo
Rotação simples: Matemática de rotação funciona melhor com coordenadas relativas
Reutilização: O mesmo código serve para diferentes posições na tela
A Beleza da Simplicidade
O Tetris prova que jogos incríveis podem ter código simples:
Apenas 154 linhas de código
Usa conceitos básicos: arrays, loops, condicionais
Sem classes complexas ou padrões de design rebuscados
Foca na lógica do jogo, não em arquitetura
Possíveis Melhorias
1. Sistema de Pontuação
2. Níveis de Dificuldade
3. Previsão da Próxima Peça
4. Sistema de Pausa
Por que este Código Funciona Tão Bem
1. Separação Clara de Responsabilidades
check()
: Valida movimentosLoop principal: Gerencia input e timing
Algoritmo de linha: Remove linhas completas
2. Uso Inteligente de Dados
Arrays 2D para o campo
Arrays 1D para peças
Números simples para representar formas
3. Algoritmos Eficientes
Verificação de colisão: O(1) por bloco
Remoção de linhas: O(n) onde n é o número de linhas
Rotação: O(1) por bloco
4. Matemática Simples mas Poderosa
Módulo e divisão para conversão de coordenadas
Rotação usando transformação linear
Timing baseado em acumulação de tempo
O Tetris Como Ferramenta de Aprendizado
Este jogo é perfeito para iniciantes porque ensina:
Arrays bidimensionais: O campo de jogo
Estruturas de dados: Points para representar blocos
Algoritmos: Detecção de colisão, remoção de linhas
Matemática básica: Rotação, conversão de coordenadas
Game loop: Timing, input, renderização
Lógica booleana: Verificações de validade
Cada conceito é usado de forma prática e imediata, tornando o aprendizado mais efetivo do que estudar teoria abstrata.
Conclusão
O Tetris é um exemplo perfeito de como um jogo simples pode ensinar conceitos profundos de programação. Sua beleza está na simplicidade elegante: com menos de 200 linhas de código, temos um jogo completo e divertido que demonstra arrays, algoritmos, matemática e lógica de jogos.
O código não é apenas funcional - é educativo. Cada linha tem um propósito claro, cada algoritmo resolve um problema específico, e o resultado final é um jogo que diverte e ensina ao mesmo tempo.