Development Journal – I Can Haz Procedurally Ramped Difficulty?

Preface – I’m not a mathematician in any way, shape or form.

Shamefully, one of the things that’s always bugged me about any game I’ve ever written was the difficulty was explicitly defined. In other words, I would always have a method that would check the current level and apply random scalars to settings depending upon that check. Does it work? Yes. Is it intuitive? No. Does this make for a horrible game experience? Yes and no (more yes).

Without diving too far into the rabbit hole, I wanted a way to automatically increase the difficulty of a game while still retaining certain qualities. Simply ramping the difficulty could be achieved in a number of ways depending on how you want the game to be. If you want it to react to how the player makes decisions in the game, well that’s a whole other issue that I’m not going to dive into right now as it could get complex really quick. For the project that I’m working on now, I wanted something a little more simple. Why not a logarithm?

Logarithmic graphs are really nice to look at but present some interesting hurdles that you need to compensate for in other ways.

First of all, I decided that I’d play with the natural logarithm instead of another base. I like smaller numbers as they’re always easier to manage (plus, I’m lazy). To entangle it a bit more with the game, I decided to take the natural logarithm of the value of the current level multiplied by two, squared. So it would look something like this:

ln((currentLevel*2)^2)

Java has a nice log method in Math that operates on the natural so the code actually looks something like this:

(float)Math.log((Math.pow(currentLevel * 2, 2)));

This little modification to the natural log gives a relatively nice curve.

Image

This is just a sample of what I was getting. But why use the current level multiplied by two then using the value of that number raised to the power of two? Because it produced the nicest results in all of the testing that I did plus it ties into the current level which helps to give the impression that the difficulty scales with the levels. Levels pushing into the mid to upper 90’s produce a value that’s 10.xx and quickly ramps up from there which can cause some problems in systemic calculations (since you’re actually using 1.x (1xx.xx%) as a multiplier which will always give you at least the number you’re multiplying against which is not desired in most cases). However this fact is taken into consideration and compensation is made for it where needed.

So what can you do with this value? Well, in the simplest terms, the possibilities are endless. And, frankly, you don’t even have to calculate it the same way I did. You can do whatever you want, so long as it makes some sense. But I chose to tie it to the level and amp it up a little (the base value returned from ln(level) was a little low, even for my tastes). The great thing about this seemingly insignificant number is that it can actually hold a lot of weight for procedurally generating difficulty scalars (which is basically what this is). Variations of this value (mostly being derived from rounding functions like floor or ceiling) can be used to help determine the total number of objects to work with in a level or how many enemies to pack into a wave. If the player has a goal that’s a fraction of a total number of objects, this value can be used to help determine that percentile and you can apply it there and elsewhere. You can also use it as an abstract base in probability calculations so that you can make things happen more slowly in early levels and more quickly in later levels, helping to increase that sense of difficulty.

Another thing to keep in mind that could potentially help is that an exponential curve is the inverse of a logarithmic curve. So if you find yourself in a position where you logically need to do things that go against the logarithmic curve but still need to retain that difficulty, having a second measurement from the exponential curve of the same method that calculates difficulty could be beneficial.

Game Development – Migrating to Classical Mechanics

Let’s clear up some possible confusion regarding the title of this post. I’m not necessarily directly talking about game play mechanics as I am talking about the branch of physics called Classical Mechanics. You know, the fun stuff that helps us describe motion of mass under certain types of forces and the effects, both direct and indirect, resulting.

Well it’s fun for me anyway. Even though I hadn’t necessarily realized how much I’d forgotten about really simple stuff.

And let’s clear one more thing up here. I’m not a professional mathematician or physicist. I’m a software engineer. So if you’re looking for a primer on those areas, you’d be better served by Wikipedia/Wolfram, sites dedicated to those areas, or proper coursework. More importantly, my understanding of certain concepts might not be as robust as a skilled professional in either of those areas but I’m confident enough that I can describe what I see in everyday life enough with classical mechanics to be proficient in what’s called applied mechanics (that was actually my strongest point).

What I wanted to talk about here is something that I’m sure every game developer has dealt with at some point in time when designing a 2D game (strictly 2D). But to best describe what I’m getting at, I should probably start with an example.

Moving a block from one point to another is a relatively simple task to accomplish. Assuming that you’re not using an origin offset of some type, moving from point A to point B would look like this:

A simple affine transformation
A simple affine transformation

Geometrically speaking, this can be accomplished by a simple affine transformation. However, even though you could get away with expressing this event with an affine transformation, it’s not taking into account how this would happen in the real world. Even autonomous movement doesn’t occur without some type of external force being applied to the object to make it move in a certain direction. That being said, an affine transformation like this wouldn’t actually happen without some force being applied to the rectangle to make it move from vector A to vector B. Visually, the player may or may not be able to tell the difference between which method you chose to use. But we all know which one is more fun. 🙂

With that example, I wanted to point out that even in the most seemingly simple situations, it’s really easy to avoid the use of classical mechanics. But should you even if you could?

The really nice thing about classical mechanics is that the rules for movement, collision, and forces are all already laid bare before you. Even better is that these rules and observations are and have been made about real-world objects and these rules can be expressed mathematically (thus you’re translation point into software). At that point, it’s nothing more than to write a utility class or a series of methods that parameterize those expressions and make arbitrary calls to them in code as needed.

Ignoring classical mechanics means that you’re basically left to invent your own set of rules for these behaviors. Not only would that mean that things would probably not do what a player would expect them to do, but it makes a significant amount of work for a developer.

One particular point of difficulty for developers looking to migrate to using classical mechanics would be the change in understanding of objects in the game world. You can no longer look at your objects and entities as mere rectangles and circles with dimensions based in pixels. Now you have to start thinking about how these objects relate to real-world counterparts. Gravity now comes into play thus properties like mass, density, volume, etc.. are all now factors. It’s not enough to simply say “the user pressed this key so now I call this method to do a transformation to make the player move from here to here”. Now it’s more or less along the lines of “the user pressed this key so based on the current factors like gravity, applied friction of the area they’re standing on, if the wind is blowing or not and how fast, how fast can they move in the direction requested and move them accordingly”.

It all comes with the territory transition though.

A really simple but fun exercise for this transition would be to try and write a Pong clone implementing as much of classical mechanics as possible. It’d be fun to discuss this so I think I might try to do so soon.