DEV Community

Cover image for [PT-BR] Gatonauta: Experiência do GameDev.tv GameJam 2025
StealthC
StealthC

Posted on

[PT-BR] Gatonauta: Experiência do GameDev.tv GameJam 2025

Tradução: This post is also available in English

Decidi participar da game jam da GameDev.tv (GameDev.tv Game Jam 2025 - Free Course For All Submissions! - itch.io), que é uma ótima opção para quem está começando no desenvolvimento de jogos. A comunidade é bem acolhedora, formada principalmente por alunos e iniciantes, e a troca de feedbacks é muito ativa e construtiva. Além disso, todo participante que enviar um jogo, automaticamente ganha um curso deles, que é algo muito bom pra quem está começando!

Essa é uma jam de 10 dias, e o tema escolhido foi “Tiny World”. No ano passado, participei com um jogo chamado Gataria by StealthC, feito para o tema “Last Stand”, e recebi muitos feedbacks positivos. Eu já sabia que queria fazer mais um jogo com um gato como protagonista, e, assim que o tema saiu, comecei a pensar em como encaixar essa ideia.

Dessa vez, decidi me arriscar com um escopo bem maior que Gataria, mesmo sabendo que corria o risco de não conseguir finalizar a tempo. Afinal, boa parte dos 10 dias eram dias úteis, e eu também precisava conciliar com meu trabalho.


Escolha de ferramentas e escopo inicial...

Minha proposta era criar um jogo de sobrevivência, exploração e crafting, com bastante inspiração em jogos como Factorio e Forager. Além disso, queria implementar uma mecânica de gravidade em pequenos planetas, no estilo Super Mario Galaxy, mas adaptado para um jogo 2D.

Decidi usar o Godot Engine (arrisquei e fiz todo na versão beta 4.5 dev3), que é uma ferramenta que já conheço bem e que me permite desenvolver jogos de forma rápida e eficiente. Suas builds para Web são ótimas e leves, perfeitas para game jams, e a comunidade é bem ativa, o que facilita encontrar soluções para problemas comuns.

Uma das coisas que eu não tinha feito antes, mas dessa vez decidi implementar, foi preparar uma CI (integração contínua) para o projeto, usando o GitHub. Assim, a cada commit que eu fizesse na branch main, o jogo seria compilado e disponibilizado automaticamente no Itch.io. Isso me ajudou a manter o controle do progresso, fazer outras pessoas testarem e identificar bugs mais rapidamente.

O workflow ficou assim (Se você quiser usar este workflow, lembre-se de adaptar as chaves e ajustar a versão do Godot conforme o seu projeto):

name: Export and Upload to Itch.io

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Export Godot project
        id: export
        uses: firebelley/[email protected]
        with:
          godot_executable_download_url: https://github.com/godotengine/godot-builds/releases/download/4.5-dev4/Godot_v4.5-dev4_linux.x86_64.zip
          godot_export_templates_download_url: https://github.com/godotengine/godot-builds/releases/download/4.5-dev4/Godot_v4.5-dev4_export_templates.tpz
          relative_project_path: ./
          archive_output: true
          cache: true

      - name: Upload to Itch.io
        uses: Ayowel/butler-to-itch@v1
        with:
          butler_key: ${{ secrets.ITCHIO_API_KEY }}
          itch_user: MEU_USUARIO_ITCHIO
          itch_game: NOME_DO_JOGO_ITCHIO
          version: ${{ github.ref_name }}
          files: ${{ steps.export.outputs.archive_directory }}/Web.zip

Enter fullscreen mode Exit fullscreen mode

Um conceito bem ambicioso...

O meu conceito inicial já deixava claro que não seria uma tarefa fácil. Eu queria que o jogo tivesse:

  • Um sistema de sobrevivência, com fome e gerenciamento de recursos.

  • Combate e elementos de ação.

  • Dungeons, para exploração e desafios extras.

  • Um gancho, para se prender em asteroides ou puxar objetos até o personagem.

  • Internacionalização, para que o jogo pudesse ser jogado em português e inglês.

