AI & 2D Development COSC 315 Fall 2014 Bridget M. Blodgett
Artificial Intelligence Why the Turing Test is BS What is the goal of including AI in games? Although genuine AI would be nice we need to start small Making sprites appear randomly is a good first step towards a more natural AI
Random XNA has a built in Random number function – It isn’t great but it works for what we need to do It is a good idea to create a single random variable and then call it for all your randomization needs If you make multiple variables and call them too quickly you could end up making numbers off the same seed – This defeats the purpose of randomness
Making Random Variables The first step is to create some placeholder variables to hold your randomly generated number and initialize it in your game1 class constructor public Random rnd{get; private set;} rnd = new Random(); We also need some class variables to define the frequency of enemy spawns int enemySpawnMinMilliseconds = 1000; int enemySpawnMaxmillisends = 2000; int enemyMinSpeed = 2; int enemyMaxSpeed = 6;
Using SpriteManager Remove the code that makes the stationary sprites from LoadContent The method should only have the player variable now Make a class variable called: – int nextSpawnTime = 0; Make a new method in SpriteManager private void ResetSpawnTime() { nextSpawnTime = ((Game1)Game).rnd.Next( enemySpawnMinMilliseconds, enemySpawnMaxMilliseconds); }
ResetSpawnTimer() Now call your new method in Initialize() This will set up the spawner but adding code to the Update method will get it running nextSpawnTime -= gameTime.ElapsedGameTime.Milliseconds; if(nextSpawnTime < 0) { SpawnEnemy(); ResetSpawnTime(); } Right now this makes a call to a function that doesn’t exist but that will be added next
Spawn Enemy There are several things that need to be done: – The enemy needs a starting position, starting speed, added to the spriteList private void SpawnEnemy(){ Vector2 speed = Vector2.Zero; Vector2 position = Vector2.Zero; Point frameSize = new Point(75,75); } After declaring these variables you need to write code to set them
switch (((Game1)Game).rnd.Next(4)){ case 0: position = new Vector2(-frameSize.X, ((Game1)Game).rnd.Next(0,Game.GraphicsDevice.Present ationParameters.BackBufferHeight – frameSize.Y)); speed = new Vector2(((Game1)Game).rnd(Next(enemyMinSpeed, enemyMaxSpeed), 0); break; case 1: position = new Vector2( Game.GraphicsDevice.PresentationParameters.BackBuffe rWidth, ((Game1)Game).rnd.Next(0,Game.GraphicsDevice.Present ationParameters.BackBufferHeight – frameSize.Y)); speed = new Vector2(- ((Game1)Game).rnd(Next(enemyMinSpeed, enemyMaxSpeed), 0); break;
case 2: position = new Vector2(((Game1)Game).rnd.Next(0,Game.GraphicsDevice.PresentationParameters.BackBufferWidth – frameSize.X), Game.GraphicsDevice.PresentationParameters.BackBuffe rHeight); speed = new Vector2(0, - ((Game1)Game).rnd(Next(enemyMinSpeed, enemyMaxSpeed)); break; case 3: position = new Vector2(((Game1)Game).rnd.Next(0,Game.GraphicsDevice.PresentationParameters.BackBufferWidth – frameSize.X), -frameSize.Y); speed = new Vector2(0,((Game1)Game).rnd(Next(enemyMinSpeed, enemyMaxSpeed)); break; }
spriteList.Add(new AutomatedSprite(Game.Content.Load kullball”), position, new Point(75,75), 10, new Point(0,0), new Point (6,8), speed, “skullcollision”)); } //this closes the method!
Irrelevant Objects Right now if a sprite passes outside the boundary they just keep going This means that the game will get slower the longer it’s played – Why? There are a number of different solutions to this issue
Boundary Rectangles Just like for collisions we can use a rectangle to determine when an object goes outside the window bounds In the sprite class add the following method public bool IsOutOfBounds(Rectangle clientRect) { if(position.X clientRect.Width || position.Y clientRect.Height) { return true; } return false; } Now you need to fix update to check the sprites each call
for (int I = 0; I < spriteList.Count; ++i){ Sprite s = spriteList[i]; s.Update(gameTime, Game.Window.ClientBounds); if (s.collisionRect.Intersects(player.collisionRect)) { spriteList.RemoveAt(i); --i; } if (s.IsOutOfBounds(Game.Window.ClientBounds)) { spriteList.RemoveAt(i); --i; }
Player Aware Sprites So our enemies are still pretty basic and don’t really react to the player Using a simple algorithm that determines the player’s position and moves the sprites accordingly you can make two new types of enemies: chasers and evaders Both of these require making a small modification to the Sprite base class to accept the player’s location