First gamejam post-mortem
Hi,
this was my first gamejam ever, so I decided I could do a postmortem on it, how I progressed, what worked, what didn't and whatever else comes to my mind. First, I am from germany, so english is not my native language, but I think it is good enough ;)
About me
For context, I was working as a web/app programmer for about 14 years before I was driven more into project management. As programming is still a passion thing of me, I decided I would do a hobby project to stay in practice. And besides that I always wanted to create a game but never did more than a few simple things like tic-tac-toe, flappy bird and the likes.
I found Godot last year and did a few tutorials on it I liked, the ones on the official docs, a great free one, and the first one and a half from the Gamedev.tv Godot humble bundle on 3D games, which is how I noticed this jam.
So quite a few "regular" programming experience, game programming not so much.
The beginning (day 0)
The jam started at 11pm, so I didn't have a lot of time on friday and did mostly brainstorm. I first thought that there were probably lots of tower defense and vampire survivor games, so I wanted to make something different to not drown in the masses (also I was in the middle of the tower defense tutorial and didn't want to do that again). So I made a list of all the things that came to my mind:
It is a mixture of german and english, sorry :D
So I actually started on "what could a stand be" to think a bit outside of the box. The bookstand came up very quickly and as someone who loves everything magic, I thought of magic furniture in the likes of Disneys the beauty and the beast, which wants to escape a magical library together with a book. Why... I didn't know yet. But I already thought a stealth puzzler seemed doable for the timeframe.
I just thought about a few other ideas, the best one was Gandalf on the bridge of Khazadum fighting of orcs until they break his shield and the balrogg gets him... which would have been a tower defense again. So it got scrapped.
After a while I asked ChatGPT for a few ideas for my book escape, while there were a few that were interesting, there was no coherent concept I liked. So in the end, I had to use my own brain... but it was late and I went to bed :D
The thinking session (day 1)
The first day I wasn't exactly productive. I am someone who likes telling stories as I DM in tabletop roleplaying-games, so I didn't want to do a half baked one just for the sake of participating. So I slacked most of the day and thought about stuff that could work while doing other stuff and it took until 8pm until I had the story outline that actually made it. But in my best procrastinating manner, I called it a day and wanted to start fresh the next morning.
The beginning (day 2)
Finally I pulled myself together and sat down at 9am and started. I even made a project plan with some time guessing and priorities. I cleaned a bit up here:
Task | Priority | estimated time |
Menu and Credits | 0 | 2h |
Export prep | 0 | 1h |
Levels | 1 | 4h (*lol*) |
Dialogue | 1 | 4h |
Bookstand model | 1 | 1h |
Bookstand model | 1 | 1h |
Bookshelf model | 1 | 1h |
Import 3d assets | 1 | 2h |
Puzzles | 2 | 2h (*rofl*) |
Boss fight | 4 | ??? |
Enemy navigation | 3 | 2-3h |
Ingame cutscene | 3 | 3h |
Model animations | 4 | 1h |
added later | ||
Interactables | 1 | 1h |
Lighting | ? | ? |
Particles | ? | ? |
Sound | ? | ? |
Music | ? | ? |
According to that plan and the times I could spend each day (see image), I would be done on with priorities 0 and 1 on monday, 2 on wednesday, and prio 3 on thursday (which was a vacation day in germany... nice), so I would even have time for all the not mandatory prio 4 stuff on my list and even more levels for the weekend. Nice...
Spoiler: it didn't work out :D
After that I started and actually created a git repository, a godot project and imported in the dialogic-addon.
Intermission - on source control
Yes it is a solo project and yes I used Git as source control. Why? Because it saved my ass so many times in my professional career, I only do the most simple things without it. Try something and it didn't work out? Rollback. Did change something by accident and didn't know what? Show changes. Want to see how that line of code looked before? Diff. Source control makes your life SO MUCH EASIER. If you don't use it yet: Start doing it! Seriously! Want to write a devlog while not having a great memory and not making any progress screenshots? Just look what you did on each day in your commit-log and download previous versions :D
Back to day two
I haven't done much with dialogic yet, so I was exploring a bit while creating the characters and writing the dialogue for the first room. After that, I started up blender and created the bookstand model and a book model. I am no blender guru, but a few low poly models were perfectly doable.
With these two done, I started creating a block-level in Godot. I used a gridmap with simple cubes to create the first room. After that I coded a player controller to move the bookstand. I started doing the lever, but didn't get the code finished to actually click it from my 3D perspective yet. At the end of the day, the game looked like this:
I was kinda satisfied and went to bed.
Bringing in some shape (day 3)
After having only placeholders in my gridmap (which seems to be the equivalent of a tilemap in 2d) I tried getting some meshes in. I used a Dungeon pack that I found earlier and thought would fit my project pretty well. It took some time to figure out how to import the meshes with textures, the *.glb files didn't want to work but after a bit of googling I found someone who said .obj files were less struggle and actually it worked out much better (I think I'll have to figure this out later). I exported them to a meshlibrary which I then used as source for my gridmap... and re-built the first room.
After that I created a base-class for Interactables and derived the book and the lever from it. And yay I could actually click on both and even flip the lever (which was build entirely out of simple meshes inside godot). At this time the camera still moved with the player character, which i stopped doing at some later time. As this was a normal working monday, I had only a few hours so when I finished it looked like that:
Turn on the lights (day 4)
On tuesday I noticed I had forgotten a pretty important thing: collisions :D After fiddeling a bit with the meshlibrary, hoping I could add the collision shapes there, I didn't get it to work and decided I just use a StaticBody3D and a bunch of box-collisionshapes to block out the level. For the objects like the table I used the create simplified convex collision silbling functionality in the editor.
At this time I split the camera off the player and changed to a static viewport and added some first lighting with shadows. As soon as two lightsources overlapped I got some weird artifacts, but I considered that a "future me problem" xD
Finally it started to look nice. Time to add some magic. I pulled out some particle tutorial on youtube and tried to create the casting-effect, and already after an hour it looked like I wanted and even went flying through the room... wheeee (I actually made that noise) :D
After about 4 hours I called it a day and it looked like that:
I was finally sure, that this thing was going to work and went to bed happy.
Slacking again (Day 5)
After the great progress from the day before (I totally forgot my estimations from sunday) and seeing that I would have a lot of time on the next day, I took it a little easier and just polished a bit and finetuned the dialogue... and that's it. Lazy me :o
Holiday (Day 6)
Thursday was a holiday in germany so I had all day to do stuff... except I had an lazy morning with some housework and actually started working on the project at noon.
I started designing the second level and the area transition code to get there. For that I needed a bookshelf, as the shelf was only in the paid asset pack that I wasn't allowed to use. So back to blender again:
I created a single book, duplicated it alot and just rotated it a bit around. After a while I was happy and decided that all shelves would look the same, because gamejam :D
After building the level it was time for my first enemy. I planned to use some magical creature that floats around and leeches the magical energy out of other beings, so I had three options: search for a great free model online, create one yourself, or just use a cloud of smoke particles and call it a day. You know how that ended xD
I used an image from Kenneys particle pack and experimented with the Godot particle settings until it looked like a flying cloud of smoke.
I tried a bit working with the Path3D to create the path for the shade to go to the other book and then out of the room, but the Path editing interface went all weird, so I just tweened its position between a few Marker3D objects. It was almost 9pm until I was happy with the level and the "cutscene" (4 hours for ALL levels... right? *lol*), so I didn't want to start something big for the rest of the evening. As I needed a pause-menu to add the mandatory credits to follow licensing requirements, I decided to do that. After an hour the menu was done and working, so I decided that now after I followed the licensing terms, I could actually export and upload it for the first time. After all, I don't want to start exporting-troubles near the actual jam deadline... and damn was I happy I did that. Because after exporting and uploading to itch, I just got a black box after the loading screen finished. Dang xD
I had to tinker a bit and saw a lot of errors in the browser console, that he couldn't find my textures. After a bit of research I found out that the path of the texture of an .obj file is in its accompanying .mtl file. After I changed that from absolute to relative the errors disappeared, but the screen stayed black. It went late, so I stopped for today with at least an (almost) complete second level.
Guess what I missed? (Day 7)
So... how about collisions xD
I didn't take a "free gap-day" at work, so I only had friday afternoon to continue working on the project. After adding level collisions I started refactoring again and rebuilt the scene transition code, the enemy code and added some dialogue, that you cannot go back to the last level. I added all common things from both levels to a "base level" scene that I could clone for further levels to save basic setup. After that I put all the magic missile code into an own scene, that I could reuse more easily.
With cleanup done it was time for the next and actual first level with the first dodging/distraction setup for patrolling ghosts. I created a new derived Interactable for the moving stool and retried creating paths for the patrols. And this is where it got messy. Somehow I had a really hard time editing the Path3D object inside the editor. After a bit, it got so broken the whole Godot editor actually crashed, as soon as I clicked on it in the scene tree. Luckily I had checked in my progress into git a bit earlier, so I could pin down the possible sources. I spent some time on google trying to find about the issue, used the Godot console executable for the first time in hopes of additional error messages. Which I got:
OpenGL Type: Undefined behavior ID: 131222 Severity: Medium Message: Program undefined behavior warning: The current GL state uses a sampler (0) that has depth comparisons enabled, with a texture object (1072) with a depth format, by a shader that samples it with a non-shadow sampler. Using this state to sample would result in undefined behavior
I couldn't find a solution for it online, but after lots of experimenting I noticed, that if I mark the node as invisible by clicking on the eye in the scene tree, the editor wouldn't crash anymore and I could edit the path in the inspector again. It was annoying, but I didn't get any useful info on the exception, so I also considered that a "future me" problem, after all, I had a workaround. After all the fiddeling I haven't had time for adding lighting and I was kinda burned out from the error profiling, so again, I called it a day.
The end is near (Day 8)
After loosing a lot more time than planned on the first few levels and having some real live activities on saturday that "cost" me 6 hours, I realized that I would have to scrap my first plan of creating 6 levels and a second spellbook that could shackle the shades. I finished the attacking-code of the shades in the morning, added some split dialogue for successful dodging or distracting your first enemy and blocked the dialogue on level restart (I hate that in other games... looking at you Tomb Raider!). In the evening I spent about two hours for adding in music and sound that I found on OpenGameArt. As it was getting late, I added a bit of banter dialogue between the book and the stand.
The (almost) final day (Day 9)
I planned that I don't want to add any features on monday, so I have the whole day for polish. Which meant I had to finish today. And I only had one actual level with some player agency. F***** :D
And to make things even better, I promised a friend to watch Furiosa with her. So... everything was fine xD
I actually speedbuilt the fourth level in the morning until I hit my next "funny" bug: The reload_current_scene in level 3 broke. It just loaded level 4. WTH?!? I spent some time experimenting and even when explicitly loading level 3, level 4 would just start... PANIC MODE activated. Oh, and I had to go to the movies :D
After a bit of experimenting I noticed that this had to do with my tween of the enemy attack and I had to disable a few lines of code, to get it back to working again:
func _on_leech_alerted_by(intruder: Node3D, leech : Leech) -> void: if (intruder == player): $Player.accepts_input = false leech.isAlerted = true var tween = create_tween() tween.tween_property(leech, "global_position", player.global_position, 0.5) await tween.finished %AnimationPlayer.play("fade_out") #tween.stop() # TODO crazy bug that reloads the wrong scene?!? #tween.tween_interval(1000) #await tween.finished get_tree().reload_current_scene() #get_tree().change_scene_to_file("res://Levels/3_FirstSneak.tscn") # reload_current_scene doesn't work?!
I still have absolutely no idea what these lines have to do with loading the wrong scene. If you have any ideas, please write me a comment :D
After having that fixed I was a bit less stressed about cinema. In the afternoon I finished the level at 7pm and was at a place, where I was certain I wouldn't get another level working. So I decided to add some final cutscene to an (hopefully) epic ending, which was done at 9pm. I had fun with curves again for the camera pan (no crashes this time) and the first time I saw the scene with music, it was like magic. I really loved it and watched it a few times. I was very happy and annoyed a lot of my buddies that they should playtest for me, which some of them did and they did find a few bugs. After fixing those I went to bed very happy.
The End (Day 10)
This is it. I wanted to spend the whole evening on polish (I had to my day-job again), which I was done at around 8pm. So, what could I do to stop getting nervous. Sure thing, adding mobile controls. As you probably noticed, that didn't work out. The capability detection of godot didn't trigger to add in the steering cross, so after 2 hours I gave up on that and spent the rest of the time replaying everything to be sure nothing is broken.
That's all folks
I have to say, I had a lot of fun and only small amounts of stress over the jam period. I am really proud of what I made, even though I am a bit sad that it is soooooo short. But that's probably fine, people don't want to spend lots of time testing, right? Right?
So, where will I go forward? I want to add the stuff I planned in the beginning that got scrapped (more levels, at least one more spellbook). And I want an amazing final boss battle. Should be easy, right? Furthermore I'd like to make a working android build. And than I will look what happens. If you're still with me, thank you for reading my journey and I would be very happy to hear from you, how you like The last bookstand. Cya
Files
The last bookstand
Sneaky puzzler with snarky characters
Status | In development |
Author | brandtware |
Genre | Interactive Fiction |
Tags | 3D, Casual, Fairy Tale, Godot, Indie, Mystery, Simple, Singleplayer, storygame, Top-Down |
Languages | English |
Accessibility | Subtitles |
Leave a comment
Log in with itch.io to leave a comment.