So I'm starting to run out of topics that interest me for Graphics (and which haven't been covered pretty well in class) so I'm going to take a bit of a break and talk about a programming topic near and dear to my heart: AI!
So last term I talked to Dan Buckstein about some AI stuff and he put me down an interesting path, one filled with weirdly named terms like Fuzzy Logic, and I've gotten the chance to apply a few the fun concepts that I picked up from him. My absolute favourite is Finite State Machines, which are basically anything that can have multiple states which the system will transition between once certain conditions are met. The most basic example of a FSM is a light which switches between on and off when the light switch is put into different positions. Of course, they can get a lot more complex than that (for example, games are FSMs themselves) but for this blog I'll be talking strictly in terms of how they can be applied for AI.
For our enemies in our GDW game, I use a combination of polymorphism and states allowing me to reduce a large portion of the update function for each enemy to just one simple line:
currentState->Execute(dt, this);
Where the variable currentState is a pointer of the root State class, dt is the change in time for the update and this is a pointer to the enemy currently being updated. Now what does this do? Well, firstly I'm going to break down the root State class. This class has 3 functions: Enter, Execute and Exit. Enter is called only when a new state is entered, Execute is called during each update and Exit is called when the current state is being exited. Each state also has a BehaviourTag enumerator so that we can keep track of which state an enemy is in. Now that we have our root class defined, we can derive all other behaviours from it, in this case we have a FollowPath state, MeleeAttack state and Death state. Each one has its own unique Execute function (i.e. the FollowPath state will find the path to the enemies target and follow it while the Death state will count down the enemies death timer) which essentially allows us to swap out the enemies update function while being able to recycle the code between multiple enemy types! I tried to make it a bit more efficient by also making each derived state a singleton as this relies on making a static pointer in an object to its self which is returned with the GetInstance function. This way, we will always only have one instance of each state and won't have to create new ones when we want to change states.
Now then, for another interesting topic which was mentioned earlier: Fuzzy Logic! This is effectively the blending of different behaviours of similar natures. For example, say we have three behaviours which dictate how an enemy will move, these behaviours are Seek, Flee and Wander. The Seek behaviour has the enemy heading directly towards a point or entity, Flee has it moving in the completely opposite direction from a point or entity and Wander has it choosing a random point and moving towards it. These behaviours all return a normalized Vector3 for the enemy to use as a movement direction. By adding weights to each output which sum up to a value of 1.0, we can simulate more than these three behaviours. For example: 0.5 to Seek and 0.5 to Flee will make the enemy stand still while 0.5 to Flee and 0.5 to Wander will make the enemy seem like it's trying to avoid the player but it isn't actively fleeing from them. That's sort of the quick and dirty info for Fuzzy Logic. Unfortunately I have yet to actually apply it with code and only know this bit of theory regarding it but I look forward to getting that opportunity!
So yeah, there's my blog on all the fun AI stuff that I've learned and applied this year. I've greatly enjoyed using FSMs as they help clean up the code drastically, they're highly reusable and they're just so much more flexible than having a collection of if else statements in the update function of an enemy. I hope you've enjoyed reading me ramble on for a...LONG time. I apologize for the length of this blog, but I didn't want to do another that was broken up into two parts.
Next blog: Either BVHs and Mo-cap or Thinking With Portals!
Note:
In regards to the title, if you don't know the reference here it is: http://youtu.be/WnTGaTbR7C0?t=1m33s
Note 2:
Most of this informatoin is what I can recall from Programming Game AI By Example by Mat Buckland, a fantastic book which I was given the chance to borrow and which I keep meaning to purchase for myself.
No comments:
Post a Comment