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