/* * Carrier.cs * Authors: 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 Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using ColonySim.Structures; namespace ColonySim { /// /// Defines the carrier object used in the colony sim /// class Carrier : GridComponent { #region Enums /// /// The direction this Carrier is moving. /// public enum Directions { /// /// Defines that the carrier is moving in the positive x direction /// Positive_X, /// /// Defines that the carrier is moving in the positive y direction /// Positive_Y, /// /// Defines that the carrier is moving in the negative x direction /// Negative_X, /// /// Defines that the carrier is moving in the negative y direction /// Negative_Y, /// /// Defines that the carrier isn't moving at all /// None } #endregion #region Fields // Whether we are disposed or not private bool mIsDisposed; /// /// Counter used for keeping carriers together /// protected int bumps; /// /// The direction the carrier's moving /// protected Directions mDirection = Directions.None; /// /// The total distance traveled by the carrier /// public float mDistanceTraveled; /// /// The speed at which the carrier moves /// public float mSpeed; /// /// Current scaling value /// float mScale = 1.0f; /// /// What the carrier is seeking /// Type mDestinationType; #endregion #region Properties /// /// Gets/Sets the destination type /// public Type DestinationType { get { return mDestinationType; } set { mDestinationType = value; } } /// /// Gets/Sets the direction this Carrier is moving. /// public Directions Direction { get { return mDirection; } set { // Only if we're different if (mDirection == value) { return; } // Set the direction value mDirection = value; // Re align us RealignDirection(); } } /// /// Gets whether this is disposed or not. /// public bool IsDisposed { get { return mIsDisposed; } } #endregion #region Constructs /// /// Base constructor /// /// The Content Manager /// The model name /// The texture name /// The reference to the current game grid public Carrier(ContentManager pContent, string pModelName, string pTextureName, Grid pGridReference) : base(pContent, pModelName, pTextureName) { Register(pGridReference); mSpeed = Util.Random.NextFloat(.3f, 1f); } #endregion #region Management /// /// Destroy the Carrier so that it can be gotten rid of. /// public void Destroy() { // Set us to be disabled and not visible Visible = false; Enabled = false; this.mDirection = Directions.None; // Tell the grid to re-enqueu us GridReference.AddToCarrierPool(this); } /// /// Overrides the basic dispose for handling setting of the /// disposed parameter. /// public new void Dispose() { // Set us to being disposed mIsDisposed = true; // Call the base to dispose base.Dispose(); } #endregion #region Update /// /// Update us so that we move just enough to give the appearance of /// smooth movement. /// /// The current game time. public override void Update(GameTime gameTime) { // Base call base.Update(gameTime); // Create the lerp value float distanceToMove = (float)gameTime.ElapsedGameTime.TotalSeconds * mSpeed; // The current location Vector3 currentLocation = m_TransformationMatrix.Translation; Vector3 directionToMove = Vector3.Zero; // Move based on our current move state switch (mDirection) { case Directions.Positive_X: directionToMove = Vector3.Right; break; case Directions.Positive_Y: directionToMove = Vector3.Backward; break; case Directions.Negative_X: directionToMove = Vector3.Left; break; case Directions.Negative_Y: directionToMove = Vector3.Forward; break; case Directions.None: break; } m_TransformationMatrix.Translation = currentLocation + (distanceToMove * directionToMove); mDistanceTraveled += distanceToMove; if (mDistanceTraveled >= 1) { UpdatePosition(); mDistanceTraveled = 0; } } /// /// Has the Carrier update it's information logically, meaning that it /// now treats itself as if a Turn has passed. /// public virtual bool UpdatePosition() { // Move in the direction we need to for the turn switch (mDirection) { // Move us in the Positive X direction case Directions.Positive_X: GridPosition = new Point(GridPosition.X + 1, GridPosition.Y); break; // Move us in the positive Y direction case Directions.Positive_Y: GridPosition = new Point(GridPosition.X, GridPosition.Y + 1); break; // Move us in the negative X direction case Directions.Negative_X: GridPosition = new Point(GridPosition.X - 1, GridPosition.Y); break; // Move us in the negative Y direction case Directions.Negative_Y: GridPosition = new Point(GridPosition.X, GridPosition.Y - 1); break; // Do nothing case Directions.None: break; } Structure contents = GridReference.GridContents(GridPosition); if (!(contents is TransportStructure)) { Destroy(); return false; } else { m_TransformationMatrix.Translation = contents.TransformationMatrix.Translation; return true; } } /// /// Does nothing for carriers /// public override void Tick() { } #endregion #region Utility /// /// Realigns the Carrier and its transformation matrix so that it is /// facing the right direction based on its direction. /// public void RealignDirection() { // The rotation matrix Matrix rotation = Matrix.Identity; // The translation matrix Matrix translation = Matrix.CreateTranslation(m_TransformationMatrix.Translation); // Switch on the direction and set the rotation switch (mDirection) { // No rotation needed case Directions.Positive_X: rotation = Matrix.CreateRotationY(MathHelper.PiOver2); break; // Rotate us 90 degrees case Directions.Positive_Y: //rotation = Matrix.CreateRotationY(3 * MathHelper.PiOver2); break; // Rotate us 180 degrees case Directions.Negative_X: rotation = Matrix.CreateRotationY(3 * MathHelper.PiOver2); break; // Rotate us 270 degrees case Directions.Negative_Y: //rotation = Matrix.CreateRotationY(MathHelper.PiOver2); rotation = Matrix.CreateRotationY(MathHelper.Pi); break; case Directions.None: rotation = Matrix.CreateRotationY(GridReference.GridContents(GridPosition).rotY + MathHelper.PiOver2); break; } // Alter our transform matrix m_TransformationMatrix = Matrix.CreateScale(mScale) * rotation * translation; } /// /// Gets the opposite direction of the given direction /// /// The direction to move opposite of /// The opposite direction of the given direction public Directions Opposite(Directions d) { switch (d) { case Directions.Positive_X: return Directions.Negative_X; case Directions.Negative_X: return Directions.Positive_X; case Directions.Negative_Y: return Directions.Positive_Y; case Directions.Positive_Y: return Directions.Negative_Y; } return d; } #endregion } }