Neste post
Toda discussão sobre jogo em Flutter degenera na mesma pergunta binária: usa Flame ou não usa?
A pergunta binária é ruim porque a resposta depende de uma característica do jogo que quase nunca é nomeada. Depois de sete jogos, o critério que usamos cabe numa linha:
O estado do jogo muda por frame ou muda por evento?
Tudo mais decorre disso.
O critério, aplicado
Um jogo que muda por evento tem estado estável entre interações. Nada acontece até alguém tocar na tela. É o caso de puzzle, cartas, merge, turno e da maior parte dos jogos idle.
Um jogo que muda por frame tem simulação rodando o tempo todo: posição, velocidade, colisão. Ele continua acontecendo mesmo com o dedo parado.
Note que "por evento" não quer dizer parado. Um idle acumula recurso com o tempo — mas isso é uma função do relógio, calculada quando a tela precisa mostrar, não uma simulação a 60 quadros por segundo.
O que o nosso portfólio realmente mostra
Aqui é onde o post fica mais útil do que uma regra bonita, porque os números não obedecem à regra tão bem quanto a gente gostaria. São sete jogos:
| Jogo | Gênero | Renderização |
|---|---|---|
| Chihuahua Fly | arcade endless flyer | Flame |
| Godforge | RPG idle / auto-battler | Flame |
| Zombounty | idle autobattler | Flame |
| Mewtopia Merge | merge idle | Flame |
| Villa Aurora | novela com minigames | Flame |
| Kombate | estratégia de tabuleiro | widget puro |
| Troll Quest BR | platformer | fora do Flutter |
Cinco de sete com Flame. Um único em widget puro. Se o critério fosse "idle usa widget", quatro dessas linhas estariam erradas.
Por que os idle acabaram em Flame
Godforge, Zombounty e Mewtopia são idle — pelo critério declarado, deveriam ser widget puro. E não são. A razão não é incoerência: é que "idle" descreve a economia, não a tela.
Num auto-battler idle, o jogador não toma decisão durante a luta. Mas a luta acontece: o herói atira, o zumbi anda, o dano aparece, o chefe tem barra que esvazia. Isso é simulação por frame, com muitos objetos ao mesmo tempo — o critério original, aplicado à parte certa do jogo.
O que confunde é o rótulo de gênero. "Idle" fala do loop de progressão: você fecha o app e continua ganhando. Não fala nada sobre quantos sprites se mexem na tela enquanto está aberto.
Refinando o critério: a pergunta não é sobre o jogo, é sobre a tela. Um mesmo jogo pode ter tela de progressão que muda por evento e tela de combate que muda por frame — e a resposta certa é widget numa e Flame na outra.
O Kombate é o único em widget puro e o motivo é exato: tabuleiro de estratégia por turno, tipo Combate/Stratego. Peça só se move quando alguém move. Não existe frame em que algo mude sozinho — nem na progressão, nem no combate.
A diferença não é o jogo "ter movimento". É se o movimento precisa ser simulado passo a passo ou pode ser interpolado entre dois estados. Animação de transição é interpolação, e o Flutter faz isso sozinho.
Onde widget puro ganha, e ganha fácil
Para jogo por evento, usar Flame é adicionar um sistema paralelo sem necessidade.
O que se ganha ficando no Flutter:
Layout responsivo de graça. Grade que se adapta a tela de qualquer tamanho é o problema que o Flutter resolve melhor que qualquer coisa. Reimplementar isso dentro de um canvas é trabalho puro.
Acessibilidade e entrada. Toque, arrastar, foco, leitor de tela — tudo já funciona. Dentro de um canvas, nada disso existe até você construir.
Um sistema só. Menu, loja, configurações e o jogo compartilham widgets, tema e navegação. Sem ponte entre dois mundos.
Ferramentas. Hot reload de verdade, inspetor de widget, tudo o que já existe.
O Kombate é o exemplo mais claro disso na nossa lista: tabuleiro, peças, setup, combate por turno, modo online e contra bot. Nada aí é simulação por frame. É estado, regra e transição — e a interface é uma grade responsiva, que é a especialidade da casa.
O contraexemplo instrutivo é o Mewtopia Merge, que tem grade 5×6, merge por arrastar e soltar e renda passiva. Pela descrição, é o caso mais óbvio de widget puro do portfólio inteiro. Ele usa Flame — e olhando em retrospecto, é o candidato mais forte a ter entrado em Flame por precaução, que é justamente o erro descrito no fim deste post.
Onde Flame ganha, e ganha muito
Quando o estado muda por frame, escrever à mão significa reimplementar quatro coisas:
- 1. Laço de jogo com delta de tempo. Um
AnimationControllerdá o gatilho por
frame, mas você ainda precisa de um modelo de atualização com tempo decorrido, senão a velocidade muda conforme o aparelho.
- 2. Árvore de componentes com ciclo de vida. Objetos que nascem, atualizam,
colidem e morrem. Sem estrutura, isso vira uma lista com condicionais.
- 3. Detecção de colisão. É o item que mais parece simples e mais consome
tempo. Colisão contínua com muitos objetos não é um if de retângulo.
- 4. Câmera e coordenadas do mundo. Separar sistema de coordenadas do mundo do
sistema de coordenadas da tela é o que permite câmera, zoom e paralaxe.
Fazer os quatro à mão é escrever Flame com menos horas de teste.
O Chihuahua Fly cai nesse lado: voo contínuo, obstáculos que se aproximam, chefes, colisão o tempo todo. Não há versão razoável disso em widget puro.
O modelo mental que funciona
A confusão vem de tratar Flame como alternativa ao Flutter. Ele não é — GameWidget é um widget.
MaterialApp
├─ MenuPage (Flutter normal)
├─ LojaPage (Flutter normal)
└─ PartidaPage
└─ GameWidget (Flame comeca aqui)
└─ HUD (pode voltar a ser Flutter por cima)
Isso resolve a falsa escolha. Você não decide para o aplicativo inteiro; decide para a tela de partida. Menu, configuração, loja e ranking continuam sendo Flutter em qualquer cenário — e são a maior parte das telas.
Quando nem Flame basta
Existe um terceiro degrau, e ele é sobre ferramenta, não sobre desenho.
Quando o jogo precisa de física com corpos e materiais, tilemap, editor de cena e um fluxo de criação de fases feito por quem não programa, a conversa muda. Aí o que falta não é uma biblioteca de renderização: é um ambiente de autoria.
Foi por isso que um dos nossos jogos foi construído fora do Flutter — assunto que rende post próprio.
O critério aqui também é curto:
Alguém vai desenhar fases neste jogo?
Se sim, você precisa de editor. Fase escrita em código é sustentável até a terceira; da décima em diante é sofrimento.
O erro que a gente cometeu
Vale registrar, porque é o mais comum: começar com Flame por precaução.
O raciocínio parece prudente — "e se depois precisar de movimento?". Na prática, o custo aparece antes do benefício: você entra num sistema de coordenadas próprio, perde layout responsivo, e reimplementa botão e lista dentro do canvas para uma necessidade que talvez nunca chegue.
O caminho barato é o contrário. Comece em widget e mova para Flame a tela de partida, se ela precisar. A migração é local, porque só aquela tela muda.
Resumo
- A pergunta é se o estado muda por frame ou por evento. Todo o resto decorre.
- Por evento: widget puro. Ganha layout responsivo, acessibilidade, ferramentas
e um sistema só.
- Por frame: Flame. Evita reimplementar laço com delta de tempo, ciclo de vida,
colisão e câmera.
- Flame é um widget, não um substituto do Flutter. A decisão é por tela.
- Se alguém vai desenhar fases, o que falta é editor — e aí a conversa é sobre
motor completo.
- Não adote motor por precaução. Comece simples e mova só a tela de partida.
Perguntas frequentes
Flame substitui o Flutter?
Não. Flame roda dentro do Flutter, num widget. Isso é a maior vantagem dele: o menu, a loja e as telas de configuração continuam sendo Flutter normal, com os widgets que você já sabe usar.
Dá para fazer jogo só com AnimationController?
Dá, e é a escolha certa para jogo de turno, puzzle e cartas — o que muda só quando alguém toca. Cuidado com o rótulo 'idle': ele descreve a progressão, não a tela. Auto-battler idle tem combate animado com muitos objetos, e isso é laço por frame como qualquer outro.
Quando Flame começa a valer?
Quando você precisa de atualização por frame com muitos objetos, detecção de colisão contínua ou controle fino de câmera. Se o seu jogo tem essas três coisas, escrever à mão é reimplementar Flame pior.
E quando nem Flame resolve?
Quando o jogo precisa de física, tilemap, editor de cena e ferramenta de nível. Aí a conversa não é sobre biblioteca, é sobre motor completo — e vale sair do Flutter.