Friday, March 18, 2016

Production Post 4 : "Object State" Architecture

The way I've been writing a lot of my scripts has been similar to what a finite state machine accomplishes. A finite state machine usually implies a somewhat complex AI to make those state changing decisions, but for my purposes I've been running these object states on timers.

The problem is that objects often need to execute a series of functions, in order, when timers are completed. This is especially true when we need to interpolate through a series of positions, rotations, scales, colors, etc for polish. I've seen this problem solved by ugly, ugly boolean checks that increase in complexity and decrease in readability very quickly as more states are required. I've been taking advantage of enums to resolve this.

This is a bit hard to explain, but it's actually a very simple concept, and one that has made my code very readable and easy to add and remove functionalities. So, to explain, I'll use the Wind Level as an example:

The important functionality of the wind level is that an invisible wind represented in code by a changing force vector blows the orbs off screen. It was easy enough to get the base wind blowing, but in order to feel like wind I couldn't just have a constant force vector for the wind, I needed to add turbulence. I accomplished this with a series of interpolations that execute in-order. This is the enum that I used:


Then, in the update loop, I have a switch statement that calls the proper functions for the current "turbulence" (object) state (mTS):


Really simple, highly readable, and yes all of these comments were in there to begin with I didn't just write them for this post. So, the HandleNone() function increments a timer, and when the timer runs out, it resets the timer for the BUILDUP state and changes mTS to BUILDUP. Super easy to follow, and with no nasty boolean checks.

I like to use this kind of structure even if I only have two states (which one would typically default to a boolean variable). This is because whenever there are two states, odds are we'll want to add another one later for some polish reason. In this way, the code becomes very modifiable. Maybe we want to make it so the orbs all shoot off a windy particle effect, but only during the COASTING state. Without having to really search through any code, we can accomplish this very easily by going into the HandleCoasting() function and writing some code there!

In short, using enums to manage object states is a really good idea; it makes your code readable, modifiable, and gives you a mini finite state machine to work with in the future!














No comments:

Post a Comment