Translation: Este artigo também está disponível em Português
I decided to join the GameDev.tv game jam (GameDev.tv Game Jam 2025 - Free Course For All Submissions! - itch.io), which is a great choice for anyone getting started with game development. The community is very welcoming, mostly made up of students and beginners, and there's a lot of active and constructive feedback exchange. Also, everyone who submits a game gets a free course, which is an amazing perk if you’re just starting out!
This is a 10-day jam, and the chosen theme was "Tiny World". Last year, I joined with a game called Gataria by StealthC, made for the theme "Last Stand", and it got a lot of positive feedback. I already knew I wanted to make another game with a cat protagonist, and as soon as the theme was announced, I started thinking about how to make it fit.
This time, I decided to go big. Way bigger than Gataria. I knew I was risking not finishing in time, especially since most of the 10 days were weekdays and I had to balance it with my regular job.
Choosing Tools and Initial Scope...
My idea was to make a game focused on survival, exploration, and crafting, heavily inspired by games like Factorio and Forager. I also wanted to implement a gravity mechanic on small planets, something like Super Mario Galaxy, but in 2D.
I chose to use Godot Engine (went all in with the beta version 4.5 dev3), which I know pretty well and lets me develop quickly. Its Web builds are lightweight and perfect for game jams, and the community is super active, which helps a lot when solving problems.
One thing I hadn’t done before, but decided to try this time, was setting up a CI pipeline using GitHub. That way, every time I pushed to the main branch, the game would be automatically built and uploaded to Itch.io. It helped me track progress, get testers earlier, and catch bugs faster.
Here’s the workflow I used (if you want to try it yourself, remember to adapt the keys and the Godot version to your own project):
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: YOUR_ITCHIO_USERNAME
itch_game: YOUR_GAME_NAME
version: ${{ github.ref_name }}
files: ${{ steps.export.outputs.archive_directory }}/Web.zip
A Pretty Ambitious Concept...
From the start, it was clear the scope would be a challenge. I wanted the game to include:
- A survival system, with hunger and resource management
- Combat and action elements
- Dungeons, for exploration and extra challenges
- A grappling hook, to attach to asteroids or pull objects
- Localization, so it could be played in English and Portuguese
With that scope, a playthrough would take a while. So a save system was a must. I started building that first, which took me almost an entire day, plus time to plan the overall structure of the game.
Here’s my initial sketch and the AI-generated version:
Reinventing Gravity From Scratch...
On day two, I tackled one of the biggest technical challenges: movement with gravity on planetoids. It sounded easy in theory: just make gravity point toward the planet’s center. In practice... not that simple.
The solution I found was to calculate all movement (walking, jumping, gravity) as if it were a regular 2D Cartesian plane. Only at the end did I rotate the final movement vector to align it with the planet’s surface. It ended up feeling pretty smooth and intuitive.
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) # Smooth air control
...
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
...
var local_rotated = _local_velocity.rotated(target_rotation).normalized() * abs(_local_velocity.x)
velocity = local_rotated
velocity += _gravity_velocity.rotated(target_rotation)
velocity += _jetpack_velocity.rotated(global_rotation)
move_and_slide()
The game has two basic physics modes:
- On planets: with gravity and lateral movement
- In space: no gravity, fixed camera, and free rotation + propulsion
Of course, problems came up. In Web builds, physics started acting weird: probably due to floating point precision loss. After a lot of trial and error, I found that using square collision for the player and circle collision for planets fixed a bunch of it. Using capsules or circles for the player caused a strange bug: moving faster to one side, which got worse over time.
Racing Against Time and Using AI
For the next five days, I spent my daytime working, and only had time to work on the game late at night, usually already exhausted and not thinking straight. So I focused on building assets: sprites, planets, items, sounds, music, etc.
And that’s when I hit a hot topic: using AI to create assets.
Yeah, it’s a controversial subject in game dev, and for good reason. AI tools have become really powerful, especially for solo devs or small teams, which is basically the case in most game jams. When time is short and you don’t have all the skills needed (art, sound, music...), AI can be a huge help.
I’m not a professional artist. Creating all assets from scratch: sprites, sound effects, music, UI... just wouldn’t be realistic in a few days. So yes, I used AI tools to speed things up.
But I believe it’s important to think about how and why we use AI. It shouldn’t replace human creativity (at least not right now), but extend it. I used it to bring my ideas to life: rough sketches, textures, sounds. Almost everything needed editing, rework, adjustments to fit the game’s style.
In that sense, AI is just another tool, like a sound effect generator, for example, jsfxr - 8 bit sound maker, which I also used. It helps turn ideas into something playable, especially when you’re stuck on skills you don’t have.
Of course, I also understand the criticism. There are valid concerns around how models are trained (often using artists’ work without consent) and how it affects the creative industry.
To me, the biggest problems aren’t about the AI itself, but how the entire system around it is structured: tech monopolies, business models, etc. It’s a deeper issue.
In the context of a game jam, where we’re prototyping, learning, experimenting... I see AI use as totally valid, as long as you’re being conscious, honest, and transparent. The rules of this jam even mention that.
Still, as devs, I think we should keep asking questions and thinking about how to build a space where these tools can exist ethically and fairly, helping everyone: artists, developers, and players.
The Development of Gatonauta: Racing the Clock
Back to development: during this period, I created the first planet assets, the character, some items, and resources, but nothing was functional yet. It wasn’t until around day seven that I finally managed to finish crucial systems like inventory and resource collection. By then, I had already scrapped several parts of my initial scope:
- Survival: In the context of my idea, survival was just another layer. If the game core wasn’t even ready, that layer would only get in the way.
- Combat: Sadly, combat systems weren’t going to happen with so little free time. Maybe next time.
- Grappling Hook: This was scrapped along with space mining, but it would’ve been super cool to have.
- Dialogues: I had a whole story planned involving the Gatonaut and his sidekick, CatGPT (the little drone that flies around breaking stuff).
- Dungeons: Another idea dropped due to time constraints.
I focused on getting the basics working: movement, resource gathering, crafting, and building. Plus, the planet exploration part. I needed the game to at least have a complete gameplay loop. So I decided to go for a single simple goal: fix the spaceship. To do that, the player needs to craft three different parts. I planned the recipes for those parts and designed the steps to get them. Nothing overly complex, just enough to be fun for most players without requiring a grind.
I tried my best to make things modular using Godot’s signals, so the game would be easy to expand. In practice, if I wanted to add more resources, nodes, or structures, I just needed to create new instances using the existing logic, data, and textures.
All recipes, crafting, and upgrades are defined with simple dictionaries. Sometimes I use special objects for recipes, but they still rely on dictionaries under the hood:
## Structure costs dictionary
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
},
}
## Structure prefab dictionary
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
}
}
I wish I had polished the UI more, but I realized that every time I added a new feature, I spent way too long finishing it. This made it clear how inexperienced I am with Godot’s UI system. So I decided to keep it simple but functional. No fancy icons or effects... just text. The goal was to make sure players understood what to do and how to do it, even if it wasn’t the prettiest.
I spent day nine testing and fixing bugs, prepared a credits screen, and wrapped up the game. On day ten, I had work, so I could only fix a few last-minute bugs.
Conclusion
Joining this jam was, without a doubt, an amazing experience. I learned so much, tried out ideas I had shelved for a long time, like planet gravity, continuous integration, and even using AI more seriously in my workflow.
Gatonauta ended up being far from what I originally dreamed, but that’s not necessarily a bad thing. Part of the process is understanding your limits, adjusting the scope, and turning a giant idea into something that’s functional, fun, and gets the concept across.
I definitely leave this jam even more motivated to keep developing games, improving my processes, understanding my strengths better, and, more importantly, my weaknesses.
If you made it this far, thank you so much for reading. I hope this post inspired you, helped you, or maybe even gave you that little push to join your first (or next) game jam.
And if you’d like to try the game, it’s available here:
Gatonauta by StealthC
Top comments (0)