/*
* ColonySim.cs
* Authors: Mike Dapiran, Adam Nabinger, Bradley R. Blankenship
* 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 ColonySim.GUI;
using ColonySim.Structures;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using tAC_Engine;
using tAC_Engine.Graphics;
using tAC_Engine.Graphics.Cameras;
using tAC_Engine.Graphics.Entities;
using TACParticleEngine;
using Util;
namespace ColonySim
{
///
/// This is the main type for your game
///
public class ColonySim : GameScreen
{
public ColonySim(bool pTutorialMode)
{
tutorialOn = pTutorialMode;
}
public ColonySim(string gameFile)
{
tutorialOn = false;
this.gameFile = gameFile;
}
#region Enums
///
/// Enumeration of the available mini game tokens
///
public enum MiniGameTokenTypes
{
///
/// Defines a token of security type
///
Security,
///
/// Defines a token of military type
///
Military,
///
/// Defines a token of prosperity type
///
Prosperity
}
///
/// The enumeration of timing constant values. This is how much time
/// per each non-annual tick.
///
public enum TimingValues
{
///
/// Longest amount of time between each non-annual tick
///
REALLY_SLOW = 25000,
///
/// Somewhat longer amount of time between each non-annual tick
///
SLOW = 20000,
///
/// Average amount of time between each non-annual tick
///
NORMAL = 15000,
///
/// Somewhat shorter amount of time between each non-annual tick
///
FAST = 10000,
///
/// Shortest amount of time between each non-annual tick
///
REALLY_FAST = 5000
}
///
/// The cursor modes
///
public enum CursorMode
{
///
/// Defines the construct cursor mode
///
CONSTRUCT,
///
/// Defines the select cursor mode
///
SELECT,
///
/// Defines the select delete mode
///
DELETE,
///
/// Defines the command placement cursor mode
///
COMMAND_PLACEMENT,
///
/// Defines a lack of cursor mode
///
NONE
}
#endregion
#region Constants
///
/// The number of ticks per an annual tick.
///
public static int TICKS_PER_ANNUAL = 20;
///
/// The threshold for upkeeps.
///
public static int UPKEEP_THRESHOLD = 10;
///
/// The maximum amount of upkeep per turn.
///
public static float MAXIMUM_UPKEEP = 0.75f;
///
/// The stepping values for upkeeps.
///
public static float UPKEEP_STEP = 0.03f;
///
/// The minimum zoom level.
///
public static float MINIMUM_ZOOM = 5.0f;
///
/// The maximum zoom level.
///
public static float MAXIMUM_ZOOM = 40.0f;
///
/// The maximum tilt degree for the camera.
///
public static float MAXIMUM_TILT = MathHelper.PiOver2 - MathHelper.Pi / 18;
///
/// The minimum tilt degree for the camera.
///
public static float MINIMUM_TILT = MathHelper.Pi / 6;
///
/// The timing to use for the ticker telling the player to place the
/// Command Post.
///
public static float COMMAND_POST_PLACEMENT_LIFETIME = -1;
#endregion
#region Test Fields
// List of all of the structures lists for the tiers
readonly List mS0 = new List();
readonly List mS1 = new List();
readonly List mS2 = new List();
readonly List mS3 = new List();
// List of all the resource lists for the tiers
readonly List mR0 = new List();
readonly List mR1 = new List();
readonly List mR2 = new List();
readonly List mR3 = new List();
// The four Tiers that are accessible
Tier mTier0;
Tier mTier1;
Tier mTier2;
Tier mTier3;
#endregion
#region Fields
///
/// The current timing value
///
public static int CurrentTimingValue = (int)TimingValues.REALLY_FAST;
// The current elapsed time
private TimeSpan mElapsedTime;
// The current number of normal ticks
private int mCurrentTicks;
//GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
// Whether we are running or not
private bool mIsRunning;
// The previous moust click, and vertices for the click
private Vector2 mPreviousMousClick = Vector2.Zero;
private Vector3 vert1 = Vector3.Zero;
private Vector3 vert2 = Vector3.Zero;
private Vector3 vert3 = Vector3.Zero;
private Vector3? mPointInSpace;
private bool insideBoundingBox;
// The scrolling area bounds and speed
private const float SCREEN_SCROLL_AREA = .005f;
private const float SCREEN_SCROLL_SPEED = .5f;
// The current model, texture, and building asset
private Structure mCurrentStructure;
// The ghost model and the plane model
private EntityModel mGhostModel;
private EntityModel mPlane;
private EntityModel mBackground;
private EntityModel mBackgroundBottom;
// The popup window sprite
private PopupSprite testPopup;
// The input handler and input handling values
private InputHandler mInputHandler;
private bool mZoomIn;
private bool mZoomOut;
private bool mRotateRight;
private bool mRotateLeft;
// List of resource sprites
private readonly List mResourceSprites = new List();
// The camera for the player
private Perspective3DCamera mPlayerCam;
private bool mMouseMoved;
private Vector2 mPreviousMouseLoc = Vector2.Zero;
private bool cameraMode;
// The particle manager and particle engines for connections
private ParticleManager mParticleManager;
// All current structures and selected structures
private Structure mSelectedStructure;
// The font for dialogs
private SpriteFont mDialogtextfont;
// The last structure to be placed
// NOTE: Unused?
private Structure mLastStructure;
// The manager for managing technologies
private readonly TechManager mTechManager = new TechManager();
// The logger for building placement
private readonly StructurePlacementLogger mBuildingLogger = new StructurePlacementLogger();
// The viewports
private Viewport mStandardViewport;
private Viewport mBuildViewport;
private Tutorial mTutorial;
private readonly bool tutorialOn;
// The GUI for the colony sim
private ColonySimGUIScreen mGui;
// The current mouse location
private Vector2 mouseLocation = Vector2.Zero;
// The number of objects being drawn
private int objectDrawn;
// Whether the mouse is inside of the view area or not
private bool mouseInsideViewArea;
// The world grid for the colony
private Grid mWorldGrid;
// The current cursor mode
private CursorMode mCurCursorMode = CursorMode.NONE;
// The colony's status info
private readonly ColonySimStatusInformation mStatusInfo = new ColonySimStatusInformation();
// The mini game manager
private MiniGameManager mMiniGameManager;
// If the game file has been loaded from the first load.
private bool hasLoadedFromStart;
// The saved game file to be loaded.
private readonly string gameFile;
#endregion
#region Properties
public InputHandler InputHandler
{
get { return mInputHandler; }
}
///
/// Gets/Sets whether or not the colony sim is currently running
///
public bool IsRunning
{
get { return mIsRunning; }
set
{
mIsRunning = value;
// Change the component states as needed
if (mIsRunning)
{
// Go through for each component
foreach (DrawableGameScreenComponent comp in Components)
{
// If it's a grid component
if (comp is GridComponent)
{
// Disable it
comp.Enabled = true;
}
}
}
else
{
// Go through for each component
foreach (DrawableGameScreenComponent comp in Components)
{
// If it's a grid component
if (comp is GridComponent)
{
// Disable it
comp.Enabled = false;
}
}
}
}
}
///
/// Gets/Sets the transparent draw order
///
public int TransparentDrawOrder { get { return DrawOrder + 3; } }
public int BillboardDrawOrder{ get { return DrawOrder + 4;}}
///
/// Gets/Sets the particle effects draw order
///
public int ParticleDrawOrder { get { return DrawOrder + 2; } }
///
/// Gets/Sets the solid draw order
///
public int SolidDrawOrder { get { return DrawOrder + 1; } }
///
/// Gets/Sets the GUI display draw order
///
public int TopDrawOrder { get { return DrawOrder + 4; } }
///
/// Gets the colony sims status info
///
public ColonySimStatusInformation StatusInfo { get { return mStatusInfo; } }
///
/// Gets/Sets the current structure
///
internal Structure CurrentStructure
{
get { return mCurrentStructure; }
set
{
mCurrentStructure = value;
// Update the ghost model
if (mCurrentStructure != null)
{
mGhostModel.ModelPath = mCurrentStructure.ModelPath;
mGhostModel.TexturePath = mCurrentStructure.TexturePath;
mGhostModel.ReloadModel();
}
}
}
///
/// Gets/Sets the current cursor mode.
///
internal CursorMode CurrentCursorMode
{
get { return mCurCursorMode; }
set
{
// Then change some values based on the type
if (value == CursorMode.CONSTRUCT && mCurCursorMode != CursorMode.CONSTRUCT)
{
// Make the plane visible
mPlane.Visible = true;
mPlane.Enabled = true;
mWorldGrid.DrawBuildArea = true;
//// Go through the grid's structures
//foreach (Structure structure in mWorldGrid.GridStructures)
//{
// // Make it's build area visible
// structure.BuildAreaVisible = true;
//}
}
else if (value != CursorMode.CONSTRUCT && mCurCursorMode == CursorMode.CONSTRUCT)
{
// Make it invisible
mPlane.Visible = false;
mPlane.Enabled = false;
mWorldGrid.DrawBuildArea = false;
//// Go through the grid's structures
//foreach (Structure structure in mWorldGrid.GridStructures)
//{
// // Make it's build area visible
// structure.BuildAreaVisible = false;
//}
}
// Set the cursor mode
mCurCursorMode = value;
// Clear the selected structure
mSelectedStructure = null;
}
}
#endregion
#region Initialization
///
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
///
public override void Initialize()
{
mWorldGrid = new Grid(128, 128, Content);
//AddComponent(mWorldGrid);
//mWorldGrid.DrawOrder = TransparentDrawOrder;
// Create the GUI
mGui = new ColonySimGUIScreen(this, mWorldGrid);
mInputHandler = GetInputHandler();
mInputHandler.Initialize();
mInputHandler.LoadBindings(typeof(EventCodes), RootDirectory + @"\testkeybindings.txt");
//mInputHandler.Bind(Keys.OemTilde, InputHandler.Trigger.Pressed, (int)EventCodes.TestingKeybindings);
//mInputHandler.Bind(InputHandler.MouseButtons.Left, InputHandler.Trigger.Released, (int)EventCodes.ReleaseLeftTrigger);
//mInputHandler.SaveBindings(typeof(EventCodes), RootDirectory + @"\testkeybindings.txt");
AutoClear(DrawOrder - 1);
mTechManager.LoadTechnology(RootDirectory + @"\TechList.xml");
// Initialize the logger
mBuildingLogger.Initialize();
// Initialize the starting values for the status log
mStatusInfo.Money = 20000;
mStatusInfo.Resources.Add(ResourceCode.A1, 100);
mStatusInfo.Resources.Add(ResourceCode.B1, 100);
mStatusInfo.Resources.Add(ResourceCode.C1, 100);
//List temp = new List();
//temp.Add(mTechManager.CreateTechnology("Tech1", 10f, new List()));
//temp.Add(mTechManager.CreateTechnology("Tech2", 20f, new List()));
//mTechManager.CreateTechnology("Tech2-1", 10f, temp);
// Create the mini game manager
mMiniGameManager = new MiniGameManager();
#if !DEBUG
TrapMouse();
#endif
#if DEBUG
ShowFPS();
#endif
// Base call
base.Initialize();
IsRunning = false;
}
///
/// Reinitializes any needed values
///
public override void Reinitialize()
{
// Base call
base.Reinitialize();
// If we're not enabled
if (!Enabled)
{
// Enable us
Enable();
// If a mini-game was played
if (MiniGameInfo.HasPlayed)
{
// Evaluate any mini-game information that was gained
ScoreMiniGame();
}
}
foreach (Structure s in mWorldGrid.GetAllStructures())
{
s.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
s.UpdateConnectionIcons();
}
foreach (Structure s in mS0)
{
s.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
s.UpdateConnectionIcons();
}
foreach (Structure s in mS1)
{
s.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
s.UpdateConnectionIcons();
}
foreach (Structure s in mS2)
{
s.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
s.UpdateConnectionIcons();
}
foreach (Structure s in mS3)
{
s.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
s.UpdateConnectionIcons();
}
}
#endregion
#region Activation
///
/// Enable this screen to run.
///
public override void Enable()
{
// Enable us
base.Enable();
// Reset our viewport
GraphicsDevice.Viewport = mBuildViewport;
}
///
/// Disables us until further notice.
///
public override void Disable()
{
// Base call
base.Disable();
// Set the viewport to the original one
GraphicsDevice.Viewport = mStandardViewport;
}
#endregion
#region Update
///
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
///
/// Provides a snapshot of timing values.
public override void Update(GameTime gameTime)
{
#region Test Input
// Test the tiering
if (StatusInfo.Tier.NextTier != null)
{
// If we have a number of plays for doing the next tier
if (StatusInfo.Tier.NextTier.RequiredPlays <= StatusInfo.MiniGamesCompleted)
{
// Upgrade to the next tier
StatusInfo.Tier = StatusInfo.Tier.NextTier;
// Upgfrade the GUI
mGui.UpgradeTier(StatusInfo.Tier);
}
}
#endregion
Point mousePoint = mInputHandler.MouseLocation;
mouseLocation = new Vector2(mousePoint.X, mousePoint.Y);
if (mouseLocation != Vector2.Zero)
mMouseMoved = true;
if (!mMouseMoved)
mouseLocation = new Vector2((mBuildViewport.Width / 2f), (mBuildViewport.Height / 2f));
#region CameraUpdates
Vector3 perpVectRight = Vector3.Normalize(Vector3.Cross(mPlayerCam.Eye - mPlayerCam.LookAt, Vector3.Up)) * SCREEN_SCROLL_SPEED;
cameraMode = Keyboard.GetState().IsKeyDown(Keys.LeftAlt) || Keyboard.GetState().IsKeyDown(Keys.RightAlt);
#region Scrolling
// Initialize the temporary values
Vector3 tempEye = mPlayerCam.Eye;
Vector3 tempLookAt = mPlayerCam.LookAt;
//if (mouseLocation.X < mStandardViewport.X + (mStandardViewport.Width * SCREEN_SCROLL_AREA) ||
// mouseLocation.X > mStandardViewport.X + (mBuildViewport.Width - (mStandardViewport.Width * SCREEN_SCROLL_AREA)) ||
// mouseLocation.Y < mStandardViewport.Y + (mBuildViewport.Height * SCREEN_SCROLL_AREA) ||
// mouseLocation.Y > mStandardViewport.Y + (mStandardViewport.Height - (mStandardViewport.Height * SCREEN_SCROLL_AREA)))
//{
//inital check to make sure we need to calculate the perpendicular vector, as this can be quite time intensive
//due to normalizing and cross product vector calculations
bool hasMoved = false;
// Mouse scrolling
if (mouseLocation.X < (mStandardViewport.Width * SCREEN_SCROLL_AREA))
{
//mPlayerCam.Eye = mPlayerCam.Eye + perpVectRight;
mPlayerCam.LookAt = mPlayerCam.LookAt + (perpVectRight * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
else if (mouseLocation.X > (mStandardViewport.Width - (mStandardViewport.Width * SCREEN_SCROLL_AREA)))
{
//mPlayerCam.Eye = mPlayerCam.Eye - perpVectRight;
mPlayerCam.LookAt = mPlayerCam.LookAt - (perpVectRight * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
if (mouseLocation.Y < mStandardViewport.Height * SCREEN_SCROLL_AREA)
{
Vector3 perpVectForward = Vector3.Cross(perpVectRight, Vector3.Up);
//mPlayerCam.Eye = mPlayerCam.Eye + perpVectForward;
mPlayerCam.LookAt = mPlayerCam.LookAt + (perpVectForward * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
else if (mouseLocation.Y > (mStandardViewport.Height - (mStandardViewport.Height * SCREEN_SCROLL_AREA)))
{
Vector3 perpVectForward = Vector3.Cross(perpVectRight, Vector3.Up);
//mPlayerCam.Eye = mPlayerCam.Eye - perpVectForward;
mPlayerCam.LookAt = mPlayerCam.LookAt - (perpVectForward * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / ( 3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
// Keyboard Movement, bad I know, but it works fast
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
Vector3 perpVectForward = Vector3.Cross(perpVectRight, Vector3.Up);
//mPlayerCam.Eye = mPlayerCam.Eye + perpVectForward;
mPlayerCam.LookAt = mPlayerCam.LookAt - (perpVectForward * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
Vector3 perpVectForward = Vector3.Cross(perpVectRight, Vector3.Up);
//mPlayerCam.Eye = mPlayerCam.Eye + perpVectForward;
mPlayerCam.LookAt = mPlayerCam.LookAt + (perpVectForward * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
//mPlayerCam.Eye = mPlayerCam.Eye - perpVectRight;
mPlayerCam.LookAt = mPlayerCam.LookAt - (perpVectRight * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
//mPlayerCam.Eye = mPlayerCam.Eye + perpVectRight;
mPlayerCam.LookAt = mPlayerCam.LookAt + (perpVectRight * (Vector3.Distance(mPlayerCam.Eye, mPlayerCam.LookAt) / (3 * (MAXIMUM_ZOOM - MINIMUM_ZOOM))));
hasMoved = true;
}
// If we've moved
if (hasMoved)
{
// cast a ray into the grid and see if it intersects the grid
float? modelTemp = Picker.RayIntersectsModel(
Picker.CalculateCursorRay(new Vector2((float)mBuildViewport.Width / 2, (float)mBuildViewport.Height / 2),
mPlayerCam.Projection, mPlayerCam.View, mBuildViewport),
mPlane, out insideBoundingBox, out vert1, out vert2,
out vert3, out mPointInSpace);
// If it's null
if (modelTemp == null)
{
// Set the eye back
// mPlayerCam.Eye = tempEye;
mPlayerCam.LookAt = tempLookAt;
}
mPlayerCam.UpdateCamera();
}
//}
#endregion
if (Keyboard.GetState().IsKeyDown(Keys.LeftControl) || Keyboard.GetState().IsKeyDown(Keys.RightControl))
{
// If the normal is within a certain bounds
float delta = mPreviousMouseLoc.Y - mouseLocation.Y;
if ((mPlayerCam.Eye - mPlayerCam.LookAt).Length() > MINIMUM_ZOOM && delta > 0)
{
mPlayerCam.Offset -= (delta) * .05f;
//mPlayerCam.Eye = mPlayerCam.Eye + Vector3.Normalize(mPlayerCam.LookAt - mPlayerCam.Eye) * SCREEN_SCROLL_SPEED;
//LightingManager.CurrentEffect.Parameters["View"].SetValue(playerCam.View);
}
else if((mPlayerCam.Eye - mPlayerCam.LookAt).Length() < MAXIMUM_ZOOM && delta < 0)
{
mPlayerCam.Offset -= (delta) * .05f;
}
}
//else if (mZoomOut)
//{
// // If the normal is within a certain bounds
// if ((mPlayerCam.Eye - mPlayerCam.LookAt).Length() < MAXIMUM_ZOOM)
// {
// mPlayerCam.Offset += .1f;
// //mPlayerCam.Eye = mPlayerCam.Eye - Vector3.Normalize(mPlayerCam.LookAt - mPlayerCam.Eye) * SCREEN_SCROLL_SPEED;
// //LightingManager.CurrentEffect.Parameters["View"].SetValue(playerCam.View);
// }
//}
if (cameraMode)
{
#region Camera Rotation
float xDist = mPreviousMouseLoc.X - mouseLocation.X;
//if (mRotateRight)
//{
mPlayerCam.Rotation += (xDist * .01f) * (Vector3.Distance(mPlayerCam.LookAt, mPlayerCam.Eye) / (MAXIMUM_ZOOM - MINIMUM_ZOOM));
//}
//else if (mRotateLeft)
//{
//mPlayerCam.Rotation -= .1f * (Vector3.Distance(mPlayerCam.LookAt, mPlayerCam.Eye) / (MAXIMUM_ZOOM - MINIMUM_ZOOM));
//}
#endregion
#region Camera Zoom
//if (mZoomIn)
//{
// // If the normal is within a certain bounds
// if ((mPlayerCam.Eye - mPlayerCam.LookAt).Length() > MINIMUM_ZOOM)
// {
// mPlayerCam.Offset -= .1f;
// //mPlayerCam.Eye = mPlayerCam.Eye + Vector3.Normalize(mPlayerCam.LookAt - mPlayerCam.Eye) * SCREEN_SCROLL_SPEED;
// //LightingManager.CurrentEffect.Parameters["View"].SetValue(playerCam.View);
// }
//}
//else if (mZoomOut)
//{
// // If the normal is within a certain bounds
// if ((mPlayerCam.Eye - mPlayerCam.LookAt).Length() < MAXIMUM_ZOOM)
// {
// mPlayerCam.Offset += .1f;
// //mPlayerCam.Eye = mPlayerCam.Eye - Vector3.Normalize(mPlayerCam.LookAt - mPlayerCam.Eye) * SCREEN_SCROLL_SPEED;
// //LightingManager.CurrentEffect.Parameters["View"].SetValue(playerCam.View);
// }
//}
#endregion
#region Camera Tilt
//bool mTiltUp = false;
//bool mTiltDown = false;
//bool tilted = false;
//tempEye = mPlayerCam.Eye;
//KeyboardState state = Keyboard.GetState();
//if (state.IsKeyDown(Keys.Down))
//{
// mTiltDown = true;
//}
//else
//{
// mTiltDown = false;
//}
//if (state.IsKeyDown(Keys.Up))
//{
// mTiltUp = true;
//}
//else
//{
// mTiltUp = false;
//}
float distY = mPreviousMouseLoc.Y - mouseLocation.Y;
// See if we should tilt up.
//if (mTiltUp)
//{
// Set that we did tilt
//tilted = true;
// Rotate the camera
//mPlayerCam.Eye = mPlayerCam.Eye + (mPlayerCam.View.Up * SCREEN_SCROLL_SPEED);
mPlayerCam.Tilt += (distY * .015f) * (Vector3.Distance(mPlayerCam.LookAt, mPlayerCam.Eye) / (MAXIMUM_ZOOM - MINIMUM_ZOOM));
//}
// See if we should tilt down
//else if (mTiltDown)
//{
// // Set that we did tilt
// //tilted = true;
// // Rotate the camera
// //mPlayerCam.Eye = mPlayerCam.Eye - (mPlayerCam.View.Up * SCREEN_SCROLL_SPEED);
// mPlayerCam.Tilt += .075f * (Vector3.Distance(mPlayerCam.LookAt, mPlayerCam.Eye) / (MAXIMUM_ZOOM - MINIMUM_ZOOM));
//}
// If we tilted
//if (tilted)
//{
// // Create the ray and normalize the direction
// Vector3 ray = mPlayerCam.LookAt - mPlayerCam.Eye;
// ray.Normalize();
// // The normal
// Vector3 planeNormal = Vector3.Up;
// // Get the angle between the plane and the ray
// double dotProduct = Vector3.Dot(planeNormal, -ray);
// double angle = Math.Acos(dotProduct);
// // Make the degree version
// double degreeAngle = angle / MathHelper.TwoPi * 360;
// double degreeMax = MAXIMUM_TILT / MathHelper.TwoPi * 360;
// double degreeMin = MINIMUM_TILT / MathHelper.TwoPi * 360;
// // If this angle is greater than or less than the angle
// if (angle > MAXIMUM_TILT || angle < MINIMUM_TILT)
// {
// // Set the eye
// mPlayerCam.Eye = tempEye;
// }
//}
#endregion
}
mPreviousMouseLoc = mouseLocation;
mPlayerCam.UpdateCamera();
LightingManager.CurrentEffect.Parameters["View"].SetValue(mPlayerCam.View);
LightingManager.CameraPosition = mPlayerCam.Eye;
foreach (Structure s in mWorldGrid.GridStructures)
{
s.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
}
/*if (testPopup is FourWayHubPopUp)
((FourWayHubPopUp)testPopup).UpdateCamera(mPlayerCam);
*/
foreach (EntityBillboardSprite ebs in mResourceSprites)
{
ebs.View = mPlayerCam.View;
ebs.Projection = mPlayerCam.Projection;
}
#endregion
mouseInsideViewArea = false;
if (mouseLocation.X >= mBuildViewport.X && mouseLocation.X <= mBuildViewport.X + mBuildViewport.Width &&
mouseLocation.Y >= mBuildViewport.Y && mouseLocation.Y <= mBuildViewport.Y + mBuildViewport.Height)
{
mouseInsideViewArea = true;
}
if (mouseInsideViewArea)
{
Picker.RayIntersectsModel(Picker.CalculateCursorRay(mouseLocation, mPlayerCam.Projection, mPlayerCam.View, mBuildViewport), mPlane, out insideBoundingBox, out vert1, out vert2, out vert3, out mPointInSpace);
//if (mPointInSpace != null)
//{
// Vector3? centerofGridSquare = new Vector3((float)Math.Floor(mPointInSpace.Value.X) + .5f, 0,
// (float)Math.Floor(mPointInSpace.Value.Z) + .5f);
//}
}
if (mPointInSpace.HasValue &&
(mCurCursorMode == CursorMode.CONSTRUCT || mCurCursorMode == CursorMode.COMMAND_PLACEMENT) &&
mCurrentStructure != null && mouseInsideViewArea)
{
// Set the ghost model as visible and move it to the correct point
mGhostModel.Visible = true;
// Declare the different transform matrices
Matrix translation = Matrix.CreateTranslation(mWorldGrid.CenterOfModel(mPointInSpace.Value, mCurrentStructure));
Matrix rotation = Matrix.Identity;
//mGhostModel.TransformationMatrix = Matrix.CreateTranslation(mWorldGrid.CenterOfModel(mPointInSpace.Value, mCurrentStructure));
// Now based on the current structure, transform it a little more
if (mCurrentStructure is TransportStructure)
{
// Then display us as correctly based on face
//switch (((TransportStructure)mCurrentStructure).Running)
//{
// case TransportStructure.Runnings.Positive_X:
// rotation = Matrix.CreateRotationY(3 * MathHelper.PiOver2);
// break;
// case TransportStructure.Runnings.Negative_X:
// rotation = Matrix.CreateRotationY(MathHelper.PiOver2);
// break;
// case TransportStructure.Runnings.Positive_Y:
// rotation = Matrix.CreateRotationY(MathHelper.Pi);
// break;
//}
TransportStructure t = mCurrentStructure as TransportStructure;
Point p = new Point((int)mPointInSpace.Value.X, (int)mPointInSpace.Value.Z);
t.Running = mWorldGrid.getProperRunningForTransportStructure(p, t.GetType());
mGhostModel.ModelPath = t.ModelPath;
mGhostModel.TexturePath = t.TexturePath;
mGhostModel.ReloadModel();
// Set Rotation.
rotation = t.getRotationForRunning(t.Running);
}
// Set the ghost models matrices
mGhostModel.TransformationMatrix = rotation * translation;
}
else
{
// We must not be in view
mGhostModel.Visible = false;
}
#region Update Input Handling
// Handle input
while (mInputHandler.HasEvent())
{
// Get the current event and switch on its code
InputEvent inputEvent = mInputHandler.GetNextEvent();
// If it's a mouse event and the event is inside the GUI
if (!mGui.IsInside(inputEvent) || inputEvent is KeyInputEvent)
{
switch ((EventCodes)inputEvent.EventCode)
{
// Place the given building at the ghost model's location
case EventCodes.PlaceBuilding:
// If we're in construction mode
#region Construct
if (mCurCursorMode == CursorMode.CONSTRUCT && mouseInsideViewArea)
{
// Set the current mouse position information
mPreviousMousClick.X = ((MouseInputEvent)inputEvent).X;
mPreviousMousClick.Y = ((MouseInputEvent)inputEvent).Y;
// If we suffice to place the model
if (mPointInSpace != null && mCurrentStructure != null &&
mStatusInfo.Money >= mCurrentStructure.Cost &&
mStatusInfo.EnoughResources(mCurrentStructure.ResourceCosts))
{
// Get the point in the grid we're at
Point p = new Point((int)mPointInSpace.Value.X, (int)mPointInSpace.Value.Z);
// Create the new structure to add
Structure newStructure = mCurrentStructure.Clone();
newStructure.Visible = true;
// If the added structure is a transport structure opposite of what is there
if ((newStructure is Road && mWorldGrid[p.X, p.Y] is Tube) ||
(newStructure is Tube && mWorldGrid[p.X, p.Y] is Road))
{
// Change the structure to add to this
Structure newStruct = new RoadTubeCrossing(Content,
ColonyStrings.MODEL_PATH + ColonyStrings.Red_Blue_Crossing_Model, null);
newStruct.Name = newStructure.Name;
newStruct.FootPrintSize = newStructure.FootPrintSize;
newStruct.Cost = newStructure.Cost;
newStruct.BuildRadius = newStructure.BuildRadius;
newStruct.DrawOrder = newStructure.DrawOrder;
newStruct.TechniqueName = newStructure.TechniqueName;
newStruct.RequiresBuildArea = newStructure.RequiresBuildArea;
newStruct.AlphaMapPath = ColonyStrings.MODEL_PATH + ColonyStrings.ALPHAMAP_PATH + ColonyStrings.Tube_Four_AlphaMap;
newStructure = newStruct;
newStructure.ReloadModel();
// remove the original object in the grid
mWorldGrid[p.X, p.Y].Dispose();
mWorldGrid[p.X, p.Y] = null;
}
// Add it to the grid
if (mWorldGrid.AddStructure(newStructure,p))
{
// If it worked, then add it to us
AddComponent(newStructure);
if (newStructure is Entertainment)
{
AddComponent((newStructure as Entertainment).TransparentModel);
}
if (newStructure.BillboardRefs != null)
{
foreach (EntityBillboardSprite e in newStructure.BillboardRefs)
{
e.DrawOrder = BillboardDrawOrder;
AddComponent(e);
}
}
inputEvent.EventArgs = newStructure;
// Record the placement of the structure
mBuildingLogger.LogAddition(newStructure);
// Subtract the costs from us
mStatusInfo.Money -= newStructure.Cost;
mStatusInfo.SpendResources(newStructure.ResourceCosts);
newStructure.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
//
//// If it was a transport structure
//if (newStructure is TransportStructure)
//{
// // Update it
// (newStructure as TransportStructure).setDisplayForRunning();
//}
}
// Set the last structure as the new structure
mLastStructure = newStructure;
//update any nearby tubes
if (newStructure is TransportStructure)
{
if (newStructure is RoadTubeCrossing)
{
(newStructure as RoadTubeCrossing).Running = TransportStructure.Runnings.Four_Way;
foreach (Structure structure in mWorldGrid.GetNeighbors(newStructure, typeof(Road)))
{
TransportStructure ts = structure as TransportStructure;
if (ts != null)
{
ts.Running = mWorldGrid.getProperRunningForTransportStructure(structure.GridPosition, ts.GetType());
}
}
foreach (Structure structure in mWorldGrid.GetNeighbors(newStructure, typeof(Tube)))
{
TransportStructure ts = structure as TransportStructure;
if (ts != null)
{
ts.Running = mWorldGrid.getProperRunningForTransportStructure(structure.GridPosition, ts.GetType());
}
}
}
else
{
foreach (Structure structure in mWorldGrid.GetNeighbors(newStructure, newStructure.GetType()))
{
TransportStructure ts = structure as TransportStructure;
if (ts != null)
{
ts.Running = mWorldGrid.getProperRunningForTransportStructure(structure.GridPosition, ts.GetType());
}
}
}
// just in case
if(!(newStructure is RoadTubeCrossing))
{
(newStructure as TransportStructure).Running = mWorldGrid.getProperRunningForTransportStructure(newStructure.GridPosition, newStructure.GetType());
}
}
}
}
#endregion
// If we're in selection mode
#region Select
else if (mCurCursorMode == CursorMode.SELECT && mouseInsideViewArea)
{
// Set the amount of time for the pop-up to go away and die
testPopup.GoAwayAndDie(gameTime);
Structure TempLastSelectedStructure = mSelectedStructure;
// Clear the selected structure
mSelectedStructure = null;
// go through each of the structures
foreach (Structure s in mWorldGrid.GridStructures)
{
// If we're not the ghost model
if (s != mGhostModel)
{
// See if we intersect the model
float? modelTemp = Picker.RayIntersectsModel(
Picker.CalculateCursorRay(mouseLocation,
mPlayerCam.Projection, mPlayerCam.View, mBuildViewport),
s, out insideBoundingBox, out vert1, out vert2,
out vert3, out mPointInSpace);
// If we intersected a model
if (modelTemp != null && s != TempLastSelectedStructure)
{
// Set the selected model
mSelectedStructure = s;
inputEvent.EventArgs = s;
// Create a new pop-up
testPopup = new PopupInfoBox(Content, @"Textures\GUI\ToolTipBackground",
Vector2.Zero, 500, mDialogtextfont);
// Get the select information string
string selectInfo = mSelectedStructure.SelectInformationString();
// If it's not null
if (selectInfo != null)
{
string[] strings = selectInfo.Split('\n');
// Foreach of the strings
foreach (string str in strings)
{
((PopupInfoBox)testPopup).AddInfoString(str);
}
}
// Set the values as needed, and add the component
testPopup.DrawOrder = TopDrawOrder;
testPopup.SpriteBatch = spriteBatch;
AddComponent(testPopup);
break;
}
}
}
}
#endregion
// If we're deleting structures
#region Delete
else if (mCurCursorMode == CursorMode.DELETE && mouseInsideViewArea)
{
// The structure to delete
Structure deleteStructure = null;
// Go through each of the structures
foreach (Structure s in mWorldGrid.GridStructures)
{
if (s != mGhostModel)
{
float? modelTemp = Picker.RayIntersectsModel(Picker.CalculateCursorRay(mouseLocation, mPlayerCam.Projection, mPlayerCam.View, mBuildViewport), s, out insideBoundingBox, out vert1, out vert2, out vert3, out mPointInSpace);
if (modelTemp != null)
{
deleteStructure = s;
break;
}
}
}
// If the point in space is not null
if (deleteStructure != null && !(deleteStructure is CommandPost)/*|| deleteStructure is Hub*/)
{
// Set the position to be null and void
mWorldGrid.RemoveStructure(deleteStructure.GridPosition);
inputEvent.EventArgs = deleteStructure;
// Now dispose of the structure
deleteStructure.Dispose();
// Record the deletion of the structure
mBuildingLogger.LogRemoval(deleteStructure);
// Add back half of the cost to our money
mStatusInfo.Money += deleteStructure.Cost / 2;
}
}
#endregion
// If we're in command mode
#region Command Post
else if (mCurCursorMode == CursorMode.COMMAND_PLACEMENT && mouseInsideViewArea)
{
// Set the current mouse position information
mPreviousMousClick.X = ((MouseInputEvent)inputEvent).X;
mPreviousMousClick.Y = ((MouseInputEvent)inputEvent).Y;
// If we suffice to place the model
if (mPointInSpace != null && mCurrentStructure != null)
{
// Create the new structure to add
Structure newStructure = mCurrentStructure.Clone();
newStructure.Visible = true;
// Add it to the grid
if (mWorldGrid.AddStructure(newStructure,
new Point((int)mPointInSpace.Value.X,
(int)mPointInSpace.Value.Z)))
{
// If it worked, then add it to us
AddComponent(newStructure);
inputEvent.EventArgs = newStructure;
// Record the placement of the structure
mBuildingLogger.LogAddition(newStructure);
// Update the command post listing
CurrentCursorMode = CursorMode.CONSTRUCT;
mGui.DisplayTicker(string.Empty, 0);
mCurrentStructure = null;
}
// Set the last structure as the new structure
mLastStructure = newStructure;
// Unlock the GUI
mGui.UnlockAll();
}
}
#endregion
break;
// We should quit
case EventCodes.Quit:
base.Done();
return;
// Re-center the view at the correct coordinate
case EventCodes.RecenterView:
List commandPost = mWorldGrid.GetSpecificStructures(typeof(CommandPost));
if (commandPost.Count > 0)
{
mPlayerCam.LookAt = commandPost[0].Center;
mPlayerCam.UpdateCamera();
LightingManager.CurrentEffect.Parameters["View"].SetValue(mPlayerCam.View);
LightingManager.CameraPosition = mPlayerCam.Eye;
}
break;
// Start zooming in
case EventCodes.ZoomInStart:
mZoomIn = true;
break;
// Stop zooming in
case EventCodes.ZoomInStop:
mZoomIn = false;
break;
// Start zooming out
case EventCodes.ZoomOutStart:
mZoomOut = true;
break;
// Stop zooming out
case EventCodes.ZoomOutStop:
mZoomOut = false;
break;
// Start rotating right
case EventCodes.RotateRightStart:
mRotateRight = true;
break;
// Stop rotating right
case EventCodes.RotateRightStop:
mRotateRight = false;
break;
// Start rotating left
case EventCodes.RotateLeftStart:
mRotateLeft = true;
break;
// Stop rotating left
case EventCodes.RotateLeftStop:
mRotateLeft = false;
break;
// Toggle viewing the plane
case EventCodes.TogglePlane:
//mPlane.Visible = !mPlane.Visible;
GraphicsDeviceManager.PreferMultiSampling = !GraphicsDeviceManager.PreferMultiSampling;
break;
//case EventCodes.ResearchTech1:
// mTechManager.StartResearchOnTech("Tech1", true);
// mWorldGrid.RaiseSpecularIntensity();
// //Save();
// break;
//case EventCodes.ResearchTech2:
// mTechManager.StartResearchOnTech("Tech2", true);
// mWorldGrid.LowerSpecularIntensity();
// //Load();
// break;
//case EventCodes.ResearchTech3:
// mTechManager.StartResearchOnTech("Tech2-1", true);
// mWorldGrid.RaiseSpecularPower();
// break;
//case EventCodes.IncrementCurrentResearch:
// mWorldGrid.LowerSpecularPower();
// mTechManager.IncrementResearch();
// break;
case EventCodes.TestingKeybindings:
mGui.Disable();
Raise(new BindingsScreen(mInputHandler, typeof(EventCodes)));
break;
default:
inputEvent.Handled = false;
break;
}
}
if ( mTutorial != null && !mTutorial.Done)
{
mTutorial.HandleEvent(inputEvent);
}
//inputEvent.WriteToLog(
}
#endregion
#region Grid and Status Update
// Only do these things if we're running
if (mIsRunning)
{
// Base update
base.Update(gameTime);
// Add the elapsed times
mElapsedTime += gameTime.ElapsedGameTime;
// Check and see if the number of milliseconds has passed
if ((int)mElapsedTime.TotalMilliseconds >= CurrentTimingValue)
{
// Subtract off the current timing value's milliseconds
mElapsedTime -= new TimeSpan(0, 0, 0, 0, CurrentTimingValue);
// Tick
Tick();
//// If the current number is greater than or equal to the number for annuals
//if (TICKS_PER_ANNUAL <= mCurrentTicks)
//{
// // Do the annual tick
// AnnualTick();
//}
#if DEBUG
Console.WriteLine("Total Game Components: " + Game.Components.Count);
#endif
}
}
if (mSelectedStructure != null && testPopup != null)
{
if (testPopup.Visible && !testPopup.GettingSmaller)
{
Vector3 center = mBuildViewport.Project(mSelectedStructure.Center, mPlayerCam.Projection, mPlayerCam.View, Matrix.Identity)
- new Vector3(mBuildViewport.X, mBuildViewport.Y, 0);
testPopup.Center = new Vector2(center.X, center.Y);
}
if (!testPopup.Visible)
{
Vector3 center = mBuildViewport.Project(mSelectedStructure.Center, mPlayerCam.Projection, mPlayerCam.View, Matrix.Identity)
- new Vector3(mBuildViewport.X, mBuildViewport.Y, 0);
testPopup.Center = new Vector2(center.X, center.Y);
testPopup.PopUp(gameTime, new Point(150, 150));
}
}
if (mSelectedStructure == null && !testPopup.GettingSmaller)
{
testPopup.GoAwayAndDie(gameTime);
}
#endregion
#region Culling
//do some basic culling
mWorldGrid.numPolygons = 0;
objectDrawn = 0;
BoundingFrustum frustum = new BoundingFrustum(mPlayerCam.View * mPlayerCam.Projection);
foreach (DrawableGameScreenComponent gc in this.Components)
{
if (gc is EntityModel && mGhostModel != gc && gc != mPlane && !(gc is EntityBillboardSprite))
{
ContainmentType check = frustum.Contains(BoundingBox.CreateFromSphere(((EntityModel)gc).BoundingSphere));
if (check == ContainmentType.Contains || check == ContainmentType.Intersects)
{
gc.Visible = true;
mWorldGrid.numPolygons += (gc as EntityModel).PolyCount;
objectDrawn++;
}
else
{
gc.Visible = false;
}
}
}
#endregion
#region MiniGameManager
// If the tutorial is null or done
if (mTutorial == null || mTutorial.Done)
{
// update minigame timer
mMiniGameManager.Timer += gameTime.ElapsedGameTime.TotalSeconds;
if (mMiniGameManager.Timer >= mMiniGameManager.CurrentInterval)
{
// Get the mini game that's needed
MiniGameInfo miniGame = mMiniGameManager.GetRandomMiniGame();
mMiniGameManager.CurrentMiniGame = miniGame;
// Increment the number of prompts
++miniGame.NumPrompts;
// Call the GUI to process the generated mini game
mGui.GenerateMiniGame(miniGame);
////if (dialog returns true)
////{
//Raise(miniGame.GameScreen);
//++miniGame.NumPlayed;
//Enabled = false;
////}
////else
////{
//// ++miniGame.NumRejects;
////}
mMiniGameManager.ResetTimer();
mMiniGameManager.UpdateInterval();
}
}
#endregion
}
///
/// Occurs whenever we have elapsed enough time to tick the gird and
/// simulation along.
///
public void Tick()
{
// Set the status info for the grid
mWorldGrid.StatusInfo = StatusInfo;
// Tick the grid
mWorldGrid.Tick(Content);
// get the array of carriers
Carrier[] carriers = mWorldGrid.NewCarriers;
// Get the current carriers
foreach (Carrier carrier in carriers)
{
// Add the carrier
AddComponent(carrier);
}
// Set our status info to that as collected by the grid
//mStatusInfo.Money += mWorldGrid.StatusInfo.Money;
mStatusInfo.Happiness = mWorldGrid.StatusInfo.Happiness * 100;
//mStatusInfo.Population = mWorldGrid.StatusInfo.Population;
//// Foreach of the resources in the grid
//foreach (ResourceCode code in mWorldGrid.StatusInfo.Resources.Keys)
//{
// // See if we have the resource
// if (StatusInfo.Resources.ContainsKey(code))
// {
// // Increment the value
// StatusInfo.Resources[code] += mWorldGrid.StatusInfo.Resources[code];
// }
// else
// {
// // Add the value
// StatusInfo.Resources.Add(code, mWorldGrid.StatusInfo.Resources[code]);
// }
//}
// Set the values anew based on limits
if (mStatusInfo.Money < 0)
{
// Set it to 0
mStatusInfo.Money = 0;
}
else if (mStatusInfo.Money > 99999999)
{
// Set it to 99999999
mStatusInfo.Money = 99999999;
}
// Increment the number of ticks
mCurrentTicks++;
}
///
/// Occurs after a set number of ticks. This handles upkeep adjustments, etc.
///
public void AnnualTick()
{
// Reset the number of ticks
mCurrentTicks = 0;
// Calculate the possible upkeep
float upkeep = mWorldGrid.PlayerStructures;
upkeep /= UPKEEP_THRESHOLD;
upkeep = Math.Min(MAXIMUM_UPKEEP, upkeep * UPKEEP_STEP);
// Take out the upkeep
mStatusInfo.Money -= (int)(mWorldGrid.StatusInfo.Money * upkeep);
// Pause the game
IsRunning = false;
}
#endregion
#region Draw
///
/// This is called when the game should draw itself.
///
/// Provides a snapshot of timing values.
public override void Draw(GameTime gameTime)
{
// Set our viewport
GraphicsDevice.Viewport = mBuildViewport;
#if DEBUG
spriteBatch.Begin();
// Draw the name of the structure to build
//if (mCurrentStructure != null && mCurCursorMode == CursorMode.CONSTRUCT)
//{
// spriteBatch.DrawString(
// mDialogtextfont,
// "Current Build Structure: " + mCurrentStructure.Name,
// new Vector2(40, 30), Color.White);
//}
//// Or draw the name of the selected structure
//else if (mSelectedStructure != null && mCurCursorMode == CursorMode.SELECT)
//{
// spriteBatch.DrawString(
// mDialogtextfont,
// "Current Selected Structure: " + mSelectedStructure.Name,
// new Vector2(40, 30), Color.White);
//}
//// Draw the string to say if we're inside the bounding box
//spriteBatch.DrawString(
// mDialogtextfont,
// "Inside Bounding Box: " + insideBoundingBox,
// new Vector2(40, 50), Color.White);
// Draw the technology stuff
//string tempString = "";
//foreach (Technology t in mTechManager.IdleTechs)
// tempString += t.Name + ", ";
//spriteBatch.DrawString(mDialogtextfont, "Idle Techs: " + tempString, new Vector2(40, 90), Color.White);
//tempString = "";
//foreach (Technology t in mTechManager.InprogressTechs)
// tempString += t.Name + ", ";
//spriteBatch.DrawString(mDialogtextfont, "Inprogress Techs: " + tempString, new Vector2(40, 110), Color.White);
//tempString = "";
//foreach (Technology t in mTechManager.CompletedTechs)
// tempString += t.Name + ", ";
//spriteBatch.DrawString(mDialogtextfont, "Completed Techs: " + tempString, new Vector2(40, 130), Color.White);
// Draw the current cursor mode
//spriteBatch.DrawString(mDialogtextfont,
// "Current Cursor Mode: " + mCurCursorMode,
// new Vector2(40, 70), Color.White);
//spriteBatch.DrawString(mDialogtextfont, "GPOLYS: " + mWorldGrid.numPolygons, new Vector2(40, 140), Color.White);
// Draw the mouse location and if we're in the build area
//spriteBatch.DrawString(mDialogtextfont,
// "Mouse Location: " + mouseLocation,
// new Vector2(40, 90), Color.White);
//spriteBatch.DrawString(mDialogtextfont,
// "Mouse Inside Build Area: " + mouseInsideViewArea,
// new Vector2(40, 110), Color.White);
// Draw the intersection position and structure at that position
//if (mPointInSpace != null)
//{
// Structure testStruct = mWorldGrid.GridContents(new Point((int)((Vector3)mPointInSpace).X, (int)((Vector3)mPointInSpace).Z));
// if (testStruct != null)
// {
// spriteBatch.DrawString(mDialogtextfont, "Structure at grid position: " + ((Structure)testStruct).ModelPath, new Vector2(40, 230), Color.White);
// }
// else
// {
// spriteBatch.DrawString(mDialogtextfont, "Structure at grid position: null", new Vector2(40, 230), Color.White);
// }
//}
//spriteBatch.DrawString(mDialogtextfont, "Cursor Intersects plane at point: " + mPointInSpace, new Vector2(40, 250), Color.White);
spriteBatch.End();
#endif
base.Draw(gameTime);
}
#endregion
#region File I/O
///
/// Load the the given game from file.
///
/// The name of the file to load from
public void Load(string pGameName)
{
List toBeRemoved = new List();
foreach (DrawableGameScreenComponent comp in Components)
{
if (comp is Structure || comp is Asteroid)
{
toBeRemoved.Add((EntityModel)comp);
}
}
foreach (EntityModel mod in toBeRemoved)
{
mod.Dispose();
}
ColonySimStatusInformation info = mWorldGrid.Load(Content, pGameName);
StatusInfo.Money = info.Money;
StatusInfo.Resources = info.Resources;
StatusInfo.Population = info.Population;
foreach (Structure s in mWorldGrid.GetAllStructures())
{
AddComponent(s);
if (s.BillboardRefs != null)
{
foreach (EntityBillboardSprite ebs in s.BillboardRefs)
{
AddComponent(ebs);
}
}
}
foreach (DrawableGameScreenComponent a in mWorldGrid.GetResourceModels(Content))
{
a.DrawOrder = SolidDrawOrder;
AddComponent(a);
if (a is EntityBillboardSprite)
{
mResourceSprites.Add((EntityBillboardSprite)a);
}
}
#region Command Post Detection
// Whether there's a command post or not
bool isCommandPost = false;
// See if the world grid contains a command post
foreach (Structure component in mWorldGrid.GetAllStructures())
{
// If there's a command post
if (component is CommandPost)
{
// Return true
isCommandPost = true;
break;
}
}
// If we don't have a command post
if (!isCommandPost)
{
// The command post
Structure commandPost = new CommandPost(Content, @ColonyStrings.MODEL_PATH + ColonyStrings.Command_Model, null);
commandPost.FootPrintSize = new Vector2(4, 4);
commandPost.BuildRadius = 6;
commandPost.AlphaMapPath = @"images\commandCenter_InTRANS_final";
commandPost.TechniqueName = "SpecularAndDiffuseTransparent";
commandPost.Visible = true;
commandPost.DrawOrder = SolidDrawOrder;
commandPost.ReloadModel();
CurrentCursorMode = CursorMode.CONSTRUCT;
//CurrentStructure = commandPost;
//mGhostModel.Visible = true;
// Set our cursor mode to command post selection
mCurCursorMode = CursorMode.COMMAND_PLACEMENT;
// Set the ticker message and time
//mGui.DisplayTicker("Place Your Command Center Inside the Colony Grid", -1);
// add the feedback event
mGui.GUI_Event_Handled += GUIEventFeedback;
//// Get the values
//Texture2D[] icons = new Texture2D[2];
//string testMessage = "This is a # test message #.";
//// Load the icons
//icons[0] = Content.Load(@"Textures\MoneyIcon");
//icons[1] = Content.Load(@"Textures\PopulationIcon");
//// Display the message
//mGui.DisplayMessagePanel(testMessage, icons, 5000);
}
else
{
// Set the current cursor mode to none
mCurCursorMode = CursorMode.NONE;
mGui.DisplayTicker(string.Empty, 0);
CurrentStructure = null;
mGhostModel.Visible = false;
}
#endregion
// Now tick
Tick();
}
///
/// Save the current game out to file.
///
/// The name of the file to save to
public void Save(string pSaveString)
{
// Save the grid and colony sim information.
mWorldGrid.Save(pSaveString);
}
#endregion
#region Management
///
/// LoadContent will be called once per game and is the place to load
/// all of your content.
///
protected override void LoadContent()
{
// Set the standard viewport
mStandardViewport = GraphicsDevice.Viewport;
// Set the GUI viewport
mGui.GUIViewport = mStandardViewport;
// Set the build viewport
mBuildViewport = GraphicsDevice.Viewport;
// Set the build viewport values
//mBuildViewport.Y = 0;
//mBuildViewport.Height = (int)(mStandardViewport.Height * .85);
// Create the player camera
mPlayerCam = new Perspective3DCamera(
20f,
new Vector3(mWorldGrid.GridCenter.X, 0, mWorldGrid.GridCenter.Y),
Vector3.Up,
MathHelper.PiOver4, mBuildViewport.AspectRatio, .1f, 1000f);
mPlayerCam.Tilt = -(MathHelper.PiOver2);
// Initialize the lighting manager
GraphicsDeviceManager.PreferMultiSampling = true;
LightingManager.Initialize(Content, GraphicsDevice);
//LightingManager.MaxShaderVersion = ShaderProfile.PS_1_1;
// Set the values for the light manager
LightingManager.CurrentEffect.Parameters["View"].SetValue(mPlayerCam.View);
LightingManager.CurrentEffect.Parameters["Projection"].SetValue(mPlayerCam.Projection);
LightingManager.AmbientColor = new Vector4(0.2f, 0.2f, 0.2f, 1f);
LightingManager.SetLightColor(0, new Vector4(.5f, .5f, .5f, 1));
LightingManager.SetLightEnabled(0, true);
LightingManager.SetLightDirection(0, new Vector3(1, .5f, 1));
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
mParticleManager = new ParticleManager(Content, mPlayerCam/*, spriteBatch, mBuildViewport*/);
mParticleManager.DrawOrder = ParticleDrawOrder;
AddComponent(mParticleManager);
mPlane = new EntityModel(Content, @"Models\testPlane", @"Textures\singlePixel", Matrix.CreateScale(.5f));
mPlane.DrawOrder = TransparentDrawOrder;
mPlane.TechniqueName = "Grid";
mPlane.TransformationMatrix *= Matrix.CreateScale(mWorldGrid.GridBounds.Width * 2, 1, mWorldGrid.GridBounds.Height * 2) * Matrix.CreateTranslation(mWorldGrid.GridCenter.X, 0, mWorldGrid.GridCenter.Y);
AddComponent(mPlane);
mPlane.Visible = false;
mBackground = new EntityModel(Content, @"Models\starfield_Background_01");
mBackground.DrawOrder = TransparentDrawOrder;
mBackground.TechniqueName = "AlphaMapSpecularAndDiffuse";
mBackground.AlphaMapPath = @"images\spacePlane_OutTRANS";
AddComponent(mBackground);
mBackground.Visible = true;
mBackgroundBottom = new EntityModel(Content, @"Models\starfield_Background(Nebula)_02");
mBackgroundBottom.DrawOrder = TransparentDrawOrder + 1;
mBackgroundBottom.TechniqueName = "AlphaMapSpecularAndDiffuse";
mBackgroundBottom.AlphaMapPath = @"images\spacePlane_OutTRANS";
AddComponent(mBackgroundBottom);
mBackgroundBottom.Visible = true;
// Set the model for the grid
mWorldGrid.GridModel = mPlane;
// Create the initial ghost model
mGhostModel = new EntityModel(Content, @"Models\testCube", null);
mGhostModel.DrawOrder = TransparentDrawOrder;
mGhostModel.Visible = false;
mGhostModel.TechniqueName = "SpecularAndDiffuseTransparent";
AddComponent(mGhostModel);
//SpriteData spriteData = new SpriteData();
//spriteData.color = Color.White.ToVector4();
//spriteData.position = Vector3.Zero;
//spriteData.size = new Vector2(100,100);
// Load the font
mDialogtextfont = Content.Load(@"Fonts\dialogfont");
testPopup = new PopupInfoBox(Content, @"Textures\BluePixel", new Vector2(400, 400), 250, mDialogtextfont);
testPopup.DrawOrder = TopDrawOrder;
testPopup.SpriteBatch = spriteBatch;
AddComponent(testPopup);
// Add each of the pre-created Grid elements to the drawable field
foreach (DrawableGameScreenComponent a in mWorldGrid.GetResourceModels(Content))
{
a.DrawOrder = SolidDrawOrder;
AddComponent(a);
if (a is EntityBillboardSprite)
{
mResourceSprites.Add((EntityBillboardSprite)a);
}
}
Raise(mGui);
if (tutorialOn)
{
mTutorial = new Tutorial(mGui, mWorldGrid, this);
AddComponent(mTutorial);
mTutorial.StartTutorial();
mTutorial.StartSection();
}
#region Test Tier Initialization
// Creates the tiers, the lists, etc
CreateTierInformation();
// Reset the display ticker so we don't have a message
mGui.DisplayTicker(string.Empty, 0);
#endregion
#region Command Post Detection
if (mTutorial == null)
{
LoadCommandCenter();
}
//LoadCommandCenter();
#endregion
//mGui.LimitStructureSelection(ColonySimGUIScreen.BottomPanelEnumeration.RESIDENTIAL, "Residential_1");
if (!(hasLoadedFromStart || String.IsNullOrEmpty(gameFile)))
{
Load(gameFile);
hasLoadedFromStart = true;
}
}
public void LoadCommandCenter()
{
// Whether there's a command post or not
bool isCommandPost = false;
// See if the world grid contains a command post
foreach (Structure component in mWorldGrid.GetAllStructures())
{
// If there's a command post
if (component is CommandPost)
{
// Return true
isCommandPost = true;
break;
}
}
// If we don't have a command post
if (!isCommandPost)
{
// The command post
Structure commandPost = new CommandPost(Content, @ColonyStrings.MODEL_PATH + ColonyStrings.Command_Model, null);
commandPost.FootPrintSize = new Vector2(4, 4);
commandPost.BuildRadius = 6;
commandPost.AlphaMapPath = @"images\commandCenter_InTRANS_final";
commandPost.TechniqueName = "SpecularAndDiffuseTransparent";
commandPost.Visible = true;
commandPost.DrawOrder = SolidDrawOrder;
commandPost.ReloadModel();
CurrentCursorMode = CursorMode.CONSTRUCT;
CurrentStructure = commandPost;
mGhostModel.Visible = true;
// Set our cursor mode to command post selection
mCurCursorMode = CursorMode.COMMAND_PLACEMENT;
// Set the ticker message and time
//mGui.DisplayTicker("Place Your Command Center Inside the Colony Grid", -1);
// add the feedback event
mGui.GUI_Event_Handled += GUIEventFeedback;
// Lock the GUI to force the user to place the command post first
mGui.LockAll();
//// Get the values
//Texture2D[] icons = new Texture2D[2];
//string testMessage = "This is a # test message #.";
//// Load the icons
//icons[0] = Content.Load(@"Textures\MoneyIcon");
//icons[1] = Content.Load(@"Textures\PopulationIcon");
//// Display the message
//mGui.DisplayMessagePanel(testMessage, icons, 5000);
}
}
///
///
///
public void CreateTierInformation()
{
// Create the structures for the structure lists
#region Tier 1
// Create the mining plant
MiningPlant miningPlant = new MiningPlant(Content, @"Models\miningStation_FBX_FINAL", null);
miningPlant.BuildRadius = 0;
miningPlant.Name = "Mining_Plant";
miningPlant.StructureIcons[0] = Content.Load(@"Textures\GUI\03a_commercialMiningDn");
miningPlant.StructureIcons[1] = Content.Load(@"Textures\GUI\03a_commercialMiningUp");
miningPlant.RequiresBuildArea = false;
miningPlant.Cost = 250;
// Create the tier 1 factory
Factory factoryTier1 = new Factory(Content, @"Models\refineryFBX\refinery", null);
factoryTier1.FootPrintSize = new Vector2(3, 3);
factoryTier1.BuildRadius = 4;
factoryTier1.Name = "Factory_1";
factoryTier1.RequiresBuildArea = true;
factoryTier1.Cost = 500;
factoryTier1.StructureIcons[0] = Content.Load(@"Textures\GUI\03a_refineryDn");
factoryTier1.StructureIcons[1] = Content.Load(@"Textures\GUI\03a_refineryUp");
factoryTier1.ResourceConversions.Add(ResourceCode.A0, ResourceCode.A1);
factoryTier1.ResourceConversions.Add(ResourceCode.B0, ResourceCode.B1);
factoryTier1.ResourceConversions.Add(ResourceCode.C0, ResourceCode.C1);
factoryTier1.OutputValue = 5;
// Create the factory billboard sprites
SpriteData data = new SpriteData();
data.color = Color.White.ToVector4();
data.position = Vector3.Zero;
data.size = new Vector2(150, 150);
factoryTier1.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp", @"Textures\GUI\01a_redTransportUp", data);
factoryTier1.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
foreach (EntityBillboardSprite e in factoryTier1.BillboardRefs)
{
e.DrawOrder = BillboardDrawOrder;
e.Visible = false;
AddComponent(e);
}
// Create the tier 1 residential
Residential residentialTier1 = new Residential(Content, @"Models\loResBuilding_Final", null);
residentialTier1.Cost = 350;
residentialTier1.FootPrintSize = new Vector2(2, 2);
residentialTier1.BuildRadius = 4;
residentialTier1.Name = "Residential_1";
residentialTier1.RequiresBuildArea = true;
residentialTier1.StructureIcons[0] = Content.Load(@"Textures\GUI\02a_residentialTierOneDn");
residentialTier1.StructureIcons[1] = Content.Load(@"Textures\GUI\02a_residentialTierOneUp");
residentialTier1.AlphaMapPath = @"images\resBuilding_INUV_01TRANS";
residentialTier1.TechniqueName = "AlphaMapSpecularAndDiffuse";
residentialTier1.Happiness = 0.25f;
residentialTier1.MaximumPopulation = 500;
residentialTier1.ReloadModel();
// Create the tier 1 commercial
Commercial commercialTier1 = new Commercial(Content, ColonyStrings.MODEL_PATH + ColonyStrings.Commercial_Model, null);
commercialTier1.FootPrintSize = new Vector2(2, 2);
commercialTier1.BuildRadius = 4;
commercialTier1.Name = "Commercial_1";
commercialTier1.RequiresBuildArea = true;
commercialTier1.StructureIcons[0] = Content.Load(@"Textures\GUI\03b_commercialMallDn");
commercialTier1.StructureIcons[1] = Content.Load(@"Textures\GUI\03b_commercialMallUp");
commercialTier1.Cost = 400;
commercialTier1.MoneyGenerated = 25;
commercialTier1.ResourceCosts.Add(ResourceCode.A1, 10);
commercialTier1.ResourceCosts.Add(ResourceCode.B1, 10);
commercialTier1.ResourceCosts.Add(ResourceCode.C1, 0);
commercialTier1.RequiredResources.Add(ResourceCode.A1, 1);
commercialTier1.RequiredResources.Add(ResourceCode.B1, 1);
commercialTier1.RequiredResources.Add(ResourceCode.C1, 1);
// Create the commercial structure icons
SpriteData commerceData = new SpriteData();
commerceData.color = Color.White.ToVector4();
commerceData.position = Vector3.Zero;
commerceData.size = new Vector2(150, 150);
commercialTier1.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp",
@"Textures\GUI\01a_redTransportUp", commerceData);
commercialTier1.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
foreach (EntityBillboardSprite e in commercialTier1.BillboardRefs)
{
e.DrawOrder = BillboardDrawOrder;
e.Visible = false;
AddComponent(e);
}
// Create the tier 1 entertainment
EntityModel transparentEntertainment = new EntityModel(Content, @"Models\entertainmentDome_01", @"Textures\BluePixel");
transparentEntertainment.TechniqueName = "SpecularAndDiffuseTransparent";
transparentEntertainment.DrawOrder = TransparentDrawOrder;
Entertainment entertainmentTier1 = new Entertainment(Content, @"Models\entertainmentBody_01",null,transparentEntertainment);
entertainmentTier1.FootPrintSize = new Vector2(2, 2);
entertainmentTier1.BuildRadius = 4;
entertainmentTier1.Name = "Entertainment_1";
entertainmentTier1.RequiresBuildArea = true;
entertainmentTier1.StructureIcons[0] = Content.Load(@"Textures\GUI\02c_entertainmentCtrDn");
entertainmentTier1.StructureIcons[1] = Content.Load(@"Textures\GUI\02c_entertainmentCtrUp");
entertainmentTier1.Cost = 400;
entertainmentTier1.ResourceCosts.Add(ResourceCode.A1, 0);
entertainmentTier1.ResourceCosts.Add(ResourceCode.B1, 10);
entertainmentTier1.ResourceCosts.Add(ResourceCode.C1, 10);
entertainmentTier1.HappinessModifier = 0.02f;
// Create the entertainment icons
SpriteData entertainmentData = new SpriteData();
entertainmentData.color = Color.White.ToVector4();
entertainmentData.position = Vector3.Zero;
entertainmentData.size = new Vector2(150, 150);
entertainmentTier1.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp",
@"Textures\GUI\01a_redTransportUp", entertainmentData);
entertainmentTier1.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
foreach (EntityBillboardSprite e in entertainmentTier1.BillboardRefs)
{
e.DrawOrder = BillboardDrawOrder;
e.Visible = false;
AddComponent(e);
}
#endregion
#region Tier 2
// Tier 2 Residential
Residential residentialTier2 = new Residential(Content, @"Models\resHi_FBX_FINAL", null);
residentialTier2.Cost = 600;
residentialTier2.ResourceCosts.Add(ResourceCode.A2, 20);
residentialTier2.ResourceCosts.Add(ResourceCode.B2, 0);
residentialTier2.ResourceCosts.Add(ResourceCode.C2, 20);
residentialTier2.FootPrintSize = new Vector2(2, 2);
residentialTier2.BuildRadius = 4;
residentialTier2.Name = "Residential_2";
residentialTier2.RequiresBuildArea = true;
residentialTier2.StructureIcons[0] = Content.Load(@"Textures\GUI\02b_residentialTierTwoDn");
residentialTier2.StructureIcons[1] = Content.Load(@"Textures\GUI\02b_residentialTierTwoUp");
residentialTier2.AlphaMapPath = @"images\resBuilding_INUV_01TRANS";
residentialTier2.TechniqueName = "AlphaMapSpecularAndDiffuse";
residentialTier2.Happiness = 0.50f;
residentialTier2.MaximumPopulation = 1000;
residentialTier2.ReloadModel();
// Tier 2 factory
Factory factoryTier2 = new Factory(Content, @"Models\refineryFBX\refinery", null);
factoryTier2.FootPrintSize = new Vector2(3, 3);
factoryTier2.BuildRadius = 4;
factoryTier2.Name = "Factory_1";
factoryTier2.RequiresBuildArea = true;
factoryTier2.Cost = 500;
factoryTier2.StructureIcons[0] = Content.Load(@"Textures\GUI\03a_refineryDn");
factoryTier2.StructureIcons[1] = Content.Load(@"Textures\GUI\03a_refineryUp");
factoryTier2.ResourceConversions.Add(ResourceCode.A1, ResourceCode.A2);
factoryTier2.ResourceConversions.Add(ResourceCode.B1, ResourceCode.B2);
factoryTier2.ResourceConversions.Add(ResourceCode.C1, ResourceCode.C2);
factoryTier2.OutputValue = 5;
// Create the factory billboard sprites
SpriteData factory2Data = new SpriteData();
factory2Data.color = Color.White.ToVector4();
factory2Data.position = Vector3.Zero;
factory2Data.size = new Vector2(150, 150);
factoryTier2.LoadConnectionAlert(@"Textures\GUI\01b_blueTransportUp", @"Textures\GUI\01a_redTransportUp", data);
factoryTier2.UpdateIconCamera(mPlayerCam.View, mPlayerCam.Projection);
foreach (EntityBillboardSprite e in factoryTier2.BillboardRefs)
{
e.DrawOrder = BillboardDrawOrder;
AddComponent(e);
}
#endregion
Structure fD1 = factoryTier1.Clone(); fD1.Name = "Factory_4"; fD1.RequiresBuildArea = true;
Structure rD1 = residentialTier1.Clone(); rD1.Name = "Residential_4"; rD1.RequiresBuildArea = true;
Structure cC1 = commercialTier1.Clone(); cC1.Name = "Commercial_3"; cC1.RequiresBuildArea = true;
Structure cD1 = commercialTier1.Clone(); cD1.Name = "Commercial_4"; cD1.RequiresBuildArea = true;
Structure eC1 = entertainmentTier1.Clone(); eC1.Name = "Entertainment_3";
foreach (EntityBillboardSprite e in eC1.BillboardRefs)
{
e.DrawOrder = BillboardDrawOrder;
e.Visible = false;
AddComponent(e);
}
// Add to the lists
mS0.Add(miningPlant); mS0.Add(factoryTier1); mS0.Add(residentialTier1); mS0.Add(commercialTier1); mS0.Add(entertainmentTier1);
//mS1.Add(fB1); mS1.Add(rB1); mS1.Add(cB1); mS1.Add(eA1);
mS2.Add(factoryTier2); mS2.Add(residentialTier2); mS2.Add(cC1); //mS2.Add(eB1);
mS3.Add(fD1); mS3.Add(rD1); mS3.Add(cD1); mS3.Add(eC1);
// Creat the resource lists
mR0.Add(ResourceCode.A0); mR0.Add(ResourceCode.B0); mR0.Add(ResourceCode.C0);
mR1.Add(ResourceCode.A1); mR1.Add(ResourceCode.B1); mR1.Add(ResourceCode.C1);
mR2.Add(ResourceCode.A2); mR2.Add(ResourceCode.B2); mR2.Add(ResourceCode.C2);
mR3.Add(ResourceCode.A3); mR3.Add(ResourceCode.B3); mR3.Add(ResourceCode.C3);
// Create the tiers
mTier3 = new Tier(mS3, mR3, null); mTier3.RequiredPlays = 25;
mTier2 = new Tier(mS2, mR2, mTier3); mTier2.RequiredPlays = 10;
mTier1 = new Tier(mS1, mR1, mTier2); mTier1.RequiredPlays = 0;
mTier0 = new Tier(mS0, mR0, mTier1); mTier0.RequiredPlays = 0;
// Set the current tier
mStatusInfo.Tier = mTier1;
// Upgrade using both Tier 0 and Tier 1
mGui.UpgradeTier(mTier0);
mGui.UpgradeTier(mTier1);
}
///
/// UnloadContent will be called once per game and is the place to unload
/// all content.
///
protected override void UnloadContent()
{ }
///
/// Disposes of any unmanaged objects
///
/// Whether or not this is currently being disposed
protected override void Dispose(bool disposing)
{
if (disposing)
{
spriteBatch.Dispose();
GraphicsDevice.Viewport = mStandardViewport;
mBuildingLogger.Dispose();
List toBeRemoved = new List();
foreach (DrawableGameScreenComponent comp in Components)
{
if (comp is Structure || comp is Asteroid)
{
toBeRemoved.Add((EntityModel)comp);
}
}
foreach (EntityModel mod in toBeRemoved)
{
mod.Dispose();
}
mWorldGrid.Clear(GraphicsDevice);
}
base.Dispose(disposing);
}
///
/// Exits the colony sim, then calls done on the colony sim.
///
public void Done()
{
// Done with this.
foreach (EntityModel em in mWorldGrid.GetAllStructures())
{
em.Visible = false;
em.Enabled = false;
}
base.Done();
}
#endregion
#region Scoring
///
/// Scores the mini game based on feedback.
///
protected void ScoreMiniGame()
{
// Take the reward value, then clear it
MiniGameReward reward = MiniGameInfo.Reward;
MiniGameInfo.Reward = new MiniGameReward();
// Reset the mini game being played
MiniGameInfo.HasPlayed = false;
// Now use this score value to create a reward
StatusInfo.Money += reward.Credits;
StatusInfo.MiniGamesCompleted += 1;
}
#endregion
#region GUI Event Feedback
///
/// Tells the Colony Sim that the GUI handled an event.
///
/// The event that was handled.
/// The extra args (not used)
public void GUIEventFeedback(object pEvent, EventArgs pArgs)
{
(pEvent as InputEvent).Handled = true;
// If we have the tutorial
if (mTutorial != null && !mTutorial.Done)
{
mTutorial.HandleEvent((InputEvent)pEvent);
}
}
#endregion
}
}