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