All posts by Ian Gaither

Developing Randomness in our Game: Dynamic Scaling and Relative Probability

Introduction to Randomness in Games

A brief introduction to randomness in games comes from looking at games without it. Chess is the most common example of this where every move can theoretically be calculated and optimized based on the opponent’s actions. This means that the game itself can be deterministic, as in who wins or loses is known before the game is actually played. Fortunately Chess is complex enough that humans struggle to fully enact this, but that’s why computers are often better than humans, because they can compute all the possible outcomes of each move and pick their move based on the sequence that allows them to win regardless of their opponent’s actions. Tic-Tac-Toe is a much more trivial version of this where if both players are playing optimally then the game always ends in a draw.

Situations where the end is known before the game starts tend to not be fun and people tend not to play them for long. This is why randomness is important. Even the slightest bit of randomness ensures that the outcome of a given game isn’t deterministic and therefore everyone involved has a chance at achieving the desired outcome regardless of skill level. This chance is beneficial in both winning and losing because it ensures that everyone has a chance to win, but also ensures that there’s risk of losing so that even skilled players have a reason to play and make an effort to win the game.

Randomness in Our Game

Our game is a tower defense where the player is fighting against an AI. Since it’s a single player game, there isn’t so much a focus on leveling the playing field as we generally want the player to win in this scenario or to at least feel like they had a fighting chance. In this case the major concern is that the player will figure out a strategy that will allow them to effectively ‘solve’ the game. This could potentially be a tower that is way stronger than the others, or a particularly effective combination that when replicated always defeats the enemy AI. Once they’ve found this particular strategy then the rest of the game becomes boring because it’s either not stimulating enough to force them to think or it becomes so trivial that they don’t even really need to make an effort to win the game. Our solution to this issue was to introduce randomness in the form of tower availability.

Our game will have a shop with a limited inventory where the player must purchase their towers. The current plan is to have it cycle on every wave and bring in a new inventory of options to purchase. This forces players to utilize the tools they have available to them through the shop, meaning that very rarely will they ever have the same set of options in a given level or even wave. While they can still have favorites that they prioritize through this system, it removes their ability to repeat the same strategy over and over, forcing them to think critically at every stage of gameplay and ensuring that repeated attempts at a given level will produce different results. The randomness also adds an extra avenue for strategic planning in that players will have to consider whether or not it’s worth it to buy a potentially worse tower now, or hope they can survive another wave and purchase a better one when the shop resets.

Designing the Random Inventory System

When I set out to build the shop inventory system I had two main goals in mind: dynamic scaling, where we can add new towers over time and the system would automatically adjust, and relative rarity where we could simply specify a value and the difference in that value from the other towers would determine how rare it is overall.

The dynamic scaling problem was probably the most important goal I set out to achieve as I knew we had an undefined number of towers and we would gradually add more over time. I knew it would be a nightmare to manage balancing the rarity over time, so I wanted to develop a system that simply required adding a tower type to a catalog and giving it some value for rarity and everything else would just work.

I ended up making the ‘catalog’ an array of structs containing references to the towers and their rarity. All we need for the shop to handle a new tower is to make an entry in this table

Relative rarity was the way to make an autonomous balancing system work so that we could specify how frequently a tower should spawn relative to any other towers we include. This system would gradually adjust the spawn chance of each tower over time, but would maintain the same relative frequency for each tower. For an example of how this works in the existing system we can look at a tower with 20 rarity and 100 rarity (with higher numbers being more common). In this case the 100 rarity tower would appear 5 times more frequently than a 20 rarity one (100/20 = 5) and in this case the 20 rarity tower would have 20/120 odds of appearing. If we added another 100 rarity tower then obviously the odds of the 20 rarity tower would drop significantly (20/220), however so does the rarity for the first 100 tower. The end result is that the ratio between the two spawn rates is equal in (20/120)/(100/120) = (20/220)/(100/220). What this means is that while overall spawn rates will drop across the board when we add new towers, their spawn frequency relative to each other will remain the same. With this system in place we can specify that we want a new tower to spawn five times more often than an existing baseline one simply by giving it a rarity that is five times higher than the existing tower.

This is the process by which a single tower for the shop inventory is chosen. This can be performed any number of times depending on how big we want the shop to be.

With the two major components in place, we have a rarity and selection system that will dynamically accommodate any number of towers we decide to add over the course of the project. This will enable us to worry less about managing the generation process and focus more on developing cool towers for players to use in our game.

Starting Your Project in Unreal Engine 4

