Minecart – The “Vomit Comet” from BGSjam6

BGSjam6 was over a week ago now, so my writing a bit about it is a tad overdue. Better late than never, right?

So the theme of this jam ended up being “The Wild West”, which was a pretty awesome theme IMO. We had TONS of ideas, everything from shootouts to saloon simulators to gold mining to whatever else you can think of that’s out of a Sergio Leone film.

The idea of a gold mine stuck with me for a bit, and then someone else said something about minecarts and train tracks, and THEN someone else mentioned the minecart chases from Temple of Doom and Donkey Kong Country, all of which clicked in my head – “it’s simple,” I said. “I’ll make a networked multiplayer minecart shootout with procedurally generated tracks.”

…I don’t know if you’ve ever tried to make a game or participated in a game jam, but this is exactly the kind of idea that’s (A) never simple and (B) absurdly out of the scope of a 48-hour game jam. So naturally I made half of it anyway.

The game I created turned into a (literal) rail shooter in which the player rides a minecart on a randomly generated track and attempts to set a new high score by shooting as many of the duck targets as possible before flying off the rails. I dubbed it “the vomit comet”, and if you haven’t played it yet or skimmed passed the animated GIF at the start of this post, take the time to check out either and the reasoning behind the name should become abundantly obvious to you.

So, what worked?

Surprisingly a lot more than I expected. The first thing I did was create a quick test in Unity with a single piece of track, a cart, and a little bit of code. Some logic behind the cart moved it along a loose path constructed of waypoints (empties in a sequential order) that followed the curve of the track piece, simulating movement along the track. I quickly realized that assembling multiple pieces of track would require a lot of waypoints, so I slapped together a quick editor script that allowed me to easily generate new waypoints on a piece of track.

I next rewrote the movement system. For something that’s supposed to go forever, you want to move the world around the player instead of the player around the world. So I build a world controller that was controlled by the cart’s speed, thus moving the track around the cart. In the editor view it looks goofy, but to the player it’s the same thing as moving the cart itself.

Next I added some logic to connect the track pieces to one another. This involved adding another empty (I called it a “link point”) to the end of the track piece. Something I should’ve mentioned earlier is that the origin point of each piece of track is at the start of it. This way, when the world manager needs to attach a new piece of track to the end, it simply creates it and sets the transform of it to match the link point of the previous piece.

To save on resources, I made a “library” script that, at launch, instantiated something like a bazillion track prefabs that the world manager could grab and place at the end of the track. Once the cart had passed that track piece, it got moved to a queue in which, at some point, it’d get removed from the world and placed back in the library. This helps keep things from constantly being instantiated and destroyed (something I’m told is very bad).

After all that, I added a little bit of gun/raycast code (mostly pulled from my previous shooting-related projects) and added some targets that get created alongside the track pieces. I also added a super simple game manager that handled switching between scenes and kept track of the player’s score and high score. This was my first time really implementing any sort of game manager in a project, and I’m now appalled I’ve never done it before.

What didn’t

Multiplayer. I don’t know what the hell I was thinking, but trying to come up with a clever way of implementing multiplayer in a procedurally generated game is insanity. I’d have to make sure the tracks stay close enough to each other enough of the time so players could shoot one another. I’d have to keep their speed in check. I’d have to come up with real logic for the track generation. AND I’d have to get Photon working nicely quickly. Fuck. That.

FUN FACT: the “lose” condition? Where you fly off the rails? Totally a bug. I actually couldn’t think of a good way to conclude a round. At some point during track generation and movement, the cart will occasionally lose track of the next waypoint and just fly right past it, letting the track fly away into the distance. No idea what caused it, aside from some very hacky code. So on the last day I took this as a sign and turned it into a cheap way to end a round. If you end up a certain distance past the waypoint you were supposed to hit next, you “flew off” and ended the round. So I guess this is both did and didn’t work.

The track is totally random. To a certain degree, this gives it a level of charm I didn’t predict. However, it would be pretty nice if it didn’t do things like just shoot through the terrain I put in last-minute to give the game a sense of place. So a little bit of logic could be handy.

What’s next

I honestly don’t see myself going back to this project for much beyond creating a VR build that’s being demanded by some folks at the Space. I’m not looking forward to testing that, so hopefully it kinda just plugs in and works.

I think the big takeaway I got from this jam was even a little bit of code organization goes a long, long way. That game manager class (and the world manager) made things just work, which was AWESOME. I’m currently working with some basic design patterns for my Mech project, and to start the “serious” work I’ve begun implementing a game manager with a pretty solid state machine. Fingers crossed it’ll provide me with as much help as the vomit comet’s did.

If you made it to the bottom of this post, congratulations! Also holy shit, I didn’t expect to go on this long talking about this little project. I enjoyed writing it though, so if you enjoyed reading it lemme know in the comments and I’ll try to post more updates like this more often. Also, if you’re interested in this goofy little game or the project’s source, feel free to give it a download and play away.