Com esse escopo, uma partida poderia demorar bastante. Então, seria necessário ter um sistema de salvamento. Comecei criando esse sistema, que me tomou praticamente o primeiro dia inteiro, além de dedicar tempo ao planejamento da estrutura geral do jogo.

Aqui vai meu sketch inicial do projeto e a versão gerada por IA:

Image description

Image description


Recriando toda a teoria da gravidade...

No segundo dia, parti para um dos maiores desafios técnicos: fazer um sistema de movimentação com gravidade em planetoides. A ideia parecia simples na teoria: basta fazer a gravidade sempre apontar para o centro do planeta. Na prática... foi bem mais trabalhoso do que parecia.

A solução que encontrei foi calcular todos os movimentos (andar, pular, gravidade) como se estivessem num plano cartesiano normal. Só no final dos cálculos é que eu rotacionava o movimento, alinhando para que ele ficasse na direção correta em relação ao planeta. Na minha opinião, ficou bem suave e intuitivo.

if is_on_floor():
    _local_velocity.x = input_x * current_planet.side_velocity
else:
    _local_velocity.x = lerp(_local_velocity.x, input_x * current_planet.side_velocity / 2.0, 0.1) # Suaviza o movimento lateral no ar
...

var gravity_center = current_planet.global_position
var direction_to_center = (gravity_center - global_position).normalized()

...

var target_rotation = direction_to_center.angle() - PI / 2.0 # -PI/2 para alinhar com a direção do planeta

...

var local_rotated = _local_velocity.rotated(target_rotation).normalized() * abs(_local_velocity.x) # Aplica a rotação do jogador à velocidade local
velocity = local_rotated # Atualiza a velocidade do jogador com a velocidade local rotacionada
velocity += _gravity_velocity.rotated(target_rotation) # Aplica a velocidade da gravidade
velocity += _jetpack_velocity.rotated(global_rotation) # Aplica a velocidade do jetpack rotacionada pela rotação do jogador
move_and_slide()
Enter fullscreen mode Exit fullscreen mode

No jogo há basicamente dois modos de física:

  1. Dentro de um planeta, onde é calculado a gravidade, movimentos laterais e etc.

  2. No espaço, onde a câmera fica fixa, a gravidade é desligada, mas agora você pode girar o personagem e impulsioná-lo na direção que ele está.

Claro que surgiram problemas no caminho. Nas builds Web, por exemplo, a física começava a apresentar erros, provavelmente por conta da perda de precisão dos floats. Depois de muito quebrar a cabeça, descobri que usar colisão quadrada no personagem e circular no planeta resolvia vários desses problemas. Se o personagem usasse uma colisão do tipo cápsula ou redonda, acontecia um bug estranho: ele se movia mais rápido para um lado do que para o outro, e esse erro ia acumulando aos poucos, ficando cada vez pior.


A corrida contra o tempo e uso de IA

Nos cinco dias seguintes, minha rotina foi basicamente trabalhar o dia todo e só conseguir mexer no jogo bem tarde da noite, quando já estava exausto e com a cabeça pouco produtiva. Por isso, optei por focar na criação dos assets: sprites, planetas, itens, sons, músicas e afins.

E é aqui que entro em um tema meio polêmico: o uso de inteligência artificial na criação de assets para jogos.

Sem dúvida, esse é um assunto que gera bastante discussão na comunidade de desenvolvimento, e com razão. A IA se tornou uma ferramenta extremamente poderosa, principalmente para quem trabalha sozinho ou em equipes pequenas, como é o caso de muita gente em game jams. Quando o tempo é apertado e nem sempre temos habilidades em todas as áreas, como arte, música ou efeitos sonoros, ela acaba sendo uma aliada bem interessante.

No meu caso, eu não sou artista profissional. Produzir todos os assets do zero: sprites, efeitos sonoros, músicas, interfaces... dentro de poucos dias simplesmente, não seria viável. Então sim, recorri a ferramentas de IA para acelerar parte desse processo.