Making a game is hard. It is challenging and time consuming and draining and it can feel like work at times. If it was easy then everyone would be out there making every little thing that came to their mind and there would be a lot more high quality games on the market. Getting over that first step of getting a project up and running scares away most people, but it doesn’t have to be as difficult as it might seem at first. With a bit of determination and planning you can absolutely get yourself started using an engine like Unreal Engine 4 even without any knowledge of code and game development in general.

While it can be fun to jump right in and start making things, especially if you’ve never made a game before, the key to starting a long term game project is to start in the planning phase. Without doing so it is extremely easy to get sidetracked developing a few systems while leaving yourself with an unplayable mess. This might be fine in traditional development where a finished system could exist for a long time, but in game development there’s an expectation that things will change and you could end up throwing a lot of that work and time away later if things don’t work out how you envisioned them.

The initial goal for your project should be a Minimum Viable Product or MVP. This is the bare foundation of the game with the few mechanics you need to actually play and test the core idea. The goal of developing this product first is that you’ll be able to test and iterate early so that you can find the ones that work the best or are the most enjoyable to interact with. This means you throw out less work and find a good direction as quickly as possible so you don’t find yourself restarting in the future. The process of planning your MVP can be fun as it forces you to come up with tangible ideas for what the game should look like and how each system should function. You can also use this time to categorize longer term goals and ideas that you can eventually build up to from the MVP.

When I start planning a MVP I think about my vision for the project and pick out the few fundamental systems that the player will interact with. The systems that the player controls or interacts with directly are likely to be the most important ones for your game and the ones you should develop first so that you have some basic gameplay elements to build upon. Once I’ve come up with these mechanics I’ll use a tool like Trello to map out and really drill down and figure out what the most basic components of those mechanics will look like. The image below is one such example of this with me breaking down every function the player could take to control their ‘generals’ which is the core mechanic of a game I’m developing around necromancy.

Each element in the list is mapped directly to a key or action the player would regularly take while playing the game

While that list is long for a MVP, it also makes up almost the entirety of my initial goals for the project. Once that list is completed then I’ll be able to test and iterate on the basic systems as well as start implementing some of the more complex elements like character customization and progression. This list essentially gives me a tangible goal to work through while trying to get to the ‘fun stuff’ which is actually implementing the game’s unique mechanics and elements and seeing the world come to life.

From here I simply went down the list and identified which mechanics are reliant on each other in order to eventually find my starting point. In this case ‘Move To’ was my first step because it required the least amount of moving parts since many of the other aspects required AI/behavior tree implementation. Thinking about how to implement that basic ‘Move To’ command basically led me right to where I needed to start: First the player so that they can give ‘Move To’ commands, then a system so they can aim and target where they want their minion to go, and finally the ability for the minion to receive that command and actually follow it to the targeted location. By following this pattern and really digging down into how each system works you can avoid getting stuck and unsure of what to do next because you always have that list to refer back to and to tell you exactly what else is needed to move forward.

Once that MVP checklist is completely filled out then you’re essentially free and ready to start actual development. At this point you have a functional (if very rough) game where you can test and see if your initial mechanic is actually fun to play. If not then you can try different things or add some additional features to try and find the experience that makes your game enjoyable. 

This whole process can be applied to additional features as well, giving you a clear map of how to implement a system, but at this point it’s really up to you where you go and what’s the most important part to build next. In my opinion, this is the most fun place to be in terms of development because you’ve essentially built your canvas so that now you can have fun actually implementing your cool ideas and seeing how they play and feel, you just have to power through that initial MVP phase where everything is being set up. While there are certainly more pitfalls farther down the road in game development, getting to this point can often be the hardest part. Once you’re here with a MVP and some groundwork in place, even if you don’t finish you’ll still have something functional and cool you can show off and potentially build upon later on down the line.

One final note; don’t be afraid to have a bit of extra fun, even in the MVP phase. Obviously don’t let it majorly sidetrack you from your initial goals, but if you’re making a game for yourself then you should want to work on it. It’s important to remember this and to embrace the little things you can do to make the game and the development experience more fun.

Some things are more important than others. Like skeletons. With hats.

Learning to Cook, From Someone Who Couldn’t

(BBQ chicken with cheesy bagels, I could never get over the fact that it looked like a face)

Up until last August I couldn’t cook (I was 25 at the time I started). I was never taught how by my parents as they were rarely home and I never took the initiative to learn myself because I was scared of it. I would eat out or just eat junk food instead of meals, which on top of being unhealthy was also really expensive. Then late last year my dad ended up having to make a shift in his business which left him getting home even later than before and often not having time to eat an actual meal at home (I caught him eating Ruffles covered in blue cheese dressing once and I’ll never let him live it down). This was the push I needed to teach myself how to cook, and now I cook four meals a week for both my dad and I.

