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

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

Embed Size (px)

Citation preview

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

AI & 2D Development

COSC 315Fall 2014

Bridget M. Blodgett

Page 2: 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

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

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

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

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;

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

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);

}

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

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

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

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

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

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;

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

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;

}

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

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!

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

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

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

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

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

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;

}}

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

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