//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {License Information: Creative Commons} //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Engine.GameObjects { #region Using Statements using System; using System.Collections; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; using System.Diagnostics; using DarkWynter.Engine; using DarkWynter.Engine.Globals; using DarkWynter.Engine.ObjectLib; using DarkWynter.Engine.GameObjects; using DarkWynter.Stream; using DarkWynter.Engine.Init; using Xclna.Xna.Animation; #endregion /// /// Bots /// public class AI : Player { private Enums_Engine.TurnDirection turnDirection = Enums_Engine.TurnDirection.NOT_SET; private Vector3 Destination = new Vector3(0, 0, 0); private enum State { Goto, Stop, Exit } private State aiState = State.Goto; /// /// Constructor /// public AI(Load gameObjectLoader) : base(gameObjectLoader) { mass.objectType = Enums_Engine.ObjectType.PLAYER; mass.gameObjectPointer = this; } /// /// Load stuff from XML /// /// The Bot node /// ObjectLibrary /// True if load was successful public override bool Load(ObjectLibrary objectLibrary) { if (!base.Load(objectLibrary)) { return false; } health = Statics_Engine.AISettings.AI_MAX_HEALTH; manna = 100; aiState = State.Goto; return true; } /// /// General update function /// /// ObjectLibrary public override void Update(ref ObjectLibrary objectLibrary) { // UpdatePercepts(objectLibrary); if ((aiState == State.Goto) || (Destination != Vector3.Zero)) { //gotoLogic(); } base.Update(ref objectLibrary); } public void SpawnPlayer(ObjectLibrary objectLibrary) { _spawnPosition.Y = objectLibrary.terrain.GetTerrainHeight( spawnPosition.X / Statics_Engine.TerrainSettings.terrainScaleFactor, spawnPosition.Z / Statics_Engine.TerrainSettings.terrainScaleFactor); base.SpawnPlayer(); health = Statics_Engine.AISettings.AI_MAX_HEALTH; } public void gotoLogic() { goToDestination(Destination); if (FuzzyDestination(mass.currentPosition, Destination)) { mass.currentPosition = Destination; Destination = Vector3.Zero; aiState = State.Stop; } } public Vector3 goToDestination(Vector3 destination) { Vector3 Orientation = destination - mass.currentPosition; Orientation.Normalize(); MoveTowardDirection(Orientation); if (DirectionToAngle(Orientation) < Math.PI / 12.0) { // Pass in X + Z as the force to apply in the normal's direction mass.MoveObject((float)Math.Abs(Orientation.X + Orientation.Z), 0.0f); } return destination - this.mass.currentPosition; } private bool FuzzyDestination(Vector3 Position, Vector3 TargetPosition) { if ((Position.X - TargetPosition.X < 20 || TargetPosition.X - Position.X < 20) && (Position.Z - TargetPosition.Z < 20 || TargetPosition.Z - Position.Z < 20)) return true; else return false; } public virtual void MoveTowardDirection(Vector3 direction) { float angle = DirectionToAngle(direction); if (float.IsNaN(angle) || angle < 0.1) { //If the angle is this small or not a number the idea would be NOT to rotate and just to move. } else { // Determine which direction to turn Vector3 toDirection = new Vector3(direction.X, 0, direction.Z); toDirection.Normalize(); Vector3 lookAt = new Vector3(mass.normalVector.X, 0, mass.normalVector.Z); lookAt.Normalize(); Vector3 cross = Vector3.Cross(toDirection, lookAt); if (cross.Y < 0.01) { // Turn Left Rotate(new Vector2(-0.05f, 0.0f)); mass.totalForce = Vector3.Zero; } else { // Turn Right Rotate(new Vector2(0.05f, 0.0f)); mass.totalForce = Vector3.Zero; } } } private float DirectionToAngle(Vector3 direction) { Vector2 diff2 = new Vector2(direction.X, direction.Z); diff2.Normalize(); Vector2 N = new Vector2(mass.normalVector.X, mass.normalVector.Z); N.Normalize(); return (float)Math.Acos((double)(Vector2.Dot(diff2, N))); } //private Enums_Engine.TurnDirection DirectionToOrientation(Vector3 direction) //{ // // Determine which direction to turn // Vector3 toDirection = new Vector3(direction.X, 0, direction.Z); // toDirection.Normalize(); // Vector3 lookAt = new Vector3(mass.normalVector.X, 0, mass.normalVector.Z); // lookAt.Normalize(); // Vector3 cross = Vector3.Cross(toDirection, lookAt); // if (cross.Y < 0.01) // { // return Enums_Engine.TurnDirection.LEFT; // } // else // { // return Enums_Engine.TurnDirection.RIGHT; // } //} } }