(Homemade mozzarella sticks and curry)

While cooking can be intimidating if you haven’t done it before, once you start making things and developing things you’re comfortable with, you’ll always have something you can make without too much thought or effort. One thing that helped me at first was just to make things where you could buy most of the ingredients from the store so there were only a few actual steps for cooking. I started with some really simple tacos because most of the toppings you can just buy and the only thing you really need to cook is the meat. You can obviously make more than that if you want to, but you can make really good ones without having to hand make every ingredient.

The tacos I started with simply involved browning ground beef (something that is visually easy to do), which takes about five minutes at medium heat on a stove. After that I just followed the directions on the ‘Taco Seasoning’ packets you can buy at the store and mixed it into the meat with some water. That’s really it, that’s the only thing I did at first that would be considered actual cooking, but from there you can come up with all kinds of different meals depending on what ingredients you use and how you put everything together.

One of the first ‘recipes’ I would ever actually come up with was just a slight change to that process, but it made a world of difference. Instead of using water when mixing in the seasoning, I used some salsa instead and let it simmer until the liquid boiled off and the beef was thoroughly coated in whatever salsa I was using (my preference is mango habanero).

(Ground beef cooked in salsa with a bit extra on top)

We had a lot of ‘taco’ derivatives at first which led me to eventually expand my repertoire into sauteed chicken. I was super uncomfortable at first because raw chicken was scary, but I was just really cautious and if I didn’t think something was cooked enough, I would just cook it more even if it meant part of it got over done. Over time (and lots of YouTube videos) I would get more and more comfortable cooking chicken on the stove and eventually managed to figure out the right amount of time and temperature to cook it just right. Now chicken and rice with some random sauce from the store is my go to when I don’t have much time and everyone in my family has me cook the chicken whenever we’re making some at home because I’ve had so much time and practice getting everything just right.

(Chicken and rice with some sweet Thai chili sauce I bought from the store)

I’ve come up with more recipes since then like my Meat Bowl (it’s a bread bowl full of meatballs) and homemade mozzarella sticks with curry (near the top of the post, this one was incredible), but it was a gradual process that took some time and a lot of mistakes. If you had asked me a year and a half ago to cook you something, the best I could have done was probably that taco meat and even then I probably would have messed it up somehow.

(Meat Bowl, note: difficult to eat without making a mess)

In that short amount of time I’ve gone from completely terrified of anything to do with cooking, to making my own recipes (which people sometimes actually like!). If you put some effort into it and keep trying you can almost certainly reach the same point even if you were at the same place I was a year ago, barely able to cook for myself, let alone other people. Just try new things, look up recipes, and find things you’re comfortable with so you always have something to fall back on. It really is something that anyone can do as long as they put in the effort to learn and grow as a chef. The more comfortable you get making things, the more exotic and experimental you can get over time. As an example I’ll leave you with tonight’s dinner, something I came up with on the spot at the store when I wasn’t sure what to make tonight: Naan Pizza!

Building Experiences: “Making” vs “Designing”

Almost everyone who has played a game has also come up with ideas for games of their own. Many people take this even further and want to make their own games so they can share their ideas and potentially create something completely new and unique. This is great and I’d encourage anyone with a desire to do so to make their ideas become reality, but there’s a big issue that must be addressed if you want others to enjoy your creation, and that is mindset. Specifically the difference in perspective between “building your idea” and “designing an experience”, the key difference here being methodical and conscious decisions about how the player will experience your game.

It’s relatively easy to “make” some mechanics that sound cool and throw them together, but this rarely ever results in a fun experience, especially for anyone besides the creator. To truly “design” an experience you need to understand what makes something fun so that you can leverage that knowledge to create better systems. You need to understand what the individual (who is likely not yourself) wants from your game and how you can give them the tools to create an enjoyable experience. In doing so, your decisions become more deliberate and you can analyze and test if a given change accomplishes your goal. If not, then you can step back and find a different solution, eventually resulting in an experience that is refined and enjoyable to those who play it.

