TOJam 2024
TOJam is the name of the Toronto Game jam, a jam that happens at some point in May pretty much every year. I was pretty consistent in attending in my early career years, but covid broke the streak and it never really recovered - 3 days in the city is a tall ask with little kiddos running around at home. Last year it didn't shake out for Landen and I so we vowed to make it work this time around.
If you don't care about the process, thats cool - get some friends & controllers & you can play the game on my itch page right here.
Prework #
I had prepared a Local Multiplayer lobby ahead of time a few weeks ago, because I've done Local MP in a jam before and nobody wants to be writing UI at the eleventh hour and mapping Device IDs to Player IDs with time crunch.
We finished architecting how the match data gets populated from the menus on the Train ride to the venue, which also served as a quick git primer for Landen who - as far as I can tell - only uses git when he works with me. he'll learn!
this includes a check in our GameManager class which checks for match data - if it exists, it uses that to set up the game, but if it doesn't it generates a debug match data. this way we can run the game from the gameplay scene without configuring multiple controllers / going through the local multiplayer lobby every time.
We also knew we were making a boat game, so we nabbed Kenney's boat assets. My hope was to avoid animations and have lots of small things, rather than highly detailed "hero art" or similar.
Day 1 #
We sat down with a rough plan -> Local Multiplayer fishing with a dash of Vampire Survivors. Basically the hordes of enemies become hordes of fish and each player drags a fishing bobber around behind their boat to hit the fish, thus catching them and levelling up in some way.
The first step was getting the bobber to chase the ship. We ended up spending a couple of hours debugging Godot's 6DOF Physics joint, which I suppose was not up for our task because the ultimate solution was for me to write a made-for-purpose implementation of Hooke's Law so the bobber chases an ideal point behind the ship (with a deadone). Physics is not Godot's specialty.
It did not feel great to have only this after the first few hours...
I took a few minutes to wander the halls of TOJam and find some friends. Mostly folks I haven't seen (in person) for 5 years or longer!
I then started focusing on fish - I wanted the fish to be visually simple but move in the organized chaos you see in flocks of birds. most of the time this would call for a flocking implementation, but worrying about performance I just set up a Fish Manager. The Fish manager generates a few schools of fish, and moves the fish towards an occasionally changing target. Since all the fish just rotate left or right (via the right vector's dot product with the target's position) and always swim forward, they always move in tandem(ish).
I didn't need them to collide with each other - i guess they could be at different depths? it's not really gameplay relevant either way. Thus, there was no reason to worry about local avoidance within the schools/flocks.
somewhere in here, we took our pre-packed lunches to Sugar Beach for lunch, chatting through design ideas
While I had been solving fish, Landen bounced around tweaking the boat controls, getting score working and wiring up our initial UI - everything from design through implementation.
Once we merged our work together, we had a fairly gnarly looking prototype - and a lead on a music floater who was interested in making some tunes for us.
we were feeling a bit sluggish so nabbed an early dinner and walk. That was a great decision, because it felt like we had a surge of motivation. I managed to finalized the fish visuals & the Bobber, while Landen took time to plan a dynamic camera, build out the rocks around the body of water and square away more UI. Things were looking up.
a clip we captured after finalizing the fish for the WIP channel on the TOJam discord.
with the opening ceremonies delayed, and both of us keenly aware of the next 2 days of bus rides and jamming, we decided to bail a bit earlier than planned, hoping to retain some energy for the days to come.
A quick end of day screen capture.
Day 2 #
Once again, Landen and I sat down with a rough plan: I would lay down the architecture that would enable us to add artifacts to the game, while Landen put in most of the game loop - such as the results screen & title.
We also managed to pick up another audio floater, Kate, to help us out with whatever simple SFX we could think of, and some ambience for our menus. More work to implement later!
I was hoping to have artifacts running by the end of day with a few artifacts, but it was fairly slow going, as my UI updates would often conflict with Landen's. correctly packing each UI piece into its own scene helped us navigate this a lot, but we still stepped on each others toeas a few times.
by the end of the day you could level up and select an artifact, but we only had one, so it felt a bit sparse. hopefully more artifacts tomorrow!
Landen did manage to get the game flow working: from Splash Screen -> Title -> Lobby -> Gameplay -> Results and back to Title. This involved a lot of UI, and Landen stopped and added shaders and polish as he went.
At the end of the day we played a round with our composer Wilfred and decided to rework some core gameplay while we layered on game diversity via artifacts on day 3.
Or so we thought! Landen was mega motivated and tackled some simple hanging tasks on the bus ride home and at night. we had credits, better looking water, and tons of tiny touchups.
A quick end of day screen capture.
Day 3 #
The plan for day 3 was Audio, Artifacts and Arcade. AAA gaming!
In the morning I started getting the "multiple bobber" artifacts working, alongside the "Bobber Growth" artifacts. it turns out there are some wild gotchas around duplicate()
and physics stuff in Godot, so it was a bigger rework than I planned. but eventually we got 5 new artifacts that add bobbers in different "slots", and 2 artifacts to scale the bobber up.
Landen tackled some tutorial images and player boat selection in our multiplayer lobby. It was really moving!
people spent a lot of time choosing boats!
Landen and I sat down for a lunch away from our screens and discussed the game. The biggest take away was Landen convincing me to cut the entire "Artifact Selection" process, whereby each player levels up independently, and replace it with a global artifact system, where we introduce global gameplay twists as the game progresses. I was wary about ditching something we had put the effort into, but realized it would be better for the game to push harder into the "Party" genre, away from providing more "build agency" like you'd see in a roguelike.
So we got back from lunch, and replaced the Player Artifact system with a Global Artifact system. All 7 artifacts just had to be updated to act on all players instead of whichever player they belonged to. Since our seven artifacts were just 2 scripts with different instance data, this was minor.
In this time, Landen tackled the UI upgrades needed to change the artifact system, which he did in isolation pretty quickly. We wrestled with a few git and Godot related mishaps while we were in this final mad dash.
I left to get my mind on other things by helping out another Godot team with some code issues, and when I got back Landen had added his own artifacts to the game and it was looking great!
Kate & Wilfred were both around, so I also did a pass at updating all the music & getting most of our sound effects in. when we bailed for dinner at 5:30, we had played a match with Kate and Wilfred, and had a very minor set of bugs to fix up before the closing ceremony at 6!
Still very happy with my schools of fish
The Arcade #
At the end of TOJam, everybody sets up their game to be playable in a big room and we all host players & browse the games. Our first 2 or three games with people showed us a few big flaws:
- the dynamic camera zoom was a bit too wide / tight with different player counts
- the timer was a bit too long
- players earned 6 or 7 levels very rapidly, then spent a minute or two progressing through the next.
Luckily all of these were fixable with some number tweaks, so we shut down our game a few times, tweaked some numbers and kicked out new builds. this was very quick to do with Godot!
We had a great time playing the game with a bunch of people, and we were on the big screen for a long time! The game sounded great pumping through the room's speakers.
Gallery #
Here are some pictures I've sourced from attendees. I've blurred the faces for the sake of things like AI and general privacy - I've got no real defense against those things on this site.
Some folks playing the game on the big screen at the arcade
me explaining the game to an onlooker while other folks play. Photo from Kate Tavasoli.
some people playing the game on the big screen, close up. Photo from Kate Tavasoli.
- Previous: Art Dump II
- Next: Art Dump III