Pitch: ÓRBITA, meu primeiro jogo — um roguelite de bingo feito sozinho na Godot, com núcleo determinístico e UI toda em _draw()

Oi, pessoal! Essa semana saiu na Steam o meu primeiro jogo, ÓRBITA: Bingo roguelite, e queria contar aqui como ele foi feito por dentro, principalmente a parte técnica. Desenvolvi sozinho (com a ajuda de alguns testers), e o lançamento foi bem discreto: 25 cópias e 3 análises até agora. Por isso a opinião de quem também programa vale ouro pra mim.

O jogo

É um roguelite de estratégia numa cartela de bingo. Em vez de esperar o sorteio, você escolhe as bolas numa bandeja; as marcas ficam de uma mão para a outra, e antes de cada jogada aparece a pontuação exata (FICHAS × MULT). São 77 amuletos, 29 guardiões que mudam uma regra cada, 12 paradas em 4 salas por partida, semente do dia e nada de cronômetro. 9 idiomas (incluindo português do Brasil), Windows e Linux, com suporte a controle.

Pitch: ÓRBITA, meu primeiro jogo — um roguelite de bingo feito sozinho na Godot, com núcleo determinístico e UI toda em _draw(), image #1

Stack: Godot 4.7 e GDScript.

1. Um núcleo determinístico, sem nós

Todas as regras ficam em scripts que não dependem da árvore de cena: nada de Node, nada de _process(). O motor recebe uma semente, usa um RNG com essa semente e consegue salvar e restaurar o estado inteiro da partida de forma exata. Mesma semente + mesmas decisões = mesma partida.

Na prática, isso me deu três coisas quase de graça:

  • a semente do dia, em que todo mundo joga a mesma partida;
  • bugs reproduzíveis a partir de um save;
  • testes de regra que rodam headless, sem abrir janela.

2. A prévia é o próprio motor (e os testes provam que ela não mente)

O pilar do design é "acaso na entrada, certeza na saída": antes de clicar, você vê exatamente quanto a jogada vai pontuar. Essa prévia não é uma estimativa feita pela interface; é o mesmo motor calculando a jogada sem mexer no estado.

A propriedade que os testes verificam é simples:

simular(acao) == aplicar(acao)

Para muitas sementes e jogadas aleatórias, a suíte calcula a prévia, aplica a jogada de verdade e compara os dois resultados. Se um amuleto ou guardião novo fizer a prévia divergir do resultado em um único ponto, o teste quebra. Foi a decisão que mais me poupou dor de cabeça: com 77 amuletos interagindo, eu nunca confiaria numa prévia escrita à parte.

3. A interface inteira desenhada em _draw()

Botões, painéis, cartas, a cartela e os números são desenhados em código com _draw(); não há imagens de interface. Dá mais trabalho no começo, mas trouxe vantagens:

  • traduzir para 9 idiomas não exigiu redesenhar nenhuma imagem, só ajustar quebras de linha e tamanhos de texto;
  • o modo de texto grande vale para o jogo inteiro;
  • o custo aparece no desempenho, mas dá para controlar: numa atualização passei a guardar o fundo e a arte das cartas em camadas que não são redesenhadas quando nada muda.

4. Fontes CJK com pyftsubset

Chinês e japonês precisam de fontes CJK, e a coleção Noto Sans CJK pesa 18 MB por peso. Com o pyftsubset (do fontTools) eu gero uma fonte só com os caracteres que o jogo usa: a união do subconjunto anterior com o catálogo de textos do idioma e os créditos. Resultado: cerca de 580 KB e 1.414 caracteres para o chinês, e cerca de 600 KB e 1.174 para o japonês.

pyftsubset NotoSansCJK-Medium.ttc --font-number=2 \ --text-file=caracteres_zh.txt --output-file=OrbitaSC.otf

A pegadinha: quase todo texto novo em chinês ou japonês traz algum caractere que não está no subconjunto, e na tela ele vira um quadradinho. Por isso há um teste de glifos que percorre os catálogos e quebra se faltar algum; aí é só regenerar a fonte.

5. O trailer gravado com o Movie Maker da Godot

O trailer não foi capturado jogando na mão: usei o Movie Maker da Godot (--write-movie), que grava com tempo fixo por frame, restaurando estados reais de partida. Como o motor é determinístico, as 9 versões do trailer (uma por idioma) têm exatamente os mesmos frames; só muda o texto.

Sobre IA

Sobre IA: parte da arte é gerada por IA (muitas cartas de amuleto, quase todos os retratos dos guardiões e as ilustrações da história), e a música também (feita com ACE-Step). Os textos e as 9 traduções têm ajuda de IA, e eu programo o jogo com agentes de IA (Claude e Codex) que eu dirijo e reviso. As bolas, os globos, os guardiões mecânicos e alguns amuletos são renders do Blender, a interface é desenhada em código e os efeitos sonoros são sintetizados por script. Nada é gerado por IA enquanto você joga.

Link

Steam: https://store.steampowered.com/app/5248520/?utm_source=tabnews&utm_medium=social&utm_campaign=lanzamiento1410&utm_content=tabnews_1015

Se alguém quiser que eu detalhe algum ponto (o motor, os testes, as fontes), posso explicar nos comentários. Críticas são muito bem-vindas, respondo todo mundo.

Source

2 views·1 share