A good example of this can be found in mods for existing games. Oftentimes there will be large mods which have massive amounts of community support and are often recommended over the base game. These mods have been designed and built by members of the community for members of the community, and build upon the base game in interesting and unique ways. On the other side of this, if you look through mod catalogs you’ll find all kinds of weird mods that do things you’ve never thought of, but also you never really wanted and still don’t even though it exists. These kinds of mods highlight two important things, the first being that there are people out there who want very different things than you, especially because they took the time to build said mod. The second is that these are good examples of “building an idea” and not “designing an experience”. While the creator probably accomplished their goal of building the thing they wanted, the mod doesn’t really appeal to the larger community and as such probably won’t be used very often.

 All that said, you can absolutely always make something for yourself for fun. It doesn’t have to be big or even unique if it’s something you want to make, but if you ever want to turn game development into a career or even just want other people to like the things you make, you’re going to have to learn to design for someone besides yourself. At best, you’re making games for people similar to yourself. At worst you’re building things for someone who is nothing like you and has completely different interests. The reality is that if you want your game to be successful, you’re going to have to learn to design for both.

The Importance of Separating Ideas and Emotions

Working in game development I’ve seen my fair share of conflicts over ideas and directions for projects. This is something that is very common when working on games because of the creative elements involved and the sense of ownership people develop when they create something they believe is interesting and good for the game. However, this is not exclusive to games, this sort of thing often happens in traditional development as well. This can come from things like code reviews where people feel protective of their own work or even just high level design discussions for different systems. There is always a need for conversations about these ideas because a group of people can always make something better than any one individual whether that be from feedback for improvements or potentially ideas that are just better for the given situation. The problem then comes from the fact that people by nature become attached to their own ideas, they fixate on their own pitches and have a hard time accepting feedback or that their idea might be worse than someone else’s.

The goal for us as developers is to find the best solution for a given problem in whatever form that might entail. This is independent of who came up with the solution or who contributed to it because in the scope of the problem, those things don’t really matter. This is why the separation of an individual’s ideas and the emotions associated with them is important. Emotions cloud judgement and inhibit a group’s ability to properly discuss and analyze a given problem causing the solution to be worse off as a result. In addition, stress and antagonistic behavior in a group can make working together difficult and just make the development experience overall very unenjoyable.

The best environment for collaboration and problem solving is one where people can advocate for their ideas, but are also accepting of others. This is not easily done, as it requires individuals to step back from their work and objectively analyze a given problem and the solutions provided, but to also feel like their ideas are valued and heard within the group. Only in this kind of environment can people collaborate on the vision and direction of a project without having to have an individual act as the anchor and focus point of the team. The best projects come from groups of individuals whose goals are to support the best decisions for the entire team and to create something truly unique and interesting.

State Machines Are Bad and Why You Should Use Them Anyways

I remember my first introduction to state machines was by a professor exclaiming about how terrible they were. When I eventually discovered how they worked and what they did I thought he was crazy. In my head I thought “they give you so much control over logic flow and solve so many complexity problems, how is everyone not using these?!”, and in one sense I was right. They solve a lot of problems compared to not using any structure at all and they simplify a lot of common behavior and UI problems where you want distinct changes in functionality. 

I had other students echo my professor’s sentiment “state machines bad”, but when I asked them why they didn’t even really know what state machines were. From there I knew it was my sworn duty to convince everyone of how great state machines are and why they should use them for everything; except I was wrong. State machines are a great tool and they work great in specific situations, particularly simple ones, but they definitely have flaws. They struggle in complex situations where many things can be happening at once and can cause huge issues with multithreaded systems. They are definitely not the golden egg of programing paradigms that I once praised them to be, but they definitely still have a purpose in every developer’s toolkit.

So then what is a state machine and why would you want to use one? For me it always comes back to logic flow. Having a concrete and traceable system where you can easily identify the order of execution in messy complicated systems is a huge boon to development and your sanity. This is where state machines come in. They separate logic or “states” into independent execution channels with consistent behavior. While that may sound complex (and reading articles about state machines will definitely make you believe that is true), the reality is that they don’t really need a ton of features for them to be useful. A simple example (C++) is a switch statement with an enumerated state:

Here we know that every loop will only ever be in one state and that every state individually controls what other states it can enter. So from start to finish a given state controls everything about that execution sequence. It doesn’t have to worry about other states interfering and it doesn’t need to check if we’re flying because we’re obviously dying instead, otherwise we wouldn’t be in the dying state to begin with. This example leads to my next bit of code, otherwise known as “indicators you might need a state machine”:

This is a not so exaggerated example of code similar to some I’ve seen in my teammates work on previous projects. These often tend to spread all over the place as systems get more complex and often act as band aid fixes when characters are doing things when they aren’t supposed to. The problem here is that aiming has to care about all the other actions the player could take and for each new one you add there’s an exponential growth of systems that need to check for the status of other systems until you’re stringing along conditionals that become impossible to manage. We don’t want “aiming” to have to worry about if you’re “dancing” or “climbing” or “jumping” (well maybe jumping, but we’ll get to that later). We want “aiming” to handle aiming. That is its one responsibility and removing all the extra complexity makes designing a system that handles aiming much simpler and more straightforward. This makes any system where you can compartmentalize logic into separate states easy to handle and develop.