Mas acho essencial refletir sobre como e por que usar IA. Ela não deve ser encarada como um substituto da criatividade humana, pelo menos não nesse momento, mas sim como uma extensão dela. Usei IA para transformar ideias que eu já tinha em algo mais concreto, como rascunhos visuais, texturas e até sons. Mas, na prática, quase tudo exigiu bastante trabalho manual: ajustar, editar, retrabalhar e encaixar no estilo e na proposta do jogo.

A IA, nesse contexto, acaba sendo apenas mais uma ferramenta, assim como é, por exemplo, um gerador de efeitos sonoros como o jsfxr - 8 bit sound maker, que também usei no projeto. Ela resolve um problema prático, permitindo que uma ideia se transforme em algo jogável, sem que você trave nas partes onde não domina 100%.

Claro que eu também entendo, e concordo em vários pontos, com quem traz críticas. Existem preocupações bem válidas sobre como os modelos são treinados, muitas vezes usando trabalhos de artistas sem consentimento, e sobre como isso pode afetar o mercado criativo e desvalorizar o trabalho de profissionais.

Na minha opinião, boa parte dos problemas que vemos hoje não são causados exatamente pela IA em si, mas pela forma como todo o sistema foi estruturado. A concentração de tecnologia nas mãos de poucos, todo o modelo de negócios usado, tudo isso faz parte do problema. E esse debate, honestamente, vai muito além da tecnologia em si.

No contexto de uma game jam, que é um ambiente de aprendizado, prototipagem e experimentação, vejo o uso da IA como algo totalmente válido, desde que usado de forma consciente, honesta e transparente. Inclusive, isso é abordado nas próprias regras dessa jam específica.

Mas acho que, como desenvolvedores, é nosso papel continuar questionando e discutindo como construir um cenário onde essas ferramentas possam existir de forma mais justa, ética e equilibrada, beneficiando a todos, desde quem cria, quem desenvolve e quem joga.

Image description


O desenvolvimento do Gatonauta: Problemas de Prazo

Voltando ao desenvolvimento, nesse tempo eu criei os primeiros assets de planetas, do personagem, de alguns itens e recursos, mas nada ainda estava funcional. Foi só lá pelo sétimo dia que finalmente consegui concluir partes mais importantes, como o sistema de inventário e a coleta de recursos. Nesse tempo, eu já havia riscado várias partes do meu escopo inicial:

  • Survival: No caso do meu conceito, survival seria só mais uma camada do jogo. Se a base nem está completa, essa camada mais atrapalharia do que ajudaria.
  • Combate: infelizmente, fazer sistemas de combate com tão pouco tempo livre não iria rolar. Fica para a próxima.
  • Gancho: isso foi riscado com toda a parte de mineração no espaço, mas seria muito legal de ter.
  • Diálogos: cheguei a pensar em toda uma história envolvendo o Gatonauta e seu assistente, o GatoGPT (que é esse drone que fica destruindo as coisas).
  • Dungeons: outro plano riscado por falta de tempo.

Me concentrei em fazer o básico funcionar: movimentação, coleta de recursos, crafting e construção. E, claro, a parte de exploração com os planetas. Só que precisaria, pelo menos, ter um gameplay completo. Então decidi focar em um único objetivo simples: consertar a nave. Para isso, o jogador precisaria obter três peças diferentes. Planejei a receita dessas peças e os passos para obtê-las. Não quis deixar muito complexo, mas algo que fosse viável e divertido para a maioria dos jogadores, sem muito grind.

Tentei ao máximo abstrair e usar os signals do Godot para poder reutilizar as classes e fazer o jogo ser facilmente expansível, na prática, se eu quisesse criar mais recursos, nodes, ou estruturas, era só criar instâncias dos objetos existentes, com os novos dados e texturas.

