/*
* 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);
}
}
}
}
}
}
}
}