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