Hello again! Welcome back to the historical look at how Blightmare has evolved over its development so far. Last week I introduced the blog series a little bit and gave a teaser video of the first time we could swing the net. Today we will take several steps forward to see how several mechanics first looked. In particular I’ll show the Caterpillar, Dragonfly, Butterfly, and an initial version of dragging.
Before we get into the boring things like how this stuff is programmed, lets take a peek at a video. Here we have one of the first incarnations of our caterpillars.
Now that you can see a little bit of what is happening, I’ll talk a little bit about how the code was built. We use Unity as an underlying game engine for this project. I’m not going to get into why we made that choice here or discuss other options, but I’m happy to discuss it in the comments or in a future post if there’s interest. Those of you that follow along with Unity and to some degree game programming in general may be aware of the popularization of what has been deemed “Data Oriented Design” which is typically discussed in opposition to “Object Oriented Design.” The first pieces of code that we ever wrote for Blightmare roughly followed an Object Oriented (OO) design. Put simply, this means that we use self-contained units of logic – called Objects – to work together in order to implement the game. Thinking about things in this way has a pretty natural mental model because you can have each part of the game – the player, a caterpillar, or a dragonfly – as an individual concept. One of the common techniques when using this kind of design is called inheritance and it refers to the process of creating a hierarchy of things that get more specific as you go down.
The classic example is animals: the top of your hierarchy would be Animal and below it might be Dog and Cat. This is useful because some other part of your system might not care what kind of animal it is working with. For example, if you had a player that wanted to pet the animal. You, the player, might have strong feelings about which animals you like to pet, but in the code we want to let you pet all the animals if you choose. It’s convenient then to be able to make that happen at the Animal level instead of having to specifically put in code to pet a Dog and a Cat. It also means that later if we add a Goat to the system, you can automatically pet that too. Nice!
The handy thing that we can do now is implement a specific reaction to being pet in each specific type of Animal. For example the Dog might roll over on its back to get belly rubs, the cat might purr if you pet it once and swipe at you if you try again, and the goat might jump up and down. From a programming point of view, the system looks great because we can change any of these behaviors easily without affecting anything else. So far so good.
Trouble starts to creep in as we add more mechanics or concepts. For example, all these animals need water so we add the ability to water an animal. Other than exposing the silly naming that is rampant within many software projects, we’re still okay. All of our dogs, cats, and goats are now happily drinking away. The next thing we want to add is a plant. Where do we put the plant in our system? A plant is not an animal, but we need to water plants. We could potentially duplicate the water code in our player to handle plants and animals, or we could maybe come up with some higher level name for something that is Waterable – see what I mean about silly names! Things are starting to get complicated already, and we haven’t even talked about different types of water that we might have. This is obviously a contrived example, but as we will see, real examples exist too.
In this video you can see the first working example of the dragonfly and our swing mechanic. In terms of implementing this, it started as an extension of the previously existing “Hangable” that was used to implement the caterpillar from before. Something that you can swing on is something that you first have to hang on, so this makes sense. As it turns out, because this is how things were built, it was easy then to add movement to the dragonfly itself and have its movement reflected in the final swing position. Trying to do something like this specifically would have been pretty difficult because of all the various places that movement happens, but separating them into compartmentalized functions made it easy. In fact, it was so easy that I didn’t realize it worked until someone asked if we could make the dragonfly move. Originally I thought this would require some considerable time to get working, but it turns out sometimes things Just Work.
When we finally added in the butterfly, things started to get a lot more complicated. The butterfly starts out as a cocoon that when you grab it with your net, it hatches into the butterfly and you hang from it as it goes upwards. In additional to all of this, you can control the movement of the butterfly as it goes upwards. Now we had something that wasn’t directly Catchable but you still needed to hang from. In addition to this, the movement controls were basically the same as the player controls, except they only did left and right. It was no longer obvious how to make object hierarchies that could handle this kind of mechanic overlap in a nice way. Changing one part of a mechanic was breaking it in other places because there was no longer a nice clean way to break things up. In the end, I opted to just duplicate some code so that I could get the mechanics working enough to play with. On our developer discord however, I started bringing up some of the issues with Tom, our other programmer. Considering I had only worked on a handful of mechanics so far and there were already pretty significant issues showing up, I was pretty sure we were going to have to do something about it sooner rather than later. Here’s the butterfly in its very first pass (complete with a bug at the end)
The last mechanic that got added into the game before moving on to other things like tools and some art integration was a dragging mechanic. This was another thing that was really difficult to integrate into the object hierarchy. Initially we only had ground cocoons that were Draggable. This meant that there was a problem trying to keep the rest of the cocoon behavior – namely that you could bounce on part of them. Cocoons were already in a bit of an odd place because the wall ones couldn’t move and you could hang from them. I happened to know that we wanted other things to be Draggable eventually, such as rocks. There would be no bouncing off rocks which was going to cause yet another really difficult hierarchy problem in the future. In my next post, I’ll discuss what the other paradigm I mentioned at the start, Data Oriented Design is, how we used it to solve many of these problems, and what the cost of switching designs was. For now, here’s a video of the first draggable thing in Blightmare:
Until next week, cheers!