/*
* MeteorWidgets.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.Content;
using Microsoft.Xna.Framework.Graphics;
using Random = Util.Random;
using Util;
namespace MaritimeDefender
{
///
/// A mock cockpit of the fighter in Meteor Madness. Used by the dot trial phase.
/// Also generates a HUD element for shields ("the pilot's HUD") which is tied to a component in the cockpit
///
public class Cockpit : Widget2D
{
#region Constants
// Constant for how far the HUD extends past the edge of the screen
private const float BUFFER_PERCENTAGE = .3f;
// Constant for the how much the pilot's hand moves percentage wise from original
// position to the button per second
private const float LEFT_HAND_SPEED = 1f;
// Constant for how long the flash for button 1 remains in seconds
private const float IDLE_FLASH_1_TIME = 3f;
// Constant for how long the flash for button 2 remains in seconds
private const float IDLE_FLASH_2_TIME = 4f;
// Constant for how long the flash for button 3 remains in seconds
private const float IDLE_FLASH_3_TIME = 5f;
// Constant for how far in either direction to allow the ship to roll
private const float MAX_ROLL_OFFSET = .2f;
// Constant for how long to keep turning
private const float TURN_TIME = .5f;
// Constant for the angular velocity during a turn
private const float TURN_SPEED = .03f;
// Constant for the angular velocity when a turn is completed, going towards a roll of 0
private const float RETURN_SPEED = .005f;
// Constant for the amount of time the ship indicates that it was hit in seconds
private const float HIT_TIME = 1f;
// Constant for how often the pilot will push a button when hit. (1f = 100%)
private const float BUTTON_PRESS_CHANCE = .4f;
// Constant for how long the pilot holds the button down for in seconds
private const float HOLD_BUTTON_TIME = .2f;
// Constant for the frequency of the shake speed (arbitray units).
private const float SHAKE_FREQUENCY = 50f;
// Constant for how far to shake the cockpit when it gets hit (in screen %)
private const float SHAKE_MAGNITUDE = 1f;
#endregion
#region Fields
//
private readonly MaritimeDefender mGame;
// Logger to use
private Logger mLogger;
// Nav stuff on the pilot's HUD
private WindshieldNavInfo mNavInfo;
// The main body of the ship and its console
private StaticSprite mBase;
// Sprite display for the ship image on the console display
private StaticSprite mShieldScreenShip;
// Sprite display for the ship's shield image on the console display
private StaticSprite mShieldScreenShield;
// Texture for the red illuminated buttons on the console display
private Texture2D mButtonsOn;
// Texture for button one of the yellow illuminated buttons
private Texture2D mFlash1On;
// Texture for button two of the yellow illuminated buttons
private Texture2D mFlash2On;
// Texture for button three of the yellow illuminated buttons
private Texture2D mFlash3On;
//
private Texture2D[] mProgressModule;
//
private Rectangle[] mProgressModuleLocs;
// The joystick with a hand attached to it
private Entity mJoystick;
// Offsets for the cockpit shake when it gets hit
private Vector2 mShake;
// The initial position of the joystick relative to the center of the screen, in screen pixels
private Vector2 mJoystickOrigOffset;
// The pilot's left hand
private Entity mLeftHand;
// Initial position
private Vector2 mLeftHandOrigOffset;
// The offset of the hand when it pushes the glowing button
private Vector2 mLeftHandButtonOffset;
//
private Vector2 mLeftHandCurrentOffset;
//
private Vector2 mShieldOrigOffset;
//
private Vector2[] mProgressModuleOrigOffset;
//
private float[] mProgressModuleOrigTheta;
//
private byte[] mProgressModuleOpacity;
// What rotation it would take to put the joystick straight down and then rotate it into place
private float mJoystickOrigTheta;
//
private float mLeftHandOrigTheta;
//
private float mLeftHandButtonTheta;
//
private float mLeftHandCurrentTheta;
//
private float mShieldOrigTheta;
// Roll of the entire ship (in radians)
private float mRoll;
//
private float mTurnLeftTimer;
//
private float mTurnRightTimer;
// Hold the left hand on the button for a brief time
private float mHoldButtonTimer;
// Inidicate that the ship is being hit if > 0
private float mHitTimer;
//
private float mIdleFlash1Timer;
//
private float mIdleFlash2Timer;
//
private float mIdleFlash3Timer;
// True when the pilot's hand is reaching towards the button
private bool mPushingButton;
// True when the pilot's hand is going back out of frame
private bool mPushedButton;
#endregion
#region Creation
///
/// Constructor
///
/// Reference to the current Maritime Defender game screen
public Cockpit(MaritimeDefender game, Logger logger)
{
mIdleFlash2Timer = 0f;
mGame = game;
mLogger = logger;
}
#endregion
#region Management
///
/// Loads in any necessary information for all content dependent objects
///
/// Reference to the current content manager for content loading
public void LoadContent(ContentManager Content)
{
int screenWidth = mGame.GraphicsDevice.Viewport.Width;
int screenHeight = mGame.GraphicsDevice.Viewport.Height;
Rectangle baseSize = new Rectangle(screenWidth >> 1, screenHeight >> 1, (int)(screenWidth * (1f + (BUFFER_PERCENTAGE * 2))), (int)(screenHeight * (1f + (BUFFER_PERCENTAGE * 2))));
mBase = new StaticSprite(baseSize, .90f, @"MiniGames\Cockpit");
mBase.LoadContent(Content);
mShieldOrigOffset = new Vector2(screenWidth * .28f, screenHeight * .42f);
mShieldOrigTheta = (float)Math.Atan(mShieldOrigOffset.X / mShieldOrigOffset.Y);
Texture2D shipTex = Content.Load(@"MiniGames\ShieldDisplayShip");
//Texture2D shieldTex = Content.Load(@"MiniGames\ShieldDisplayShield");
float displayWidth = screenWidth * .20f;
float displayHeight = shipTex.Height * displayWidth / shipTex.Width;
mShieldScreenShip = new StaticSprite(new Rectangle(0, 0, (int)displayWidth, (int)displayHeight), .69f, @"MiniGames\ShieldDisplayShip");
mShieldScreenShip.LoadContent(Content);
mShieldScreenShield = new StaticSprite(new Rectangle(0, 0, (int)displayWidth, (int)displayHeight), .70f, @"MiniGames\ShieldDisplayShield");
mShieldScreenShield.LoadContent(Content);
mJoystickOrigOffset = new Vector2(0, screenHeight * .62f);
mJoystickOrigTheta = (float)Math.Atan(mJoystickOrigOffset.X / mJoystickOrigOffset.Y);
Texture2D joystickTex = Content.Load(@"MiniGames\CockpitJoystick");
displayWidth = baseSize.Width * .4f;
displayHeight = joystickTex.Height * displayWidth / joystickTex.Width;
mJoystick = new Entity(@"MiniGames\CockpitJoystick", displayWidth, displayHeight);
mJoystick.LoadContent(Content);
mLeftHandOrigOffset = new Vector2(screenWidth * -.45f, screenHeight * 2f);
mLeftHandButtonOffset = new Vector2(screenWidth * -.38f, screenHeight * .87f);
mLeftHandOrigTheta = (float)Math.Atan(mLeftHandOrigOffset.X / mLeftHandOrigOffset.Y);
mLeftHandButtonTheta = (float)Math.Atan(mLeftHandButtonOffset.X / mLeftHandButtonOffset.Y);
mLeftHandCurrentOffset = mLeftHandOrigOffset;
Texture2D handTex = Content.Load(@"MiniGames\CockpitLeftHand");
displayWidth = baseSize.Width * .2f;
displayHeight = handTex.Height * displayWidth / handTex.Width;
mLeftHand = new Entity(@"MiniGames\CockpitLeftHand", displayWidth, displayHeight);
mLeftHand.LoadContent(Content);
mButtonsOn = Content.Load(@"Minigames\CockpitButtonsOn");
mFlash1On = Content.Load(@"Minigames\CockpitFlashBut1On");
mFlash2On = Content.Load(@"Minigames\CockpitFlashBut2On");
mFlash3On = Content.Load(@"Minigames\CockpitFlashBut3On");
mProgressModule = new Texture2D[2];
mProgressModule[0] = Content.Load(@"MiniGames\CockpitProgressModule");
mProgressModule[1] = Content.Load(@"MiniGames\CockpitProgressModule2");
mProgressModuleLocs = new Rectangle[10];
mProgressModuleOrigOffset = new Vector2[10];
mProgressModuleOrigTheta = new float[10];
mProgressModuleOpacity = new byte[10];
displayWidth = baseSize.Width * .019f;
displayHeight = mProgressModule[0].Height * displayWidth / mProgressModule[0].Width;
displayWidth += baseSize.Width * .007f; // Stretch them width-wise
float startX = screenWidth * -.184f;
float endX = screenWidth * .109f;
for (int i = 0; i < 10; i++)
{
mProgressModuleLocs[i] = new Rectangle(0, 0, (int)displayWidth, (int)displayHeight);
mProgressModuleOrigOffset[i] = new Vector2(endX * (i / 9f) + startX * ((9 - i) / 9f), screenHeight * .204f);
mProgressModuleOrigTheta[i] = (float)Math.Atan(mProgressModuleOrigOffset[i].X / mProgressModuleOrigOffset[i].Y);
}
mNavInfo = new WindshieldNavInfo(mGame);
mNavInfo.LoadContent(Content);
mNavInfo.Visible = false;
mGame.addWidget(mNavInfo);
}
#endregion
#region Update
///
/// Updates the state of the ship console
///
/// Time passed in game
public override void Update(GameTime gameTime)
{
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
int screenCenterX = mGame.GraphicsDevice.Viewport.Width >> 1;
int screenCenterY = mGame.GraphicsDevice.Viewport.Height >> 1;
if (mHitTimer > 0)
{
// Get shake offsets
mShake.X = SHAKE_MAGNITUDE * mGame.GraphicsDevice.Viewport.Width * (float)Math.Cos(mHitTimer * SHAKE_FREQUENCY) * .01f * mHitTimer / HIT_TIME;
mShake.Y = SHAKE_MAGNITUDE * mGame.GraphicsDevice.Viewport.Height * (float)Math.Sin(mHitTimer * SHAKE_FREQUENCY * .5f) * .01f * mHitTimer / HIT_TIME;
}
else
{
mShake = Vector2.Zero;
}
// Roll according to the current turning state
if (mTurnLeftTimer > 0 && mRoll > -MAX_ROLL_OFFSET)
mRoll -= TURN_SPEED;
if (mTurnRightTimer > 0 && mRoll < MAX_ROLL_OFFSET)
mRoll += TURN_SPEED;
if (mTurnLeftTimer < 0 && mTurnRightTimer < 0)
{
if (mRoll < -RETURN_SPEED)
mRoll += RETURN_SPEED;
else if (mRoll > RETURN_SPEED)
mRoll -= RETURN_SPEED;
else
mRoll = 0f;
}
// Shake the base
mBase.Location.X = screenCenterX + (int)mShake.X;
mBase.Location.Y = screenCenterY + (int)mShake.Y;
// Move the hands
mJoystick.X = screenCenterX + mShake.X + mJoystickOrigOffset.Length() * (float)Math.Sin(mJoystickOrigTheta - mRoll);
mJoystick.Y = screenCenterY + mShake.Y + mJoystickOrigOffset.Length() * (float)Math.Cos(mJoystickOrigTheta - mRoll);
mJoystick.Rotation = mRoll * 4 + (mShake.X * .005f);
if (mPushingButton)
{
Vector2 distanceToMove = mLeftHandButtonOffset - mLeftHandOrigOffset;
distanceToMove *= LEFT_HAND_SPEED * dt;
mLeftHandCurrentOffset += distanceToMove;
mLeftHandCurrentTheta = (float)Math.Atan(mLeftHandCurrentOffset.X / mLeftHandCurrentOffset.Y);
}
else if (mPushedButton && mHoldButtonTimer <= 0)
{
Vector2 distanceToMove = mLeftHandOrigOffset - mLeftHandButtonOffset;
distanceToMove *= LEFT_HAND_SPEED * dt;
mLeftHandCurrentOffset += distanceToMove;
mLeftHandCurrentTheta = (float)Math.Atan(mLeftHandCurrentOffset.X / mLeftHandCurrentOffset.Y);
}
if (mLeftHandCurrentOffset.Y < mLeftHandButtonOffset.Y)
{
mLeftHandCurrentOffset = mLeftHandButtonOffset;
mPushingButton = false;
mPushedButton = true;
mHoldButtonTimer = HOLD_BUTTON_TIME;
}
else if (mLeftHandCurrentOffset.Y >= mLeftHandOrigOffset.Y)
{
mLeftHandCurrentOffset = mLeftHandOrigOffset;
mPushedButton = false;
}
mLeftHand.X = screenCenterX + mShake.X * .5f + mLeftHandCurrentOffset.Length() * (float)Math.Sin(mLeftHandCurrentTheta - mRoll);
mLeftHand.Y = screenCenterY + mShake.Y * .5f + mLeftHandCurrentOffset.Length() * (float)Math.Cos(mLeftHandCurrentTheta - mRoll);
mLeftHand.Rotation = mRoll;
// Move the shield console
mShieldScreenShip.Location.X = (int)(screenCenterX + (int)mShake.X + mShieldOrigOffset.Length() * (float)Math.Sin(mShieldOrigTheta - mRoll));
mShieldScreenShip.Location.Y = (int)(screenCenterY + (int)mShake.Y + mShieldOrigOffset.Length() * (float)Math.Cos(mShieldOrigTheta - mRoll));
mShieldScreenShield.Location = mShieldScreenShip.Location;
// Update the shield progress bar
for (int i = 0; i < 10; i++)
{
if (mGame.EnergySaved > (i + 1) / 10f)
mProgressModuleOpacity[i] = 255;
else if (mGame.EnergySaved > i / 10f)
mProgressModuleOpacity[i] = (byte)(255 * 10 * (mGame.EnergySaved % .1f));
else
mProgressModuleOpacity[i] = 0;
mProgressModuleLocs[i].X = (int)(screenCenterX + (int)mShake.X + mProgressModuleOrigOffset[i].Length() * (float)Math.Sin(mProgressModuleOrigTheta[i] - mRoll));
mProgressModuleLocs[i].Y = (int)(screenCenterY + (int)mShake.Y + mProgressModuleOrigOffset[i].Length() * (float)Math.Cos(mProgressModuleOrigTheta[i] - mRoll));
}
// Recycle flashes (slightly randomized to prevent brain signal harmonics)
if (mIdleFlash1Timer < -IDLE_FLASH_1_TIME)
mIdleFlash1Timer += IDLE_FLASH_1_TIME * 2 - Random.NextFloat(IDLE_FLASH_1_TIME * .05f);
if (mIdleFlash2Timer < -IDLE_FLASH_2_TIME)
mIdleFlash2Timer += IDLE_FLASH_2_TIME * 2 - Random.NextFloat(IDLE_FLASH_2_TIME * .05f);
if (mIdleFlash3Timer < -IDLE_FLASH_3_TIME)
mIdleFlash3Timer += IDLE_FLASH_3_TIME * 2 - Random.NextFloat(IDLE_FLASH_3_TIME * .05f);
// Update timers
mTurnLeftTimer -= dt;
mTurnRightTimer -= dt;
mHitTimer -= dt;
mIdleFlash1Timer -= dt;
mIdleFlash2Timer -= dt;
mIdleFlash3Timer -= dt;
mHoldButtonTimer -= dt;
// Sync windshield HUD
//mShieldOverlay.Visible = Visible;
mNavInfo.Visible = Visible;
mNavInfo.Roll = mRoll;
mNavInfo.Shake = mShake;
base.Update(gameTime);
}
#endregion
#region Render
///
/// Draws each component of the space ship console
///
/// Reference to the current sprite batch for rendering sprites
public override void Draw(SpriteBatch spriteBatch)
{
// Draw the cockpit
spriteBatch.Draw(
mBase.Texture,
mBase.Location,
null,
Color.White,
mRoll,
new Vector2(mBase.Texture.Width >> 1, mBase.Texture.Height >> 1),
SpriteEffects.None,
mBase.ZDepth);
// Draw the components
spriteBatch.Draw(
mShieldScreenShield.Texture,
mShieldScreenShield.Location,
null,
new Color(
255,
(byte)(255 * Math.Min(1, mGame.EnergySaved)),
(byte)(255 * Math.Min(1, mGame.EnergySaved)),
(byte)(255 * .5f * Math.Min(1, mGame.EnergySaved))),
mRoll,
new Vector2(mShieldScreenShield.Texture.Width >> 1, mShieldScreenShield.Texture.Height >> 1),
SpriteEffects.None,
mShieldScreenShield.ZDepth);
spriteBatch.Draw(
mShieldScreenShip.Texture,
mShieldScreenShip.Location,
null,
new Color(255, 255, 255, (byte)(255.0 * .50)),
mRoll,
new Vector2(mShieldScreenShip.Texture.Width >> 1, mShieldScreenShip.Texture.Height >> 1),
SpriteEffects.None,
mShieldScreenShip.ZDepth);
for (int i = 0; i < 10; i++)
{
spriteBatch.Draw(
mProgressModule[i % 2],
mProgressModuleLocs[i],
null,
new Color(255, 255, 255, mProgressModuleOpacity[i]),
mRoll,
new Vector2((float)(mProgressModule[i % 2].Width >> 1), (float)(mProgressModule[i % 2].Height >> 1)),
SpriteEffects.None,
mBase.ZDepth - .01f * i);
}
if (mPushingButton)
{
spriteBatch.Draw(
mButtonsOn,
mBase.Location,
null,
Color.White,
mRoll,
new Vector2(mBase.Texture.Width >> 1, mBase.Texture.Height >> 1),
SpriteEffects.None,
mBase.ZDepth - .01f);
}
spriteBatch.Draw(
mFlash1On,
mBase.Location,
null,
new Color(255, 255, 255, (byte)MathHelper.Clamp(Math.Abs(255 * mIdleFlash1Timer / IDLE_FLASH_1_TIME), 0, 255)),
mRoll,
new Vector2(mFlash1On.Width >> 1, mFlash1On.Height >> 1),
SpriteEffects.None,
mBase.ZDepth - .02f);
spriteBatch.Draw(
mFlash2On,
mBase.Location,
null,
new Color(255, 255, 255, (byte)MathHelper.Clamp(Math.Abs(255 * mIdleFlash2Timer / IDLE_FLASH_2_TIME), 0, 255)),
mRoll,
new Vector2(mFlash2On.Width >> 1, mFlash2On.Height >> 1),
SpriteEffects.None,
mBase.ZDepth - .02f);
spriteBatch.Draw(
mFlash3On,
mBase.Location,
null,
new Color(255, 255, 255, (byte)MathHelper.Clamp(Math.Abs(255 * mIdleFlash3Timer / IDLE_FLASH_3_TIME), 0, 255)),
mRoll,
new Vector2(mFlash3On.Width >> 1, mFlash3On.Height >> 1),
SpriteEffects.None,
mBase.ZDepth - .02f);
// Draw the hands
mJoystick.Draw(spriteBatch);
mLeftHand.Draw(spriteBatch);
}
#endregion
#region Turn
///
/// Turns the entire ship to the left. Additionally moves the joystick.
///
public void TurnLeft()
{
mTurnLeftTimer = TURN_TIME;
}
///
/// Turns the entire ship to the right. Additionally moves the joystick.
///
public void TurnRight()
{
mTurnRightTimer = TURN_TIME;
}
#endregion
#region TakeDamage
///
/// Inform the user that ship is taking damage
///
public void TakeDamage()
{
mHitTimer = HIT_TIME;
if (Random.NextFloat() < BUTTON_PRESS_CHANCE)
mPushingButton = true;
// Issue code that negative feedback has been issued
mLogger.Write((int)EventCode.MD_CockpitDamageFeedback, EventCode.MD_CockpitDamageFeedback.ToString());
}
#endregion
#region IsStable
///
/// Returns whether or not the cockpit isn't doing anything that would distract the user and taint
/// the dot experiment.
///
/// True if the cockpit isn't doing anything that would distract the user and taint the dot
/// experiment. "Anything distracting" includes rotation, shaking, and some blinking
public bool IsStable()
{
return (mRoll == 0 && mShake == Vector2.Zero) && !mPushingButton && !mPushedButton;
}
#endregion
}
///
/// Displays a cross, circle, and other pilot-lookin stuff on the window of the cockpit
///
public class WindshieldNavInfo : Widget2D
{
public float Roll; // Set by the cockpit
public Vector2 Shake; // ''
protected StaticSprite mCircle; // A HUD element
protected StaticSprite mCross; // ''
//protected Entity mTicks; // ''
protected Vector2 mOrigCircleOffset; // Original position of this element
protected Vector2 mOrigCrossOffset; // ''
//protected Vector2 mOrigTickOffset; // ''
protected float mOrigCircleTheta; // Original angle between this the ray from the screen center to this element and a vertical ray
protected float mOrigCrossTheta; // ''
//protected Vector2 mOrigTickTheta; // ''
protected float mOveralOpacity = .8f; // Tone down the HUD element
protected float[] mLagRolls; // Use to make the cross + "down" line lag behind the cockpit roll
protected float mLagRoll; // Average of LagRolls
protected int mLagCount = 50; // Frames to average over for lag roll
protected int mLagIndex = 0; // Last lag roll record
protected bool mLagRollStable; // True if all entries in LagRoll are 0
MaritimeDefender mGame;
///
/// Create a new HUD Nav element
///
public WindshieldNavInfo(MaritimeDefender game)
{
mGame = game;
mHeightPercentage = .4f;
mCircle = new StaticSprite(Rectangle.Empty, 0f, @"MiniGames\NavCircle");
mCross = new StaticSprite(Rectangle.Empty, 0f, @"MiniGames\NavCross");
mLagRolls = new float[mLagCount];
}
public void LoadContent(ContentManager Content)
{
mCircle.LoadContent(Content);
mCross.LoadContent(Content);
ChangeResolution();
}
///
/// True if the widget is not moving
///
///
public bool IsStable()
{
return mLagRollStable;
}
///
/// Change dimensions
///
public override void ChangeResolution()
{
int screenWidth = mGame.GraphicsDevice.Viewport.Width;
int screenHeight = mGame.GraphicsDevice.Viewport.Height;
int screenCenterX = screenWidth >> 1;
int screenCenterY = screenHeight >> 1;
float heightCircle = screenHeight * mHeightPercentage;
float widthCircle = heightCircle * (mCircle.Texture.Width / (float)mCircle.Texture.Height);
float heightCross = heightCircle * .5f;
float widthCross = heightCross * (mCross.Texture.Width / (float)mCross.Texture.Height);
mCircle.Location.Width = (int)widthCircle;
mCircle.Location.Height = (int)heightCircle;
mCross.Location.Width = (int)widthCross;
mCross.Location.Height = (int)heightCross;
mOrigCircleOffset = new Vector2(screenWidth * .015f, -screenHeight * .18f);
mOrigCrossOffset = new Vector2(0, -screenHeight * .1f);
mOrigCircleTheta = (float)Math.Atan(mOrigCircleOffset.X / mOrigCircleOffset.Y);
mOrigCrossTheta = (float)Math.Atan(mOrigCrossOffset.X / mOrigCrossOffset.Y);
UpdatePositions();
base.ChangeResolution();
}
///
/// Updates the widget
///
public override void Update(GameTime gameTime)
{
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
mLagRolls[mLagIndex++] = Roll;
if (mLagIndex >= mLagCount)
mLagIndex = 0;
mLagRoll = 0;
for (int i = 0; i < mLagCount; i++)
mLagRoll += mLagRolls[i] * (1 + Shake.Length() * .25f);
mLagRoll /= mLagCount;
mLagRollStable = mLagRoll == 0;
UpdatePositions();
base.Update(gameTime);
}
///
/// Updates all items to their new position
///
public void UpdatePositions()
{
int screenCenterX = mGame.GraphicsDevice.Viewport.Width >> 1;
int screenCenterY = mGame.GraphicsDevice.Viewport.Height >> 1;
// Move with cockpit
mCircle.Location.X = (int)(screenCenterX + Shake.X + (mOrigCircleOffset.Y < 0 ? -1f : 1f) * mOrigCircleOffset.Length() * (float)Math.Sin(mOrigCircleTheta - Roll));
mCircle.Location.Y = (int)(screenCenterY + Shake.Y + (mOrigCircleOffset.Y < 0 ? -1f : 1f) * mOrigCircleOffset.Length() * (float)Math.Cos(mOrigCircleTheta - Roll));
mCross.Location.X = (int)(screenCenterX - mLagRoll * 200f + Shake.X + (mOrigCrossOffset.Y < 0 ? -1f : 1f) * mOrigCrossOffset.Length() * (float)Math.Sin(mOrigCrossTheta - Roll));
mCross.Location.Y = (int)(screenCenterY + Math.Abs(mLagRoll) * 100f + Shake.Y + (mOrigCrossOffset.Y < 0 ? -1f : 1f) * mOrigCrossOffset.Length() * (float)Math.Cos(mOrigCrossTheta - Roll));
}
///
/// Draws the component to the spritebatch
///
///
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(
mCircle.Texture,
mCircle.Location,
null,
new Color(255,255,255,(byte)(255 * mOveralOpacity * .3f)),
Roll,
new Vector2(mCircle.Texture.Width >> 1, mCircle.Texture.Height >> 1),
SpriteEffects.None,
0f);
spriteBatch.Draw(
mCross.Texture,
mCross.Location,
null,
new Color(255,255,255,(byte)(255 * mOveralOpacity)),
mLagRoll,
new Vector2(mCross.Texture.Width >> 1, mCross.Texture.Height >> 1),
SpriteEffects.None,
0f);
}
}
}