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