/*
* Wormhole.cs
* Authors: August Zinsser, Adam Nabinger
* 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.Graphics;
namespace MaritimeDefender
{
///
/// Creates wormholes in the meteor madness game.
/// The player can connect to a wormhole with their "wormhole connector beam."
/// The wormhole disappears from memory after fading out several seconds after connection, leaving
/// the meteor madness game to spawn a UFO in its location.
///
internal class Wormhole : Collidable
{
#region Constants
// Constant for how fast the wormhole is rotating.
private const float mRotationSpeed = MathHelper.PiOver2;
#endregion
#region Fields
// Whether the wormhole is opening for the player or for an enemy/friendly ship.
private readonly bool mIsPlayer;
// Holds the original spawning position so UFOs can spawn where the wormhole initially appeared.
private readonly float mSpawnedArcPosition;
// Whether the wormhole is visible or not.
private bool mVisible;
// Whether or not the wormhole is currently fading in/out.
private bool mFading;
// Whether the wormhole is currently fading in or fading out.
private bool mFadeIn;
// Counter for the current life of the fade in/out effect.
private float mFadeCounter;
// Total duration of time for the fade in/out effect.
private float mFadeLifeSpan;
// The opacity of the wormhole. Used for fade in/out effect.
private float opacity;
// Rotational position of the base wormhole layer
private float mAngle1;
// Rotational position of the middle wormhole layer
private float mAngle2;
// Texture for the base wormhole layer
private Texture2D mLayer1;
// Texture for the middle wormhole layer
private Texture2D mLayer2;
// Color of the base wormhole layer
private Color mColor1 = Color.White;
// Color of the middle wormhole layer
private Color mColor2 = Color.White;
// Position of the base wormhole layer in terms of x,y coordinates.
private Vector2 mOrigin1;
// Position of the middle wormhole layer in terms of x,y coordinates.
private Vector2 mOrigin2;
// Size of the wormhole in terms of width, height, and depth.
private Vector3 mSpace3DSize;
#endregion
#region Properties
///
/// Gets the size of the wormhole in terms of width, height, and depth.
///
public override Vector3 Size { get { return mSpace3DSize; } }
///
/// Position of the wormhole along the outside circular perimeter
///
public float SpawnedArcPosition { get { return mSpawnedArcPosition; } }
///
/// Gets/Sets the width of the wormhole.
///
public override float Width {
get { return mSpace3DSize.X; }
set { mSpace3DSize.X = value; }
}
///
/// Gets/Sets the height of the wormhole.
///
public override float Height {
get { return mSpace3DSize.Y; }
set { mSpace3DSize.Y = value; }
}
///
/// Gets/Sets whether the wormhole is visible or not.
///
public bool Visible {
get { return mVisible; }
set { mVisible = value; }
}
#endregion
#region Creation
///
/// Constructor
///
/// Width of the wormhole
/// Height of the wormhole
/// Depth of the wormhole
/// Position of the wormhole along the outside circular perimeter
/// Whether the wormhole is for the player or for an enemy/friendly ship
internal Wormhole(float width, float height, float depth, float spawnedArcPosition, bool isPlayer)
{
mSpace3DSize = new Vector3(width, height, depth);
mSpawnedArcPosition = spawnedArcPosition;
mIsPlayer = isPlayer;
}
#endregion
#region Management
///
/// Loads in any necessary information for all content dependent objects
///
/// Reference to the current content manager for loading content
internal void LoadContent(Microsoft.Xna.Framework.Content.ContentManager content)
{
mLayer1 = content.Load(@"MiniGames\WormholeP");
mLayer2 = mIsPlayer ? content.Load(@"MiniGames\WormholeG") : content.Load(@"MiniGames\WormholeR");
mOrigin1 = new Vector2(mLayer1.Width >> 1, mLayer1.Height >> 1);
mOrigin2 = new Vector2(mLayer2.Width >> 1, mLayer2.Height >> 1);
}
#endregion
#region Update
///
/// Performs necessary logic, including position and rotation updates
///
/// Time that has passed in game
internal void Update(GameTime gameTime)
{
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
mAngle1 += mRotationSpeed * dt;
mAngle2 += mRotationSpeed * 1.75F * dt;
if (mAngle1 >= MathHelper.TwoPi)
{
mAngle1 -= MathHelper.TwoPi;
}
if (mAngle2 >= MathHelper.TwoPi)
{
mAngle2 -= MathHelper.TwoPi;
}
// Update fading
if (mFading)
{
if (mFadeIn)
{
mFadeCounter -= dt;
if (mFadeCounter >= 0)
{
opacity = 1.0F - (mFadeCounter / mFadeLifeSpan);
}
else
{
mFadeCounter = 0;
opacity = 1.0F;
mFading = false;
}
mVisible = true;
}
else
{
mFadeCounter -= dt;
if (mFadeCounter >= 0)
{
opacity = mFadeCounter / mFadeLifeSpan;
}
else
{
opacity = 0;
mFadeCounter = 0;
mVisible = false;
mFading = false;
}
}
mColor1 = new Color(255, 255, 255, (byte)(Math.Max(opacity - .25f, 0f) * 255));
mColor2 = new Color(255, 255, 255, (byte)(Math.Max(opacity - .50f, 0f) * 255));
}
}
#endregion
#region Render
///
/// Renders the wormhole and its individual layers
///
/// Reference to the current spritebatch for rendering sprites
/// Reference to the gameboard for graphical dimensions and positions
internal void Draw(SpriteBatch spriteBatch, Space3D gameBoard)
{
// Ignore drawing invisible wormholes
if (!mVisible)
{
return;
}
// Project into screen coordinates
Rectangle projected = Space3D.Project(Position.X, Position.Y, Position.Z, mSpace3DSize.X, mSpace3DSize.Y);
// Draw all layers
float depth = Position.Z - gameBoard.MinZ + Space3D.mMeteorCameraFocalLength;
float depthRange = gameBoard.MaxZ - gameBoard.MinZ + Space3D.mMeteorCameraFocalLength;
// Layer 1
spriteBatch.Draw(
mLayer1,
projected,
null,
mColor1,
mAngle1,
mOrigin1,
SpriteEffects.None,
1F * depth / depthRange
);
// Layer 2
spriteBatch.Draw(
mLayer2,
new Rectangle(projected.X, projected.Y, (int)(projected.Width * .80f), (int)(projected.Height * .80f)),
null,
mColor2,
mAngle2,
mOrigin2,
SpriteEffects.None,
.9999F * depth / depthRange
);
}
#endregion
#region Fade
///
/// Sets the wormhole to fade in with a total fade time equal to the given amount of seconds
///
/// The duration of time in which the wormhole will fade in
internal void FadeIn(float seconds)
{
mFading = true;
mFadeIn = true;
opacity = 0F;
mFadeCounter = seconds;
mFadeLifeSpan = seconds;
}
///
/// Sets the wormhole to fade out with a total fade time equal to the given amount of seconds
///
/// The duration of time in which the wormhole will fade out
internal void FadeOut(float seconds)
{
mFading = true;
mFadeIn = false;
opacity = 1F;
mFadeCounter = seconds;
mFadeLifeSpan = seconds;
}
#endregion
}
}