Neste post
  1. O critério, aplicado
  2. O que o nosso portfólio realmente mostra
  3. Por que os idle acabaram em Flame
  4. Onde widget puro ganha, e ganha fácil
  5. Onde Flame ganha, e ganha muito
  6. O modelo mental que funciona
  7. Quando nem Flame basta
  8. O erro que a gente cometeu
  9. Resumo

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:

JogoGêneroRenderização
Chihuahua Flyarcade endless flyerFlame
GodforgeRPG idle / auto-battlerFlame
Zombountyidle autobattlerFlame
Mewtopia Mergemerge idleFlame
Villa Auroranovela com minigamesFlame
Kombateestratégia de tabuleirowidget puro
Troll Quest BRplatformerfora 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. 1. Laço de jogo com delta de tempo. Um AnimationController dá 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.

  1. 2. Árvore de componentes com ciclo de vida. Objetos que nascem, atualizam,

colidem e morrem. Sem estrutura, isso vira uma lista com condicionais.

  1. 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.

  1. 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.