Project2-Bug+AI

=Bug AI= Bugs in the OTV Miner game simply eat any Os3 that has been mined. They do not attack the ship and have no offensive mechanisms at their disposal. They will be free roaming in the final release, but in my project they are static until an Os3 is released from an asteroid and then one bug will instantly start moving toward the Os3 and tried to eat it before the player's ship can recovered the mined element.

The Bug is a simple GameObject that is created in the LoadContent method to start the game, seen below. code format="csharp" bugs = new List; for (int i = 0; i < maxBugs; i++) {   GameObject bug = new GameObject(GetRandomBug); bug.IsAlive = true; bug.Position = GetRandomPostionOnScreen; bugs.Add(bug); } code Notice two new methods here: GetRandomBug and GetRandomPostionOnScreen. GetRandomBug simply loads in a sprite randomly from two separate files (Red and Green Bug). code format="csharp" private Texture2D GetRandomBug {   double num = (random.NextDouble * 100); if (num <= 50) return Content.Load("Sprites\\bug1"); else return Content.Load("Sprites\\bug2"); } code GetRandomPositionOnScreen method will be used by multiple GameObjects when starting the game to insert bugs, enemy ships, and asteroids randomly into a starting position.

code format="csharp" private Vector2 GetRandomPostionOnScreen {   Vector2 pos = new Vector2; pos.X = random.Next(graphics.GraphicsDevice.Viewport.Width); pos.Y = random.Next(graphics.GraphicsDevice.Viewport.Height); return pos; } code The actual AI of the Bug is handled when a Os3 element is release from an asteroid. The method SendReleaseOs3Alert is called and a bug is "assigned" to retrieve the Os3. The calculation of rotation and velocity in the method was used from my solution of Les's problem of firing lasers from a rotating ship. It took me wiping off the dust of a trigonometry book in order to figure out exactly what I need. I posted this solution to the ListServ in order to save others time, if they were experiencing a similar issue. code format="csharp" private void SendReleaseOs3Alert(GameObject target) {   foreach (GameObject bug in this.bugs) {    if (bug.IsAlive && !bug.Busy) {       double dx = (double)(bug.XPos - target.XPos); double dy = (double)(bug.YPos - target.YPos); bug.Rotation = -(float)(Math.Atan2(dx, dy)); double atan = Math.Atan2((float)Math.Cos(bug.Rotation), (float)Math.Sin(bug.Rotation)); bug.Velocity = new Vector2((float)Math.Cos(atan), -(float)Math.Sin(atan)) * 1.0f; bug.Busy = true; break; }   } } code I also added another property to the GameObject class called Busy. This is simply a boolean flag that would tells whether or not an object is currently tracking an element. This was needed to keep the same bug going after all the elements. Currently it is only used in with Bugs.

As with all objects on the screen an Update function was added to keep the bugs moving during game play. The UpdateBugs method updates position and detects if a bug intersects an Os3 element. If an intersection occurs the bug stops, set to not busy anymore, and the Os3 is removed from screen.

code format="csharp" private void UpdateBugs {   foreach (GameObject bug in bugs) {   if (bug.IsAlive) {       if (!viewportRect.Contains(new Point((int)bug.XPos, (int)bug.YPos))) {       bug.Position -= bug.Velocity; bug.Velocity = Vector2.Zero; bug.Busy = false; continue; }       bug.Position += bug.Velocity; Rectangle bugRect = new Rectangle(       (int)bug.XPos,        (int)bug.YPos,        bug.Sprite.Width,        bug.Sprite.Height); foreach (ElementObject element in elements) {       if (element.Type == ElementType.OsmiumOre && element.IsAlive) {           Rectangle eleRect = new Rectangle(            (int)element.XPos,            (int)element.YPos,            element.Sprite.Width,            element.Sprite.Height); if (eleRect.Intersects(bugRect)) {           bug.Busy = false; bug.Velocity = Vector2.Zero; element.IsAlive = false; break; }       }        }

}   } } code This leaves one last problem, what happens when a bug is set on course but the players ship gets to the Os3 first? I solved this problem by allowing the bug to continue on its path until it reaches the edge of the screen. When that happens, the bug is backed up one unit of position (to get it off the edge of the screen) and then set its Velocity to zero and Busy to false. This happens in the first if statement after the check if a bug IsAlive, in the above code segment.

The only way to stop a bug from eating the Os3 to kill it, which is accomplished by firing a laser and hitting the bug. This code occurs in the UpdateLasers function while going through the player's fired lasers. code format="csharp" foreach (GameObject bug in bugs) {	if (bug.IsAlive) {   		Rectangle bugRect = new Rectangle(			(int)bug.XPos,			(int)bug.YPos,			bug.Sprite.Width,			bug.Sprite.Height); if (laserRect.Intersects(bugRect)) {		bug.IsAlive = false; laser.IsAlive = false; continue; } } code

The following code segment was added to the Draw method in order to display the bug to the screen.

code format="csharp" foreach (GameObject bug in this.bugs) {   if (bug.IsAlive) spriteBatch.Draw(bug.Sprite,       bug.Position,        null,        Color.White,        bug.Rotation,        bug.Center, 1.0f,        SpriteEffects.None, 0); } code A screenshot was taken from game play to show a bug tracking a Os3 (white) element.

I circled the bug that is tracking the Os3 element. Notice the rotation and velocity (path to object) are correct. The other bugs on the screen are still in their initial starting place and haven't moved. If another Os3 was released before the bug that is circled got to its destination, then another bug would be assigned to retrieve the next element.