The Concept
It all started when I wanted to do something with procedural generation. I remembered an algorithm that I used a long time ago to procedurally generate houses in Minecraft. I thought it would be nice to use that algorithm to create houses for a stealth game. I wanted to combine the stealth and stealing mechanics of the Thief series, with the inventory management of the Fallout series. I’ve created several of my own game engines in the past, but I didn’t want to handle all the physics myself this time - so I decided to use the Godot engine.
The first idea was to make it isometric 2D. To learn the engine, I created a sample level from a tutorial. It was 3D isometric. I added camera rotation and the ability to see the player through the wall when our view is blocked. I loaded some sample 3D character meshes and added walking animations and collision. I started thinking about all the assets and textures that I would have to make for this and realized that I hadn’t even started on the procedural house generation that’s supposed to be the heart of this game. I decided that I didn’t want graphics to be the main selling point of this game, and I started over with a 2D top down view. Now that I had a nice grid to work with, I was confident to continue on to the planning phase.
I started a spreadsheet to plan rooms, objects, and items. This includes which objects were in which rooms (like a sink in the kitchen), and which items could be found in which objects (like a sponge in the sink). I also planned item weights, value ranges, and chances. Items would have both weight and volume, so you have to manage your inventory and decide what things to carry.
For a proof of concept, I downloaded an asset pack and learned:
TileMaps and TileSets
placing tiles
rendering the scene
getting user input
collision detection
Now it was time to draw.
I drew some simple assets for walls and doors. Then I realized - to appear less blocky, I would need to have directional tiles that blend into each other. Like a vertical wall, a horizontal wall, L shaped walls, T shaped walls, and + shaped walls.
Finally, it was time to apply the first procedural generation algorithm: BSP (Binary Space Partitioning). There will be more types of procedural generation used in this game soon, but I didn’t know that yet.
There are some really cool things about BSP. Splitting into tree nodes means that all leaf nodes are final rooms, and any connection to a parent node means the rooms share a wall. You can put a door there to connect them. In fact, this means that you are guaranteed to always have a path from any room to any other room.
The Results of Binary Space Partitioning
The walls connect in I, L, T, or + shapes. All rooms are connected to each other. Also added doors and a variety of themes like wood and brick.
Swapped the “P” placeholder with a player sprite
I wanted to be able to enter multiple houses, so I needed a city. I realized that I could use the same binary space partition algorithm that I used for houses to create cities. There are different ways to use BSP. For houses, I decided not to trim down the spaces. That works for a dungeon style with a hallway between rooms, but this isn’t that kind of game. For cities, however, we don’t want the houses right next to each other. We want yards and roads and dirt paths and such. So a partitioned space has a smaller space somewhere in it where the house will be placed. This leads to the next type of procedural generation: Rectangle Overlapping.
The first houses generated this way were kind of silly, but after some tweaking of the parameters, I started to get some nicer looking city houses.
Added sidewalks
…and dirt paths
Also added:
scene transitions (fade out and in)
ability to open doors in houses
room labels
special floors for gardens and garages
…and scattered patches of dirt
Now it was time to place some objects in the houses.
First I wanted to find the corners of each room
Then make sure the boundaries fill the rooms properly
And get the edges that outline the room
Then randomize and make sure the object orientations are correct
And finally, randomize the objects based on the room
Double sized items (like shelves and couches) were clipping through the wall and far items (like paintings) need to be moved back.
Those issues were soon fixed.
Here’s what it looks like with max object density
The next step was adding items to the objects. We can’t see them yet, though.
I think we’re done with houses for now. Let’s add some menus and screens!
I wanted menu to feel eerie, like you’re being watch by a thief. I made a proof on concept where the eyes randomly look at you. I like it!
The proof of concept worked, so I jumped in to VR to paint a guy in a ski mask reaching for something. The thing he’s reaching for will change each time the menu is loaded. I like the idea of a dynamic menu.
The very beginning of a backpack
Back at the house scene, I added foggy rooms and camera zooming.
Settings screen
Splash screen
Planning story and missions
gamepad controls
keyboard/gamepad controls for UI
UI navigation and confirmations
Inventory transfer
Then a barrage of updates…
Player
Animation
Updated Backpack GUI
Added saving and loading
Added suspicion meter and stats HUD
Improved saving/loading (custom JSON objects)
Some tricky menu improvements and edge cases
Added more characters
add tutorial and guild
location traversal
action bar (for lockpicking, etc.)
special stashes (vehicle, desk, safe)
tasks & task list
Signs and text boxes, with animation
partial tutorial
bugfix: load save wasn't clearing previous vars
bugfix: moving backpack rows was acting weird
bugfix: spacebar on item_row was emitting "pressed" twice
lockpicking animations
migrated from Godot 4.1.1 to 4.1.2
NPCs are generated from a random head, a random mid section, and a random bottom.
Some mid sections (like tank tops) will show skin, so some logic was added to make sure open skin middles are limited to the right head color.
I considered using a shader to color the skin. Then any top works with any mid. But some color combinations might not look good. I wanted a more curated feel.
Time for some NPCs!
Testing NPC Generation with 400 NPCs
48 heads * 24 middles * 24 bottoms * 3 skin tones = 82,944 possible NPC combinations.
After some curating and filtering, the total became 59,648 possible NPC combinations.
Added random NPC generation
NPC roaming with boundaries
NPC walking animations
Wait… Where are they going?
Lesson: This is what happens when you mix local position and global position.
update the suspicion label
added notoriety mechanics
added mask mechanics
added safe cracking
bugfix: searching through walls
design cop assets
add cops to cities
add NPCs to houses
make fog on top of NPCs in the house
make being in the house a suspicious activity
added objects to tutorial
backpack bug fix
place X on a city houses to indicate no re-entry
Cops chase the player at high suspicion (no pathfinding yet, just a straight line to the player)
dynamically color the suspicion & notoriety bars
popup notice on entered houses & busted locks
revamp suspicion/notoriety/mask mechanics
update the tutorial signposts
slide in and out of the city on the vehicle.
This started as a “What if?" idea, but it turned out to be so fun that I kept it.
Added: Getting busted!
Added camera smoothing.
Wow, the camera is so much better now!
fixed: trying to move while lock picking
NPC vision is done by ray-tracing. Every NPC has a line (ray) cast from the NPC to the player. If the line collides with the player and the length of the line is within the NPC max vision distance, then the NPC can see the player.
Let’s talk about NPC Vision!
Performing an illegal action while you are seen by the NPC makes your suspicion raise (or notoriety if you’re not wearing a mask). This is multiplied by the number of NPCs that are watching you. Cops work the same way (but you become wanted if they see you do something illegal).
An NPC is trying to track the player
All NPCs are trying to see the player
Cops work the same way as NPCs
Whatcha gonna do when they come for you?
added Special NPCs
character dialogue
add museum
update settings
implemented buy & sell
fixed some bugs
Museum Donations and Rewards
Auto-scroll for gamepads.
Godot 4 cannot repeat gamepad directional button presses, so I had to write my own logic to simulate this functionality in the backpack and other menus.
change backpack drop behavior
add task list (with auto-scroll)
At first the museum used the regular shelves asset, but I decided to make some lighter shelves specifically for the museum.
Sometimes something that seems simple is harder than you think. Scrolling with the gamepad is a great example. When you hold an arrow key on the keyboard, the event is repeated and you can scroll through menu options. When you press a directional on a gamepad or controller, the event is not repeated (mostly due to OS limitations). But we want to be able to scroll through menu items without pressing multiple times. So how did I fix this?
When a direction is pressed on a gamepad, I catch the button down event and start a timer. Whenever the timer reaches zero, the event is replicated in code and the timer starts over. This repeats until a button up event is caught, and we stop the timer. The scrolling speed can be modified by changing the timeout of the timer (a 0.1 second timer will scroll faster than a 0.5 second timer).
It’s little things like this that many gamers don’t even think about. But it doesn’t come for free, it takes work.
I’ve been drawing a few items a night. With over 1,000 assets to draw for this game, progress can feel slow at times. It’s nice to step back every now and then to see all that’s been accomplished.
vehicle yard
vehicle carry warning
update player stats and saving
updated assets and decorations
improve gamepad menu scrolling
expanded the yard and vehicles
implement experience gain and level up
get a popup message on level up
delay level up message while in conversation
implement training menu
fix window auto-closing on movement
enable new game defaults in config file
Let’s talk about Maze Generation
There are many ways to generate a maze (see Wikipedia: Maze Generation Algorithms) for some examples. Each way has their pros and cons. I chose a recursive backtracking algorithm because it fills all grid positions, guarantees a solution from any point, has no loops, and no islands.
The algorithm is not hard. You run a DFS (depth-first search) from any point in the grid, choosing a random open direction at each step. If you get to a point where you have no open positions, you backtrack up the stack until you have an open position and continue. You do this until you’ve backtracked all the way to the beginning. Now you can set your start and end point anywhere you like (this algorithm guarantees a solution from any spot). You now have a maze!
Now we have multiple type of procedural generation: BSP for the houses, modified BSP for the cities, rectangle overlapping for the city buildings, part matching for the NPCs, and backtracking DFS for maze generation. Nice!
A bunch of updates:
add main street to city (split at initial bisection)
extend vehicle collision & interaction range
updated vehicle assets
fix trespassing while exiting special houses
update vehicle collision on the yard
implemented vehicles purchasing
extract dialogue to separate file
fix skill training buttons
Gain abilities when requirements are met
Apply skill and ability effects
improve initial continue logic
using strength abilities
maze access board
start position camera fix
add maze reward area
task board asset changes on use
maze tasks
add city edges (beach and forest)
refactor border code
Location based triggers
Leaving city by main road
Add random foliage to city
statistics board
implement task board
split tasks by type
fix two new game save bugs
randomize character poses in settings
categorize items
display categories in backpack
backpack categories toggle
add task board collection chest
board task generation (category, item)
task board initialization
improve task board structure
update curator asset
improve sub-menu transitions
board completion condition check
suspicious person in guild
In order to accommodate some of the new task type from the task board, I had to categorize all (over 150 so far) items and show the categories in the backpack GUI (with a toggle for when you don’t want to see them).
Also had to widen the taskboard several times to make sure all tasks would fit
refactor board tasks
add more board task types (multi, single)
add more board tasks
clean up some tasks
improved level up notification
particle effects for level up
particle effects for gold up/down
bugfix: new game after deleting a profile
more board task types (distinct, room, object)
testing new board task types
particle effects for player busted
migrated from Godot 4.1.2 to 4.2
add code regions
cleanup particle effects
improve level up delays
update NPC mid assets
bugfix: min city lot size
small tutorial & guild updates
update statistics board
gameplay demo with audience
NPC and Cop visibility cones
toggle visibility settings menu
At first I wasn’t going to show which NPCs can see you. In real life you don’t have a vision cone to hide from. I didn’t want this to feel like a Metal Gear game.
But it was hard to know when to pick a lock if you don’t know who can see you. So I decided to only have vision cones when you’re doing something illegal. That way you can hide better without staring at immersion-breaking vision cones all the time.
And I added an option to turn these off in the settings. I split NPC and cop vision cones because you might want to keep the cop vision as you will become wanted when a cop spots you doing something illegal.
design, draw, import ability icon assets
update some GUI themes
add player icon to save profile menu
added clout & VIP item label colors
more type safety and GUI theme edits
started work on the Burgleville website
particle effects for bashing and smashing
screen shake on bashing and smashing
screen shake toggle in settings
refactor notoriety logic when busted
add pathfinding for NPC chase mode
can be caught by NPC when trespassing
fix some spelling mistakes
theme donated item text to avoid donating again
particle effects for abilities and vehicle purchase
update main menu background
improve menu performance
more work on Burgleville website
Update app icon and window icon
test windows export exe
Cops were chasing the player in a straight line. It was easy to get them stuck on a tree or building. So I added real pathfinding so they can walk around objects. I didn’t make it perfect, though. I want the player to have fun running form the cops and trying to trick them. I didn’t want the game to feel too stressful with perfect cops.
The Menu Objects
I like a dynamic menu, so apart from the characters eyes moving around, the object that the character is stealing also changes.
I’ve been drawing 32 x 32 pixel graphics for everything this whole time, and I’m definitely not experienced enough to draw something bigger with shading and lighting and gradient colors. So I looked at a bunch of references and started combining sketching. Then I imported to paint shop pro and pixelated the drawings to make them fit in better with the aesthetic of the game.
Now most of the main mechanics are done.
Next step was adding a ton of dialogue. Each character has their own way of speaking.
Then I worked on recording music and sounds. That’s a whole project on its own.
Then I continued adding new locations and populating them with items.
A huge part of the remaining work is now adding more story missions. It’s not the hardest, but it’s the most tedious and time consuming.
Then it’s time to work on some dev-ops. Exporting and testing, integrating with Steamworks, configuring depots, pushing builds, etc.
Then it’s time to update the business side of things. Registering, licenses, business accounts, websites, Steam store assets, etc.
It’s time for PR! Making videos, trailers, dev blogs, and interacting with communities.
Finally - as I write this, the release date is nearing. After the release, I expect the usual bugfixes and maintenance.
This project was huge for a single person.
Hopefully you like it!
If you’ve made it this far and you’re still interested in game development, check out a more detailed log here…
Burgleville Dev Journey
or view it as a plain text file here…
Burgleville_dev.txt