AI & 2D Development

advertisement
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
int
int
int
enemySpawnMinMilliseconds = 1000;
enemySpawnMaxmillisends = 2000;
enemyMinSpeed = 2;
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<Texture2D>(@”images\s
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 < -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
Download