/* * LOSCheckAI.cs * Authors: Karl Orosz * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System.Collections.Generic; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace StarJack { /// /// This class will check if a Game Object is in this objects line of site. /// public class LOSCheckAI : AI, DrawableAI, DefferedTurn { private static Entity mMouse; public static Entity Mouse { get { return mMouse; } set { mMouse = value; } } private static bool mMouseOver; public static bool MouseOver { get { return mMouseOver; } set { mMouseOver = value; } } private static bool mLOSDraw = false; public static void ToggleLOSDraw() { mLOSDraw = !mLOSDraw; } private bool mDraw = false; Tile mLOS; bool[,] mLosGrid; List view; private GameObject mMe; private GameObject mThem; public GameObject LookFor { get { return mThem; } set { mThem = value; } } private GameObject.Direction mLook; int[] sides; int[] temp; int[] myPos; int[] dir; public LOSCheckAI(GameObject tied, GameObject lookFor) { mMe = tied; mThem = lookFor; curPriority = Priority.Low; mLook = mMe.Facing; sides = new int[2] { 0, 0 }; dir = new int[2] { 0, 0 }; temp =new int[2]{0,0}; myPos = new int[2] { 0, 0 }; mLOS = new Tile("LOS"); mLOS.Depth = Room.Depth.Tile - 0.001f ; mLOS.TextureName = "LOS"; mLosGrid = new bool[Room.TILECOUNT, Room.TILECOUNT]; } /// /// This routine will calculate a line between the 2 objects and determine /// if there's any collidable tiles blocking it's view. /// /// public override void TakeTurn(int pTurn, bool deffered) { mDraw = false; //break out if the target un undetectable //if (!mThem.Detectable) { return; } //Resets the los array; for(int a = 0; a < Room.TILECOUNT; a++) { for (int b = 0; b < Room.TILECOUNT; b++) { mLosGrid[a,b] = false; } } //Check direction dir[0]=0; dir[1] = 0; switch (mMe.Facing) { case GameObject.Direction.Down: dir[1] = 1; break; case GameObject.Direction.Up: dir[1] = -1; break; case GameObject.Direction.Left: dir[0] = -1; break; case GameObject.Direction.Right: dir[0] = 1; break; } mMe.Position.CopyTo(myPos, 0); myPos[0] += dir[0]; myPos[1] += dir[1]; view = new List(); view.Add(mMe.Position.Clone() as int[]); if (!mMe.MyRoom.CheckCollision(mMe, myPos)) { sides[0] = 0; sides[1] = 0; //Determines width of view //Up or down if (dir[0] == 0) { bool left; bool leftAdd = false; bool right; bool rightAdd = false; do { //left temp[0] = myPos[0] - sides[0] - 1; temp[1] = myPos[1] + sides[0] * dir[1] + 1 * dir[1]; left = mMe.MyRoom.CheckCollision(mMe, temp); if (!left) { view.Add(temp.Clone() as int[]); sides[0]++; } else if( !leftAdd) { if (temp[0] == mThem.Position[0] && temp[1] == mThem.Position[1]) { view.Add(temp.Clone() as int[]); } leftAdd = true; } //right temp[0] = myPos[0] + sides[1] + 1; temp[1] = myPos[1] + sides[1] * dir[1] + 1 * dir[1]; right = mMe.MyRoom.CheckCollision(mMe, temp); if (!right) { view.Add(temp.Clone() as int[]); sides[1]++; } else if (!rightAdd) { if (temp[0] == mThem.Position[0] && temp[1] == mThem.Position[1]) { view.Add(temp.Clone() as int[]); } rightAdd = true; } } while (!left || !right); } else { bool up; bool upAdd = false; bool down; bool downAdd = false; do { temp[0] = myPos[0] + sides[0] * dir[0] + 1 * dir[0]; temp[1] = myPos[1] - sides[0] - 1; down = mMe.MyRoom.CheckCollision(mMe, temp); if (!down) { view.Add(temp.Clone() as int[]); sides[0]++; } else if (!downAdd) { if (temp[0] == mThem.Position[0] && temp[1] == mThem.Position[1]) { view.Add(temp.Clone() as int[]); } downAdd = true; } temp[0] = myPos[0] + sides[1] * dir[0] + 1 * dir[0]; temp[1] = myPos[1] + sides[1] + 1; up = mMe.MyRoom.CheckCollision(mMe, temp); if (!up) { view.Add(temp.Clone() as int[]); sides[1]++; } else if (!upAdd) { if (temp[0] == mThem.Position[0] && temp[1] == mThem.Position[1]) { view.Add(temp.Clone() as int[]); } upAdd = true; } } while (!down || !up); } } CheckLOS(); } private void CheckLOS() { bool end = false; int[] checkRadial = new int[] { 0, 0 }; foreach (int[] pos in view) { temp = pos.Clone() as int[]; do { end = mMe.MyRoom.CheckCollision(mMe, temp); if (temp[0] == mThem.Position[0] && temp[1] == mThem.Position[1]) { if (mThem.Detectable) { mThem.Detected = true; mDraw = true; mLosGrid[temp[0], temp[1]] = true; } } else { //Checks if the player is within 1 unit of the LOS if (!end &&( (temp[0] - 1 == mThem.Position[0] && temp[1] == mThem.Position[1]) || (temp[0] + 1 == mThem.Position[0] && temp[1] == mThem.Position[1]) || (temp[0] - 1 == mThem.Position[0] && temp[1] - 1 == mThem.Position[1]) || (temp[0] + 1 == mThem.Position[0] && temp[1] - 1 == mThem.Position[1]) || (temp[0] - 1 == mThem.Position[0] && temp[1] + 1 == mThem.Position[1]) || (temp[0] + 1 == mThem.Position[0] && temp[1] + 1 == mThem.Position[1]) || (temp[0] == mThem.Position[0] && temp[1] - 1 == mThem.Position[1]) || (temp[0] == mThem.Position[0] && temp[1] + 1 == mThem.Position[1]))) { mDraw = true; } } if (!end) { mLosGrid[temp[0], temp[1]] = true; } temp[0] += dir[0]; temp[1] += dir[1]; } while (!end); } } public override void Reset() { //nothing } #region DrawableAI Members public void Draw(SpriteBatch pSpriteBatch) { bool draw = false; if (mMouseOver) { int[] tile = Room.CalcTileCoord(new int[] { mMouse.X, mMouse.Y }); if (tile[0] == 8 && tile[1] == 1) { } if (tile[0] == mMe.Position[0] && tile[1] == mMe.Position[1]) { draw = true; } } draw = mDraw; if (mLOSDraw) { draw = true; } if (draw) { int[] pos = new int[] { 0, 0 }; //Draws the los array; for (int a = 0; a < Room.TILECOUNT; a++) { for (int b = 0; b < Room.TILECOUNT; b++) { if (mLosGrid[a, b]) { pos[0] = a; pos[1] = b; mLOS.Position = pos; mLOS.Draw(pSpriteBatch); } } } } } public void LoadContent(ContentManager pContent) { mLOS.LoadContent(pContent); } #endregion } }