/*
* EntityStimulusPeripheral.cs
* Authors: Mike DeMauro and Brian Murphy
* 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 System.Text;
using tAC_Engine.Graphics.Entities;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using TACParticleEngine.Particles;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Audio;
using TACParticleEngine;
using Random=Util.Random;
using Util;
namespace StellarProspector
{
///
/// Defines the peripheral stimulus that spawns in the outer screen region and how it gets "caught"
///
internal class EntityStimulusPeripheral : EntitySpawnable
{
#region Fields
// The Logger to use for event codes
private Logger mLogger;
// The width of 3D camera used for ParticleEngine
private float mCameraWidth;
// The height of 3D camera used for ParticleEngine
private float mCameraHeight;
// The ParticleManager used for ParticleEngines
private ParticleManager mParticleManager;
// The particle effect representing a fading stimulus
private ParticleEngine mFadeEffect;
// The particle effect representing a tractor beam
private ParticleEngine mTractorBeam;
// Stores the two end points of the tractor beam
private Vector3[] mBeamPositions;
// The direction in which to grab in
private Vector3 mGrabDir = Vector3.Zero;
// The current color of the fade particle effect
private Vector4 mFadeEngineColor = Vector4.Zero;
// The current size of the fade particle effect
private Vector2 mFadeEngineSize = Vector2.Zero;
// The current position of the fade particle effect
private Vector3 mFadeEnginePosition = Vector3.Zero;
#endregion
#region Properties
///
/// Sets the Logger to use for event codes
///
public Logger Logger { set { mLogger = value; } }
///
/// Gets/Sets the width of 3D camera used for ParticleEngine
///
public float CameraWidth
{
get { return mCameraWidth; }
set { mCameraWidth = value; }
}
///
/// Gets/Sets the height of 3D camera used for ParticleEngine
///
public float CameraHeight
{
get { return mCameraHeight; }
set { mCameraHeight = value; }
}
///
/// Gets/Sets the ParticleManager used for ParticleEngines
///
public ParticleManager ParticleManager
{
get { return mParticleManager; }
set { mParticleManager = value; }
}
///
/// Gets/Sets the particle effect representing a fading stimulus
///
public ParticleEngine FadeEffect
{
get { return mFadeEffect; }
set { mFadeEffect = value; }
}
///
/// Gets/Sets the particle effect representing a tractor beam
///
public ParticleEngine TractorBeam
{
get { return mTractorBeam; }
set { mTractorBeam = value; }
}
#endregion
#region Creation
///
/// Creates a new EntityStimulusPeripheral
///
/// The ContentManager used to load content.
/// The name of the texture to load.
public EntityStimulusPeripheral(ContentManager content, string textureName)
: base(content, textureName)
{
mBeamPositions = new Vector3[2];
mMinWaitTime = Settings.StimulusWaitMin;
mMaxWaitTime = Settings.StimulusWaitMax;
}
#endregion
#region Management
///
/// Loads in the necessary information for content dependent objects
///
protected override void LoadContent()
{
base.LoadContent();
mFadeEffect = mParticleManager.Load("ParticleEffects/StimulusFade");
mTractorBeam = mParticleManager.Load("ParticleEffects/TractorBeam");
mTractorBeam.SetEnginePositions(mBeamPositions);
}
#endregion
#region Update
///
/// Updates the EntityStimulusPeripheral. This should be called by XNA.
///
/// Time that has passed so far in game
public override void Update(Microsoft.Xna.Framework.GameTime gameTime)
{
if (mState == SpawnableState.Alive)
{
UpdateFadeEffect();
}
if (mState == SpawnableState.Suspended)
{
UpdateFadeEffect();
UpdateTractorBeam(gameTime);
}
base.Update(gameTime);
}
#endregion
#region State
///
/// Spawn the EntityDistractor at a random position within the given sector's bounds.
/// There is a 20% chance the peripheral stimulus will spawn in a different sector.
///
/// The sector to spawn in
/// If the stimulus can spawn outside the given sector
public override void Spawn(int sectorNum, bool errorEnabled)
{
// If allowed, 20% of the time, spawn the peripheral stimulus in a different sector
if (errorEnabled && Random.Next(5) == 0)
{
int diffSector = Random.Next(3);
if (diffSector >= sectorNum)
{
++diffSector;
}
sectorNum = diffSector;
}
mRadialDistance = Random.Next(mMinSpawnRadius + (int)m_Radius, mMaxSpawnRadius - (int)m_Radius);
double randomAngle = Random.NextDouble() * mSectorAngle;
double bufferAngle = Math.Atan((float)m_Radius / mRadialDistance);
if (randomAngle < bufferAngle)
{
randomAngle = bufferAngle;
}
else if (randomAngle > mSectorAngle - bufferAngle)
{
randomAngle = mSectorAngle - bufferAngle;
}
mTheta = -mSectorAngle * sectorNum - randomAngle;
X = (int)(mRadialDistance * Math.Cos(mTheta) - m_TextureCenter.X + mOrigin.Y);
Y = (int)(mRadialDistance * Math.Sin(mTheta) - m_TextureCenter.Y + mOrigin.X);
Visible = true;
mLifeTime = mMaxLifeTime;
SetFadeEffect();
base.Spawn(sectorNum, errorEnabled);
}
///
/// Inactivates particle effects, sets visible to false and state to Dead.
///
public override void Die()
{
mTractorBeam.SetActive(false);
mFadeEffect.SetActive(false);
Visible = false;
Color = Color.White;
base.Die();
if (mLifeTime <= 0)
{
mLogger.Write((int)EventCodes.MissedPeripheralStimulus, "SP_MissedPeripheralStimulus");
}
}
#endregion
#region Fade Effect
///
/// Updates effects to simulate fading away.
///
private void UpdateFadeEffect()
{
// Modify the stimulus' color, position, and size to reflect fading away
float ratio = (float)(mLifeTime / mMaxLifeTime);
float inverseRatio = 1.0f - ratio;
float scale = ratio + inverseRatio * 0.2f;
X += ((Texture.Width >> 1) - ((int)(Texture.Width * scale) >> 1)) -
((Texture.Width >> 1) - (Width >> 1));
Y += ((Texture.Height >> 1) - ((int)(Texture.Height * scale) >> 1)) -
((Texture.Height >> 1) - (Height >> 1));
Width = (int)(Texture.Width * scale);
Height = (int)(Texture.Height * scale);
Color = new Color(Color.R, Color.G, Color.B, (byte)(ratio * 255));
// Modify the particle effect's color, position, and size to reflect fading away
mFadeEngineColor.X = ratio + inverseRatio * 0.2f;
mFadeEngineColor.Y = mFadeEngineColor.X;
mFadeEngineColor.Z = mFadeEngineColor.X;
mFadeEngineColor.W = ratio * 0.8f + inverseRatio * 0.2f;
mFadeEffect.SetEngineColor(mFadeEngineColor, false);
mFadeEngineSize.X = ratio * 40.0f + inverseRatio * 10.0f;
mFadeEngineSize.Y = mFadeEngineSize.X;
mFadeEffect.SetEngineSize(mFadeEngineSize);
mFadeEnginePosition.X = (Position.X + (Width >> 1) - (GraphicsDevice.Viewport.Width >> 1)) * mCameraWidth;
mFadeEnginePosition.Y = (Position.Y + (Height >> 1) - (GraphicsDevice.Viewport.Height >> 1)) * mCameraHeight;
mFadeEffect.SetEnginePosition(mFadeEnginePosition);
}
///
/// Sets all the parameters needed for the fade effect
///
public void SetFadeEffect()
{
mFadeEffect.SetEnginePosition(new Vector3((Position.X + (Width >> 1) -
(GraphicsDevice.Viewport.Width >> 1)) * mCameraWidth, (Position.Y + (Height >> 1) -
(GraphicsDevice.Viewport.Height >> 1)) * mCameraHeight, 0));
mFadeEffect.SetActive(true);
}
#endregion
#region Tractor Beam
///
/// Sets all the parameters needed for the tractor beam
///
public void SetTractorBeam()
{
mState = SpawnableState.Suspended;
mBeamPositions[0].Y = (mOrigin.Y - (GraphicsDevice.Viewport.Height >> 1)) * mCameraHeight;
mBeamPositions[1].X = (X + (Width >> 1) - (GraphicsDevice.Viewport.Width >> 1)) * mCameraWidth;
mBeamPositions[1].Y = (Y + (Height >> 1) - (GraphicsDevice.Viewport.Height >> 1)) * mCameraHeight;
mTractorBeam.SetActive(true);
mTractorBeam.SetEnginePositions(mBeamPositions);
mFadeEffect.SetEnginePosition(mBeamPositions[1]);
mGrabDir = Vector3.Subtract(mBeamPositions[1], mBeamPositions[0]);
mGrabDir.Normalize();
SoundManager.SoundManager.PlayEffect("WarpIn");
}
///
/// Updates the current position of the tractor beam and stimulus.
///
/// Elapsed time in game
private void UpdateTractorBeam(GameTime gameTime)
{
// TODO: optimize, organize constants
mBeamPositions[1] = mBeamPositions[1] - Vector3.Multiply(mGrabDir, 0.004f * gameTime.ElapsedGameTime.Milliseconds);
Vector3 tempVec = mBeamPositions[1] - mBeamPositions[0];
Position = new Vector2(mBeamPositions[1].X / mCameraWidth - (Width >> 1) +
(GraphicsDevice.Viewport.Width >> 1), mBeamPositions[1].Y / mCameraHeight -
(Height >> 1) + (GraphicsDevice.Viewport.Height >> 1));
mFadeEffect.SetEnginePosition(mBeamPositions[1]);
if (tempVec.Length() < 0.5)
{
Die();
}
}
#endregion
}
}