AI & 2D Development COSC 315 Fall 2014 Bridget M. Blodgett

Preview:

Citation preview

AI & 2D Development

COSC 315Fall 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 constructorpublic Random rnd{get; private set;}rnd = new Random();

• We also need some class variables to define the frequency of enemy spawnsint 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 SpriteManagerprivate 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 runningnextSpawnTime -= 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 spriteListprivate 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.PresentationParameters.BackBufferHeight – frameSize.Y));

speed = new Vector2(((Game1)Game).rnd(Next(enemyMinSpeed, enemyMaxSpeed), 0);break;

case 1:position = new Vector2( Game.GraphicsDevice.PresentationParameters.BackBufferWidth, ((Game1)Game).rnd.Next(0,Game.GraphicsDevice.PresentationParameters.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.BackBufferHeight);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<Texture2D>(@”images\skullball”), 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 methodpublic bool IsOutOfBounds(Rectangle clientRect) {

if(position.X < -frameSize.X || position.X > clientRect.Width || position.Y < -frameSize.Y || 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