Alpha EdTech · Líder do projeto
RaceGame: corrida multiplayer em tempo real
Uma corrida top-down para até 10 jogadores na mesma pista, em que o servidor decide onde cada carro está e o navegador desenha a corrida sem esperar por ele.
Setas ou WASD para dirigir, espaço para o nitro, Enter para começar, R para recomeçar e Esc para pausar. Os selos azuis com raio são nitro; barris, troncos e cones seguram o carro. A linha azul tracejada marca o próximo checkpoint.
ou aperte Enter
No celular, use os botões abaixo da pista.
Setas ou WASD para dirigir, espaço para o nitro, Enter para começar, R para recomeçar e Esc para pausar. Os selos azuis com raio são nitro; barris, troncos e cones seguram o carro. A linha azul tracejada marca o próximo checkpoint.
Em 30 segundos
- Líder de um time de 4 num projeto da Alpha EdTech, feito em 3 semanas.
- Escrevi o motor do jogo nos dois lados: servidor autoritativo a 30 ticks/s, predição e interpolação no cliente, por WebSocket.
- Testado com a sala cheia, 10 jogadores. Em 2026 refiz o jogo com o Claude Code para rodar nesta página.
- Quando
- nov 2024 · 3 semanas
- Papel
- Líder do projeto · motor do jogo
- Time
- 4 pessoas
- Stack
- TypeScript, React, Canvas, Node.js, Express, ws, PostgreSQL, Redis, Docker
Contexto
Projeto do ciclo 2 da Alpha EdTech, uma code academy sem fins lucrativos que forma desenvolvedores em tempo integral, trabalhando em projetos reais. O time tinha três semanas para entregar um jogo multiplayer que rodasse no navegador, com login, salas e ranking.
Escolhemos uma corrida em visão de cima: pista com paredes, checkpoints, voltas, itens de nitro e até 10 carros disputando ao mesmo tempo.
O problema
Numa corrida em tempo real, todos precisam ver a mesma corrida. Se cada navegador calcular a própria posição, dois jogadores discordam de quem está na frente, e qualquer um pode trapacear editando o JavaScript.
Se, ao contrário, o navegador só desenha o que o servidor manda, o próprio carro responde às setas com o atraso da rede, e os outros carros andam aos trancos entre uma atualização e outra.
Minha parte
Como líder, coordenei o time, conduzi as decisões técnicas e a integração entre frontend e backend. No código, fiquei com o motor do jogo, dos dois lados. O restante do time cuidou do login, das salas e do lobby, e das telas.
- Game loop do servidor: física de velocidade e rotação, colisão com as paredes, checkpoints, voltas, itens e fim de corrida.
- Game loop do cliente em Canvas, com predição do próprio carro e interpolação dos adversários.
- Boa parte do servidor WebSocket e do contrato de mensagens entre cliente e servidor.
- Docker Compose de produção (frontend, backend, PostgreSQL e Redis).
Decisões técnicas
O servidor é a fonte da verdade
O navegador não envia posição, só quais teclas estão apertadas. O servidor roda o loop a 30 ticks por segundo, aplica física e colisões e decide onde cada carro está. Assim não há como “teletransportar” o carro pelo console.
Predição no cliente, com reconciliação
Para o próprio carro não esperar a rede, o cliente aplica a mesma física localmente e guarda cada movimento numerado. Quando o estado do servidor chega, compara pelo número do movimento e só corrige a posição se as duas versões divergirem.
Interpolação para os outros carros
Os adversários não são previstos: a cada quadro, o carro percorre metade da distância até a última posição recebida. Isso tira o tremido entre atualizações sem inventar movimento.
Só manda o que mudou
Antes de transmitir, o servidor compara posição, velocidade e rotação com o tick anterior. Carro parado não gera mensagem, o que reduz o tráfego com 10 jogadores na sala.
WebSocket sem Socket.IO
No servidor, a biblioteca ws; no navegador, a API nativa de WebSocket. As mensagens seguem um contrato tipado em TypeScript nos dois lados. Menos camadas entre o loop e o fio, e cada mensagem é nossa.
Arquitetura
Resultado
O jogo foi entregue e testado com a sala cheia, 10 jogadores na mesma corrida, rodando num servidor da Alpha EdTech. O vídeo na seção abaixo é um recorte dessa partida.
A reescrita de 2026
A versão jogável no topo desta página é uma reimplementação de 2026, feita a partir do motor de 2024. O original dependia do login, do banco e do servidor da Alpha EdTech, e a arte dele não tem licença para ser republicada; para dar para jogar aqui, o jogo foi refeito com a mesma direção e o mesmo traçado.
A reescrita foi feita com o Claude Code, a IA de programação da Anthropic: eu decidi o design, a física e o que entrava em cada rodada, joguei e revisei cada uma, e o código foi escrito em pareamento com a IA.
- O motor virou um pacote TypeScript sem dependências, com cada tick determinístico e testado, inclusive um teste de propriedade que garante que o carro nunca termina um movimento dentro de uma parede.
- A colisão foi refeita: o carro anda um eixo por vez e quica na parede em vez de grudar nela, o que acabou com o carro preso num canto da pista.
- Três modos: o treino, contra bots, e o contra o relógio, contra o fantasma da sua melhor corrida, rodam inteiros no navegador; o online roda no servidor (NestJS e ws, 30 ticks por segundo), e o navegador usa o mesmo motor para prever o próprio carro.
- Um formato compacto de mensagens (cerca de 11 KB/s por jogador numa sala de 10) e limites contra abuso protegem o servidor gratuito.
- A pista é desenhada em código a partir das caixas de colisão do motor.
Versão original, de novembro de 2024: partida de teste com a sala cheia, 10 jogadores.