Asteroids Plus 2.0 - Milestone 18– Adding the enemy AI


Let’s discuss something that I’ve never even remotely attempted before, Artificial Intelligence (AI). 

One of the things that I’d like to take a stab at in this project is to code up an enemy ship that arrives periodically when you get into the game and causes havoc for the player.

How I’m specifying this out initially, and it will change, is using a decision tree to work its way through logic and make decisions about what to do next based on the tree.  Between the decision tree and a series of state machines we’ll be able to code up this enemy.


The initial decision tree will walk through a series of assessments and make decisions regarding what actions to take next.  The plan was to have the enemy assess if its about to get hit by bullets or asteroids and take evasive action as a priority.  Then if its not in danger, it will scan for proximity to the player, and if not close enough, start randomly patrolling the screen.

I had a decent plan going into this, and then I made a terrible decision.  I code vomited the entire AI class all at once.  This is very unusual for me, but I was feeling pretty cocky about it.  Well, what happens is obvious, it needed a ton of debugging.  Hours of it, and I feel that I made my life much more difficult by not iteratively developing it block by block.

Another setback was I way overengineered the plan for this AI, specifically with the evasion branches of the logic.  I fortunately developed the patrol and attack branches first, and one I was playtesting with them, even though its not the most sophisticated logic ever, it worked for the style of game I had.  Adding the evasion logic would have made it twice as complicated, and twice as difficult to debug and test.

The general walkthrough the code looks like this, once you reach level 5, a spawning timer starts, and when its elapsed, the game loop will spawn an enemy ship randomly located on the edge of the playing area.  The enemy is almost a mirror setup as the player, with same health and ammo, and ammo recharging capabilities.  When you get into the update loop there’s a few state machines that need to be discussed.  First things in the update loop are the invincibility delay and ammo recharge logic.

Then you update the physics model for this, by checking if the enemy is using any of its thrusters (forward/reverse).  This then updates the position of the rendering.  This is all VERY similar to the player’s update code.

Then you check for collisions with asteroids and bullets, same as the player and asteroid logic.  Also, include in this portion is the screen collision that creates the screen wrapping effect.

Then you get into the logical state machines.

The outer state machine is called… enemyAIstates…


I use enums to identify these states, as a means of preventing me form screwing them up.  I also set them to strings so when I want to console them or display on the screen what state I’m in I can simply read it.

The attack and patrolling states have inner state machines for each of them: attackStates and patrollingStates.


Each state has to perform an update to that behavior, and then assess the conditions under which it leaves to another state.

One example is the Stopping state.


The stopping state does just that, it decreases the speed of the entity until its low enough.  Once the velocities are low enough, it halts all speed and leaves the state. Some state conditions run only once, some have timer tiks as conditions which are then time based, and some are event based.

The result for this AI class is much simpler than originally planned.  It bounces between patrolling and attacking, until its killed.  This took a ton of debugging, and I had one technically challenging aspect of this class.  The turning logic I really struggled with, and it required some research to address.

Over at math.stackexchange… which apparently is a Stack Overflow for math people *shrug*… I got this article.



This algorithm tells you how to calculate which direction to turn. 

My steps here are… sanitize the angles (normalize angles to 0-360), and then find the lowest number of absolute values of the three equations above.  And the lowest absolute value then if positive is a clockwise turn, and if negative is a counterclockwise turn.  I went with a reducer function for this, but a for loop itself might be the most performant. 


This took a couple tries to get right, but I’m happy with how it turned out.

So here’s to a completed AI class that’s integrated into my main branch now, and is online for playtesting.

 

This currently hosted game site: https://mookie4242.itch.io/asteroids-plus-20

Twitter: @jyoung424242

SlideShare: https://www.slideshare.net/JustinYoung3/next-gen-asteroids

GitHub: https://t.co/utxHxXKdOz

Leave a comment

Log in with itch.io to leave a comment.