/* * Room.cs * Authors: Karl Orosz, Brian Chesborough * 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; using System.Collections.Generic; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace StarJack { /// /// Contains information about the tiles and traps etc associated with this room /// public class Room : TimedObject { /// /// The current turn the game is on /// private int mTurn; public int Turn { get { return mTurn; } set { mTurn = value; } } public struct Depth { public static float Tile = 0.9f; public static float Wall = 0.8f; public static float Shadow = 0.85f; public static float GameObject = 0.6f; public static float Enemy = 0.5f; public static float Player = 0.4f; public static float Particle = 0.3f; public static float UI = 0.2f; public static float UIButton = 0.175f; public static float UIIcon = 0.15f; public static float UIText = 0.125f; public static float Mouse = 0.1f; } public struct Shadows { public static String Bottom = "Bottom"; public static String BottomLeftStart = "BottomLeftStart"; public static String BottomrightCorner = "BottomRightCorner"; public static String CornerTop = "CornerTop"; public static String Side = "Side"; public static String SideEnd = "SideEnd"; } //MS public const int ROOM_TURN_TIME = 300; protected Dictionary mShadows; public enum GameState { Load, Hacking, Dungeon, SallyAnne, Caught, TurnRoutines, End, Failure } protected GameState mState; public GameState State { get { return mState; } set { mState = value; } } public const int TILECOUNT = 20; private string mRoomName; public string Name { get { return mRoomName; } set { mRoomName = value; } } readonly Tile[,] mTiles = new Tile[TILECOUNT, TILECOUNT]; public Tile[,] Tiles { get { return mTiles; } } readonly Dictionary mWallShadow = new Dictionary(); //The list of all the game objects in the room. readonly List[,] mPositions = new List[TILECOUNT, TILECOUNT]; public List[,] PositionList { get { return mPositions; } } public List mGameObjects = new List(); public List GameObjects { get { return mGameObjects; } } public List mRemoveList = new List(); public List mTurnRoutines = new List(); // Shared colors for linked objects private Dictionary mLinkedColors = new Dictionary(); PlayerObject mPlayer; public PlayerObject Player { set { mPlayer = value; } get { return mPlayer; } } HackableObject mHacked; public HackableObject Hacked { get { return mHacked; } } protected int[] mStartingPos; public int[] PlayerStartingPos { get { return mStartingPos; } set { mStartingPos = value; } } private readonly Tile mColTile; private SpriteFont mFont; public Room() { mTurn = 0; } /// /// constructor called from World class /// /// list of tiles in room public Room(IList tileList) { mColTile = new Tile("Square"); mColTile.TextureName = "Square"; mRemoveList = new List(); IniShadows(); //parse through tileList and populate 2d array for (int i = 0; i < TILECOUNT; i++) { for (int j = 0; j < TILECOUNT; j++) { int index = (20 * i) + j; mTiles[i, j] = tileList[index]; mTiles[i, j].Position = new int[] { i, j }; //Adds the bucket list mPositions[i, j] = new List(); } } for (int i = 0; i < TILECOUNT; i++) { for (int j = 0; j < TILECOUNT-1; j++) { mTiles[i, j].Group = "Wall"; if (mTiles[i, j].Collision) { mTiles[i, j].TextureName = mTiles[i, j + 1].Collision ? "Ciel" : "Wall"; } else { mTiles[i, j].TextureName = "Floor"; } } } for (int j = 0; j < TILECOUNT; j++) { mTiles[j, TILECOUNT - 1].Group = "Wall"; mTiles[j,TILECOUNT - 1].TextureName = "Ciel"; } CalcShadow(); mState = GameState.Dungeon; mTurn = 0; PlayerStartingPos = new int[] { 1, 1 }; InitColors(); } private void InitColors() { mLinkedColors = new Dictionary(); mLinkedColors.Add(Color.Red, null); mLinkedColors.Add(Color.Blue, null); mLinkedColors.Add(Color.Green, null); mLinkedColors.Add(Color.Yellow, null); mLinkedColors.Add(Color.Orange, null); mLinkedColors.Add(Color.Brown, null); mLinkedColors.Add(Color.Azure, null); mLinkedColors.Add(Color.Pink, null); mLinkedColors.Add(Color.Navy, null); mLinkedColors.Add(Color.Violet, null); mLinkedColors.Add(Color.Teal, null); } public void LoadContent(ContentManager content) { mFont = content.Load(@"Fonts\dialogfont"); foreach (Tile t in mTiles) { t.LoadContent(content); } foreach (String s in mShadows.Keys) { mShadows[s].LoadContent(content); } foreach (GameObject go in mGameObjects) { go.LoadContent(content); } mColTile.LoadContent(content); } public void Update(GameTime gt) { bool deffered = false; //Calculates the turn routines if (mTurnRoutines.Count > 0) { bool finished = true; foreach (TimedTurnRoutine ttr in mTurnRoutines) { if (ttr.State != TimedTurnRoutine.TurnState.Finished) { finished = false; ttr.Update(gt); } } if (finished) { mTurnRoutines.Clear(); State = GameState.Dungeon; deffered = true; } } if (deffered) { TakeTurn(0, true); } if (mTurnRoutines.Count <= 0) { if (mPlayer != null) { mPlayer.Update(gt); if (mPlayer.TurnRoutines.Count > 0) { foreach (TimedTurnRoutine ttr in mPlayer.TurnRoutines) { mTurnRoutines.Add(ttr); } mPlayer.TurnRoutines.Clear(); } } foreach (GameObject go in mGameObjects) { go.Update(gt); if (go.TurnRoutines.Count > 0) { foreach (TimedTurnRoutine ttr in go.TurnRoutines){ mTurnRoutines.Add(ttr); } go.TurnRoutines.Clear(); } } if (mRemoveList.Count > 0) { foreach (GameObject go in mRemoveList) { mGameObjects.Remove(go); go.AIEnable = true; } mRemoveList.Clear(); } if (mTurnRoutines.Count > 0) { State = GameState.TurnRoutines; } } } public void Draw(SpriteBatch pSpriteBatch) { foreach (Tile t in mTiles) { t.Draw(pSpriteBatch); } Tile shadow; foreach (int[] t in mWallShadow.Keys) { shadow = mShadows[mWallShadow[t]]; shadow.Position = t; shadow.Draw(pSpriteBatch); } foreach (GameObject go in mGameObjects) { go.Draw(pSpriteBatch); } /* mColTile.Color = new Color(255, 0, 0, 100); mColTile.Depth = Room.Depth.UI; int count=0; for (int a = 0; a < TILECOUNT; a++) { for (int b = 0; b < TILECOUNT; b++) { foreach (GameObject go in mPositions[a, b]) { if (go.Collision) { count++; mColTile.X = a * Tile.WIDTH; ; mColTile.Y = b* Tile.HEIGHT; mColTile.Draw(pSpriteBatch); } } if (count > 0) { pSpriteBatch.DrawString(mFont, "" + count, new Vector2(a * Tile.WIDTH, b * Tile.HEIGHT), Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, Room.Depth.Mouse); } count = 0; } } * */ } public void EndRoom() { mState = GameState.End; } public void StartHackingPhase(HackableObject hacking) { mState = GameState.Hacking; mHacked = hacking; } public void EndHackingPhase(bool result) { mHacked.Enabled = !result; if (mHacked is SallyAnneObject) { if (result) { StartSallyPhase(mHacked); } else { //mState = GameState.TurnRoutines; mState = GameState.Dungeon; } } else { //mState = GameState.TurnRoutines; mState = GameState.Dungeon; } if (!result) { mPlayer.Detected = true; } } public void StartSallyPhase(HackableObject hacking) { mState = GameState.SallyAnne; mHacked = hacking; } public void EndSallyPhase(bool result) { mState = GameState.Dungeon; } public void AddGameObject(GameObject go) { AddGameObject(go, go.Position); } public void AddGameObject(GameObject go, int[] pos) { mGameObjects.Add(go); mPositions[pos[0], pos[1]].Add(go); setLinkedColor(go as LinkedObject); } /// /// Sets the color for a LinkedObject and the LinkedObject it is linked to. /// /// /// private void setLinkedColor(LinkedObject linkedObject) { if (linkedObject != null) { LinkedObject linkedTo = linkedObject.Linked; if (linkedTo != null) { if (!mLinkedColors.ContainsValue(linkedTo)) { // Give linkedTo the next free color foreach (Color c in mLinkedColors.Keys) { if (mLinkedColors[c] == null) { mLinkedColors[c] = linkedTo; linkedTo.LinkedColor = c; break; } } } linkedObject.LinkedColor = linkedTo.LinkedColor; } } } public void RemoveAtPos(GameObject go){ RemoveAtPos(go, go.Position); } public void RemoveAtPos(GameObject go, int[] pos) { mPositions[pos[0], pos[1]].Remove(go); } public void RemoveObject(GameObject go){ mRemoveList.Add(go); RemoveAtPos(go); go.AIEnable = false; } #region TimedObject Members public void TakeTurn(int pTurn,bool deffered) { mTurn++; foreach (GameObject go in mGameObjects) { go.TakeTurn(mTurn, deffered); } } #endregion public void ChangePosition(GameObject go, int[] newPos) { MoveTurnRoutine mtt = new MoveTurnRoutine(go, newPos); go.TurnRoutines.Add(mtt); ///mTurnRoutines.Add(mtt); // State = GameState.TurnRoutines; mPositions[go.Position[0], go.Position[1]].Remove(go); mPositions[newPos[0], newPos[1]].Add(go); } /// /// /// /// /// A abolsute x,y coord that will be translated to tile coords /// public bool CheckCollisionAbsPos(GameObject go, int[] pos) { pos = CalcTileCoord(pos); return CheckCollision(go, pos); } public static int[] CalcTileCoord(int[] pos) { pos[0] = pos[0] / Tile.WIDTH; pos[1] = pos[1] / Tile.HEIGHT; return pos; } private void IniShadows() { mShadows = new Dictionary(); mShadows.Add(Shadows.Bottom, NewShadowTexture(Shadows.Bottom)); mShadows.Add(Shadows.BottomLeftStart, NewShadowTexture(Shadows.BottomLeftStart)); mShadows.Add(Shadows.BottomrightCorner, NewShadowTexture(Shadows.BottomrightCorner)); mShadows.Add(Shadows.CornerTop, NewShadowTexture(Shadows.CornerTop)); mShadows.Add(Shadows.Side, NewShadowTexture(Shadows.Side)); mShadows.Add(Shadows.SideEnd, NewShadowTexture(Shadows.SideEnd)); } private static Tile NewShadowTexture(string textureName) { Tile temp = new Tile("Shadow"); temp.Group = "Shadow"; temp.TextureName = textureName; temp.Depth = Depth.Shadow; return temp; } public bool CheckCollision(GameObject go, int[] newPos) { bool collision = false; if (newPos[0] < 0 || newPos[0] >= TILECOUNT || newPos[1] < 0 || newPos[1] >= TILECOUNT) { return true; } if (Tiles[newPos[0], newPos[1]].Collision) { collision = true; } else { foreach (GameObject check in PositionList[newPos[0], newPos[1]]) { if (check != go && check.Collision) { collision = true; } } } return collision; } //Calculates the shadows for the room private void CalcShadow() { mWallShadow.Clear(); for (int a = 0; a < TILECOUNT; a++) { for (int b = 0; b < TILECOUNT; b++) { if (mTiles[a, b].Collision) { if (a + 1 < TILECOUNT && !mTiles[a + 1, b].Collision) { if (b - 1 >= 0) { if (mTiles[a, b - 1].Collision && !mTiles[a + 1, b - 1].Collision) { mWallShadow.Add(new int[] { a + 1, b }, Shadows.Side); } else if (mTiles[a, b - 1].Collision && mTiles[a + 1, b - 1].Collision) { mWallShadow.Add(new int[] { a + 1, b },Shadows.CornerTop); } else { mWallShadow.Add(new int[] { a + 1, b }, Shadows.SideEnd); } } } if (a + 1 < TILECOUNT && b+1 < TILECOUNT) { if (!mTiles[a + 1, b + 1].Collision) { if (!mTiles[a + 1, b].Collision && !mTiles[a, b + 1].Collision) { mWallShadow.Add(new int[] { a + 1, b + 1 }, Shadows.BottomrightCorner); } } } if (b + 1 < TILECOUNT && !mTiles[a, b + 1].Collision) { if ( a-1 >=0 && !mTiles[a - 1, b].Collision) { mWallShadow.Add(new int[] { a, b + 1 }, Shadows.BottomLeftStart); } else { mWallShadow.Add(new int[] { a, b + 1 }, Shadows.Bottom); } } } } } } } }