Todas as receitas, crafting e upgrades usam dicionários simples para definição, algumas vezes, uso um tipo especial de objeto para as receitas, mas continua sendo baseado em dicionários:

## Dicionário de custos das estruturas
const STRUCTURE_COST: Dictionary[String, Dictionary] = {
    "FURNACE": {
        "COBBLESTONE": 10
    },
    "STORAGE": {
        "COBBLESTONE": 5,
        "WOOD": 5,
        "CHARCOAL": 5
    },
    "WORKBENCH": {
        "COBBLESTONE": 10,
        "WOOD": 5,
        "GEAR": 2
    },
    "3D_PRINTER": {
        "BAR": 10,
        "CHARCOAL": 5,
        "GEAR": 30
    },
}

## Dicionário de prefabs das estruturas
const STRUCTURE_PREFAB: Dictionary[String, PackedScene] = {
    "FURNACE": preload("res://scenes/structures/furnace.tscn"),
    "3D_PRINTER": preload("res://scenes/structures/3d_printer.tscn"),
}

const STRUCTURE_RECIPES: Dictionary[String, Array] = {
    "FURNACE": [
        preload("res://scripts/data/recipes/charcoal.tres"),
        preload("res://scripts/data/recipes/bar.tres")
    ],
    "DAMAGED_SHIP": [
        preload("res://scripts/data/recipes/fix-ship.tres"),
    ],
    "3D_PRINTER": [
        preload("res://scripts/data/recipes/ship-piece-1.tres"),
        preload("res://scripts/data/recipes/ship-piece-2.tres"),
        preload("res://scripts/data/recipes/ship-piece-3.tres"),
    ]
}

const UPGRADES_RECIPES: Dictionary[String, Dictionary] = {
    "FIX_JETPACK": {
        "GEAR": 5
    },
    "PLANETOID_INDICATOR": {
        "WOOD": 5,
        "COBBLESTONE": 5,
        "CHARCOAL": 10,
    },
    "BETTER_JETPACK": {
        "CHARCOAL": 10,
        "COBBLESTONE": 10,
    },
    "FASTER_HARVEST": {
        "WOOD": 15,
        "COBBLESTONE": 15,
        "GEAR": 25
    },
    "MORE_RESOURCES": {
        "ORE": 20,
        "GEAR": 15
    }
}

Enter fullscreen mode Exit fullscreen mode

Eu gostaria de ter polido mais a UI, mas percebi que, a cada nova feature, eu demorava muito para finalizar. Isso deixou clara minha falta de experiência com a UI do Godot. Então decidi deixar a UI mais simples, mas funcional. Nada de ícones ou efeitos, só texto. A ideia era que o jogador conseguisse entender o que fazer e como fazer, mesmo que não fosse tão bonito.

Gastei o nono dia testando e resolvendo bugs, preparei uma tela de créditos e finalizei o jogo. No décimo dia, eu tinha trabalho, então só consegui ajustar pequenos bugs que escaparam.


Conclusão

Participar dessa jam foi, sem dúvidas, uma experiência incrível. Além de aprender muita coisa nova, pude testar ideias que estavam na gaveta há tempos, como o sistema de gravidade em planetas, integração contínua e até experimentar o uso de IA de forma mais consistente no desenvolvimento.

O Gatonauta ficou longe de tudo que sonhei no início, mas isso não é necessariamente algo ruim. Faz parte do processo entender os próprios limites, ajustar o escopo e transformar uma ideia gigante em algo que, pelo menos, funcione, seja divertido e transmita uma proposta.

Com certeza saio dessa jam com ainda mais vontade de continuar desenvolvendo, melhorar meus processos, entender melhor meus pontos fortes e, principalmente, meus pontos fracos.

Se você leu até aqui, muito obrigado. Espero que esse relato tenha te inspirado, ajudado ou, quem sabe, te dado aquele empurrãozinho para participar da sua primeira (ou próxima) game jam.

E se quiser jogar o jogo, ele está disponível em:
Gatonauta by StealthC

Image description

Top comments (0)