All this sounds pretty good right? Well then what’s the catch? Well a good example of the catch is jumping. You might not want to dance when you’re jumping, but if you’re making something fast paced you may want to be able to aim while you’re jumping. Well ok, one combination is simple, we can just put together a new state called “jump-aim”. But then what if we want to do flips while jumping and aiming? Then we need “jump-flip” and “jump-aim-flip” and then we need to consider how you transition between them. Can you jump-flip into jump-aim-flip? Can you jump to jump-aim to jump-aim-flip? Then how does non jumping aiming transition into all of these states? Wait, this is starting to turn into the problem we had before where things were handling too much at once. And this is where state machines start to break down. There are two main issues at hand here; the first being that states without clear boundaries start to break down when you try to put them together i.e. composite states. The second, and arguably the bigger issue, is that whenever you add a new state, suddenly every other state has to be considered for transitions. While we’ve limited the growth of long if statements, the growth still exists. For every additional state we need to handle all the different transitions, both in and out, to all the relevant existing states. These two issues combined can cause state machines to balloon out of control and become difficult to manage and expand over time. While I personally haven’t had to deal with extreme cases of this, I’ve definitely had to toe the line and it’s easy to see how something complex could make an unmanageable mess.

So while state machines definitely have their uses, they aren’t a magic bullet to every problem. An easy way to tell if they’re good for a given system is to consider how well the system’s tasks separate into independent functionality. If they don’t cross the line into other tasks’ functionality often, then the system could be a good candidate. In addition if the system isn’t meant to be dramatically expanded on then it also could be a good candidate. If neither of these are true then it may be time to learn something a bit more complex or to try and re-design the system to better accommodate the separation of responsibilities. 

All that said, just remember that using a state machine is probably better than going in without a plan at all. They can make your life easier when used correctly, just use caution so you don’t turn your team’s project into a monstrous machine.

How to Come Up with Your Own Game Ideas

One of the most common issues I’ve seen with people who want to start developing games is that they’re constantly looking for “The One”, the game idea that will immediately click and be great immediately from the get go. They want to come up with their own unique idea and often push back from things that are similar to games that already exist. This leads to them never actually starting a project because they’re always searching for a new and better idea that will let them make the greatest game ever. The problem here is that the great games aren’t made from the perfect first pitch. The foundation of game development lies in testing and iteration; in taking your ideas, finding the flaws and making changes to improve them over time. I guarantee that the Halo and Call of Duty games of the world didn’t start as anything resembling what was released and they likely even had several different names across their development. Even across different versions of games, developers are constantly changing and improving things trying to make the next one even better, meaning their original vision still needed improvement.

So then how does one come up with good ideas? What’s worked best for me is to come up with a “seed”, a foundational idea that I can build upon and flesh out to create a unique experience. Sometimes these seeds fall flat and don’t go anywhere. Maybe the mechanics feel really simple or boring, or perhaps the theme feels shallow and uninspired. These are ideas I keep in the back of my mind, not necessarily as failures, but potentially as inspiration for future ideas which can repurpose and improve them. So then which seeds do I actually develop and turn into actual games? Usually the sign for me is that the ideas keep flowing. I’ll keep coming up with new mechanics, concepts and easter eggs, slowly building up the seed into a foundation I can use as a basis for a game. These seeds are the ones that inspire me to create actual experiences and make me want to see what they can turn into over time.

Seeds can take many forms and come from all kinds of sources of inspiration. For me it’s often started as things that are completely trivial like a basic mechanic or some simple theme I want to explore. My most recent and current project started in the simplest form: “I want to play a game solely designed around being a Necromancer”. I had realized that most games are built with it only being a part of the whole experience and as such the gameplay for that specific class often suffered for it. From there I built it up thinking about how a game solely about necromancers would function and what cool things could I do when I didn’t have to worry about balancing other systems. This is sort of the essence of a seed; an idea that inspires more and more until you can turn it into an entire experience.

One last note is that these seeds and sources of inspiration don’t have to start from somewhere unique. An example of this was based on an idea my partner and I had after we fished playing Stardew Valley. We built up an idea based around being able to move your farm around with you and the different experiences and scale you can create with that. From this we created the first piece of concept art based on the simple idea of “A farm that can move”: