Como Fazer um Jogo Deck Builder: do Design às Cartas no Godot

Aprenda como fazer um jogo deck builder: o que define o gênero, as três pilhas, cartas como Resource no Godot 4, loop roguelike da run e balanceamento.
Se você quer aprender como fazer um jogo deck builder, está mirando em um dos gêneros mais generosos para quem desenvolve sozinho. Slay the Spire e Balatro provaram que um jogo de cartas com sistemas profundos e arte contida pode competir de igual para igual com produções gigantes. Neste guia você vai entender o que define o gênero, por que ele cabe no escopo de um dev solo, como funcionam as três pilhas e o loop de turno, e como modelar cartas, deck e efeitos no Godot 4 com GDScript tipado. No final, os princípios de balanceamento que separam um deck builder viciante de um que o jogador resolve em duas partidas.
O que define um deck builder de verdade
A confusão mais comum é misturar deck builder com jogo de cartas colecionável. Nos dois existem cartas, custos e efeitos, mas a experiência é oposta.
No colecionável, estilo Magic ou Hearthstone, você monta o baralho antes da partida, usando uma coleção acumulada ao longo de meses. A construção acontece fora do jogo; a partida é só a execução do plano.
No deck builder, a construção do baralho acontece durante a partida. Você começa cada run com um deck inicial fraco e idêntico ao de qualquer outro jogador: algumas cartas de ataque básico, algumas de defesa, talvez uma curinga. A cada combate vencido, o jogo oferece cartas novas e você decide o que entra. O baralho que termina a run não existia quando ela começou. Ele é o registro das suas decisões.
Essa diferença muda tudo no design. Não existe coleção, booster nem economia de raridade fora da partida. Existe uma sequência de escolhas sob pressão: aceito esta carta que é boa agora mas polui o deck depois? O jogo é sobre avaliar valor em contexto, e o contexto muda a cada run. Para situar o deck builder no mapa maior e entender de quais famílias ele herda mecânicas, o panorama de gêneros de jogos explicados ajuda a enxergar essas fronteiras.
Por que é um dos melhores gêneros para dev solo
Três razões práticas, sem romantismo.
O escopo é controlável. Um deck builder mínimo precisa de: um sistema de cartas, um combate por turnos, um punhado de inimigos e um mapa de run. Nada disso exige física, mundo aberto, IA complexa ou netcode. O multiplayer, que dobra o custo de qualquer projeto, não faz parte do gênero na forma clássica. Slay the Spire e Balatro são single player, e ninguém sente falta.
A arte é barata em relação ao impacto. Uma carta é uma ilustração estática dentro de uma moldura. Compare com o custo de um personagem jogável: modelagem ou spritesheet, animação de idle, corrida, ataque, dano, morte. Uma tarde de trabalho rende uma carta finalizada; a mesma tarde rende uma fração de um personagem animado. Balatro foi além: usou o baralho de pôquer, arte que todo mundo já conhece, e concentrou a identidade visual nos curingas e no shader de fundo.
A profundidade vem das combinações, não do volume. Em um jogo de plataforma, mais conteúdo significa mais fases construídas à mão. Em um deck builder, cada carta nova interage com todas as anteriores. Vinte cartas bem desenhadas geram um espaço de decisão que o jogador leva dezenas de horas para esgotar, porque o que importa não é a carta isolada, é o deck que ela viabiliza. Você programa sistemas uma vez e o conteúdo se multiplica sozinho.
As três pilhas e o loop de turno
Todo deck builder de combate gira em torno de três coleções de cartas.
A pilha de compra (draw pile) guarda, viradas para baixo, as cartas que ainda vão entrar no turno. A mão guarda as cartas jogáveis agora. A pilha de descarte recebe cada carta usada ou descartada no fim do turno.
O loop de turno clássico é assim:
- Início do turno: o jogador compra um número fixo de cartas da pilha de compra, tipicamente cinco, e recebe sua energia, tipicamente três.
- Fase de jogo: ele joga quantas cartas conseguir pagar com energia, na ordem que quiser. Cada carta jogada vai para o descarte.
- Fim do turno: as cartas que sobraram na mão também vão para o descarte.
- Turno do inimigo: os inimigos executam as intenções anunciadas, e o ciclo recomeça.
O detalhe que sustenta o gênero inteiro: quando a pilha de compra esvazia, o descarte é embaralhado e vira a nova pilha de compra. Isso garante que todo o deck circule. É por isso que adicionar carta ruim tem custo real (ela vai voltar para a sua mão) e remover cartas é recompensa valiosa: deck menor significa ver as melhores cartas com mais frequência.
Se você ainda não tem a base visual de cartas na tela, com mão em leque, arrastar e soltar e instâncias de cena por carta, o tutorial de como fazer um jogo de cartas no Godot constrói exatamente essa fundação de UI e interação. Aqui vamos focar na camada de dados e nas regras que ficam por baixo dela.
Como fazer um jogo deck builder no Godot 4: a carta como Resource
No Godot 4, a decisão de arquitetura mais importante é tratar a carta como dado, não como node. Uma carta não processa frames nem tem posição no mundo: ela tem nome, custo e efeito. Isso é a definição de um Resource customizado.
# card.gd
# A carta e dado puro, por isso estende Resource e nao Node.
class_name Card
extends Resource
enum EffectType {
DAMAGE, # causa dano no alvo
BLOCK, # gera bloqueio para o jogador
DRAW, # compra cartas adicionais
ENERGY, # gera energia extra neste turno
}
@export var card_name: String = "Nova Carta"
@export var cost: int = 1
@export var effect: EffectType = EffectType.DAMAGE
@export var amount: int = 6
@export_multiline var text: String = ""
@export var art: Texture2D
Com esse script salvo, cada carta vira um arquivo .tres criado pelo Inspector: botão direito no FileSystem, novo Resource, tipo Card, preencher os campos. Um "Golpe" é DAMAGE com amount 6 e custo 1. Um "Defender" é BLOCK com amount 5. Você cria trinta cartas sem escrever código novo.
O deck e as três pilhas são Arrays tipados de Card. O gerenciador abaixo implementa o ciclo completo: embaralhar, comprar, descartar e reembaralhar.
# deck_manager.gd
class_name DeckManager
extends Node
const HAND_SIZE: int = 5
# O deck da run: persiste entre combates e cresce nas recompensas.
var run_deck: Array[Card] = []
# As tres pilhas do combate atual.
var draw_pile: Array[Card] = []
var hand: Array[Card] = []
var discard_pile: Array[Card] = []
func start_battle() -> void:
# Copia o deck da run para nao destruir a lista original.
draw_pile = run_deck.duplicate()
draw_pile.shuffle()
hand.clear()
discard_pile.clear()
func draw_card() -> void:
if draw_pile.is_empty():
_reshuffle_discard_into_draw()
if draw_pile.is_empty():
return # deck inteiro esta na mao, nada a comprar
var card: Card = draw_pile.pop_back()
hand.append(card)
func draw_new_hand() -> void:
for i: int in HAND_SIZE:
draw_card()
func discard_hand() -> void:
discard_pile.append_array(hand)
hand.clear()
func _reshuffle_discard_into_draw() -> void:
draw_pile = discard_pile.duplicate()
discard_pile.clear()
draw_pile.shuffle()
Repare em dois detalhes. shuffle() e pop_back() são métodos nativos de Array: embaralhar a pilha e puxar a carta do topo custa uma linha cada. E run_deck vive separado das pilhas de combate: é ele que cresce quando o jogador escolhe recompensas, enquanto draw_pile nasce como cópia dele a cada batalha.
Resolvendo efeitos sem um if gigante
Com a carta como dado e as pilhas funcionando, falta a pergunta central: o que acontece quando o jogador joga uma carta? Para um protótipo e até para um jogo comercial enxuto, um enum com match resolve com clareza.
# battle.gd (trecho da cena de combate)
var energy: int = 3
var player_block: int = 0
@onready var deck: DeckManager = $DeckManager
func play_card(card: Card, target: Enemy) -> void:
if card.cost > energy:
return # a UI deve impedir, mas a regra vive aqui
energy -= card.cost
match card.effect:
Card.EffectType.DAMAGE:
target.take_damage(card.amount)
Card.EffectType.BLOCK:
player_block += card.amount
Card.EffectType.DRAW:
for i: int in card.amount:
deck.draw_card()
Card.EffectType.ENERGY:
energy += card.amount
deck.hand.erase(card)
deck.discard_pile.append(card)
Quando surgirem cartas com efeitos compostos, tipo "cause 4 de dano e compre 1 carta", há dois caminhos de evolução. O primeiro: trocar o campo único por uma lista de efeitos, um Array de pequenos Resources que o combate resolve em sequência. O segundo é o método virtual: cada carta especial vira uma subclasse de Card que sobrescreve um func apply(battle: Battle) -> void, e o match desaparece. Comece pelo enum e só pague a complexidade extra quando o design pedir.
O loop roguelike da run
O combate é o coração, mas o que transforma cartas soltas em um deck builder é a run. O jogador atravessa um mapa de nós com caminhos ramificados, e cada nó é um encontro: combate normal, elite, evento, loja, fogueira, chefe.
O ciclo que importa é: combate, vitória, recompensa. A recompensa clássica oferece três cartas e o jogador escolhe uma ou pula. É aí que o deck é construído, e aí mora a decisão mais interessante do gênero: a carta boa em abstrato pode ser ruim para este deck, nesta run, contra o chefe deste ato.
Em código, essa camada é mais simples do que parece: o mapa é um grafo gerado proceduralmente, o estado da run é um punhado de variáveis (vida atual, ouro, run_deck, relíquias) e cada nó é uma cena que recebe esse estado e o devolve modificado. Esse esqueleto de geração procedural, encontros encadeados e morte permanente é o mesmo de qualquer jogo do gênero, e o guia de como fazer um roguelike cobre essa camada em detalhe.
O ponto de design que une as duas camadas: em um deck builder, a recompensa do roguelike é conteúdo de sistema, não de mundo. Você não desenha uma fase nova para recompensar o jogador, você oferece uma carta que já existe no pool. Por isso o gênero escala tão bem para uma pessoa só.
Balanceamento: custo, sinergia e a carta lixo
Balancear deck builder não é fazer todas as cartas igualmente boas. É fazer todas as decisões interessantes. Alguns princípios práticos:
Ancore tudo em uma taxa de conversão base. Defina quanto vale 1 de energia em dano e em bloqueio. Se o ataque básico custa 1 e causa 6, então 1 energia vale cerca de 6 de dano. Toda carta nova é medida contra essa régua: entrega mais valor bruto, precisa carregar condição, risco ou exigência de deck; entrega menos, precisa oferecer flexibilidade ou sinergia. Réguas numéricas, curvas de custo e fórmulas de dano estão destrinchadas no guia de balanceamento de jogos com fórmulas e técnicas.
Sinergia vale mais que poder isolado. A carta memorável raramente é a de número maior. É a que transforma outras: "bloqueio não expira", "toda carta de compra causa 2 de dano", "a primeira carta do turno custa 0". Cartas assim criam arquétipos, e arquétipos criam a vontade de jogar de novo para tentar a build que não fechou. Desenhe grupos de cartas que conversam entre si, não uma lista de itens independentes.
A carta lixo é uma decisão de design, não um acidente. Se toda oferta de recompensa fosse boa, escolher seria trivial e pular nunca faria sentido. Cartas medianas e situacionais existem para dar peso à recusa: manter o deck enxuto é uma estratégia, e ela só existe se adicionar carta tiver custo. O cuidado é com a carta armadilha, aquela que parece boa e é objetivamente ruim sem que o jogador tenha como aprender o porquê. Frustração sem lição é só frustração.
Balanceie a curva, não só a carta. Um deck com dez cartas de custo 3 trava com 3 de energia por turno. Cabe ao jogador montar uma curva de custos jogável, e cabe a você garantir opções baratas suficientes no pool para isso ser possível em qualquer arquétipo.
Por onde começar na prática
Um caminho de escopo honesto para o primeiro protótipo: implemente Card como Resource e o DeckManager com as três pilhas. Faça um único combate contra um inimigo de padrão fixo, com 10 a 15 cartas entre ataque, defesa e compra. Quando esse combate estiver divertido cru, adicione a tela de recompensa, depois encadeie três combates e um chefe. Mapa ramificado, eventos e relíquias vêm por último: tudo isso só amplifica um núcleo que precisa funcionar sozinho.
Deck builder é o raro gênero em que a versão feia já diz a verdade: se decidir o que jogar com 3 de energia não gera tensão com retângulos cinzas na tela, arte não vai salvar. Se gera, você tem um jogo. Construa o loop, jogue até enjoar e deixe as combinações fazerem o trabalho pesado.
Para arrastar cartas com o mouse na mesa, veja como implementar arrastar e soltar no Godot.
Perguntas frequentes
O que diferencia um deck builder de um jogo de cartas colecionável?
No colecionável você monta o baralho antes da partida, com uma coleção que acumulou fora dela. No deck builder você começa cada partida com um baralho fraco e padronizado e o constrói durante o jogo, escolhendo cartas nas recompensas. A construção do deck é a mecânica central, não uma etapa de preparação.
Por que deck builder é um bom gênero para dev solo?
Porque o escopo é controlável e a profundidade vem das combinações, não do volume de conteúdo caro. Arte de carta é uma ilustração estática, muito mais barata que animar personagens. Não há netcode, e cada carta nova multiplica as sinergias possíveis em vez de só somar mais um item.
Como representar uma carta no Godot 4?
Com um Resource customizado. A carta é dado puro: nome, custo, tipo de efeito e valor. Um script com class_name Card extends Resource e campos @export permite criar cada carta como arquivo .tres pelo Inspector, sem código novo. O deck vira um Array[Card] tipado.
Como funcionam as três pilhas de um deck builder?
A pilha de compra guarda as cartas que ainda vão entrar, a mão guarda as jogáveis no turno e o descarte recebe as usadas. Quando a pilha de compra esvazia, o descarte é embaralhado de volta para ela. Esse ciclo garante que todas as cartas do deck circulem durante o combate.
Preciso de muitas cartas para o jogo ficar profundo?
Não. Slay the Spire lançou com pouco mais de duzentas cartas somando personagens, e a profundidade vem das combinações entre elas, não da quantidade. Um protótipo com 20 a 30 cartas bem desenhadas, com sinergias claras entre elas, já demonstra o loop completo do gênero.
Carta ruim no pool é erro de design?
Não necessariamente. Em deck builders, recusar uma carta é uma decisão tão importante quanto aceitar. Cartas fracas ou situacionais criam o dilema de manter o deck enxuto versus ganhar opções, e ensinam o jogador a avaliar valor. O erro é a carta ser ruim sem o jogador ter como perceber.


