/* * HackingPhaseScreen.cs * Authors: Karl Orosz, Brian Chesbrough * 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 Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Random = Util.Random; using Util; namespace StarJack { /// /// This will display the hacking phase /// /// public class HackingPhaseScreen:GameScreen { //Time in MS private float WAIT_TIME = 3000.0f; private float RESULT_TIME = 2000.0f; private List mDialogList; //The List of the different modes of the test. public enum Difficulty { Tutorial, Easy, Medium, Hard, VeryHard } public int TRANS_SPEED = 1000; //Difficulty mDifficulty; //Paused bool mPause = false; //The screens Input handler InputHandler mInputHandler; //the logger! Logger mLogger; //The Sprite batch SpriteBatch mSpriteBatch; //Menu Font SpriteFont mSpriteFont; int spinTime=0; Viewport figure; Viewport key; Viewport result; public enum State { Starting, Paused, FigureTest, Waiting, NextDelay, TransitionOn, TransitionOff, Choosing, Result, Finish, Closing } private State mState; //Screen Entities Entity mHackBack; Entity mHackScreenTop; Entity mHackScreenBottom; TextEntity mStartingText; //Stores the current key-figure pair; KeyValuePair mPair; Vector2 mKeyCenter = new Vector2(0,0); Vector2 mFigCenter = new Vector2(0, 0); //Hacking phase Entities //Left and right arrows for the hacking screen. Button mRight; Button mLeft; bool mMatchChoice = false; bool correct = false; int mSuccess = 0; int mFail = 0; HackableObject mHacking; int mAttempts; int mMaxFails; SpriteBlendMode mBelnd = SpriteBlendMode.Additive; bool mWin = false; public bool Win { get { return mWin; } } private MatrixTextEffect mMatrix; private MatrixTextEffect mMatrix2; public HackingPhaseScreen(HackableObject hacked) :base() { mHacking = hacked; mAttempts = mHacking.Attempts; } public HackingPhaseScreen(int attempts) : base() { mAttempts = attempts; } private FigureManager mFigures; /// /// Initializes the screen /// public override void Initialize() { mLogger = GetLogger(); mLogger.Initialize(); mLogger.Write((int)HackingPhaseEvent.Start, "SJ_EFT_START"); mDialogList = new List(); mFigures = new FigureManager(); mInputHandler = GetInputHandler(); mInputHandler.Initialize(); mInputHandler.ReportAllEvents = true; mInputHandler.WriteToParallel = Settings.ParallelPortEnabled; mInputHandler.BindButton(Keys.Space, Trigger.Activated, (int)HackingPhaseEvent.Proceed); mInputHandler.BindButton(Keys.Left, Trigger.Activated, (int)HackingPhaseEvent.MatchChoice); mInputHandler.BindButton(Keys.Right, Trigger.Activated, (int)HackingPhaseEvent.NoMatchChoice); mInputHandler.BindButton(Keys.Escape, Trigger.Activated, (int)HackingPhaseEvent.End); if (mAttempts > 0) mState = State.Starting; else mState = State.Finish; mHackScreenBottom = new Entity(); mHackScreenBottom.TextureName = "HackScreenBottom"; mHackScreenBottom.Depth = Depth.Screen; mHackScreenTop = new Entity(); mHackScreenTop.TextureName = "HackScreenTop"; mHackScreenTop.Depth = Depth.Screen; mHackBack = new Entity(); mHackBack.TextureName = "HackScreenBack"; mHackBack.Depth = Depth.BackGroundCover; figure = new Viewport(); figure.X = 275; figure.Y = 130; figure.Width = 250; figure.Height = 200; mFigCenter.X = 400; mFigCenter.Y = 200; ; key = new Viewport(); key.X = 275; key.Y = 350; key.Width = 200; key.Height = 150; mKeyCenter.X = 400; mKeyCenter.Y = 425; mPair = new KeyValuePair(new Entity(), new Entity()); mPair.Key.Width = key.Width; mPair.Key.Height = key.Height; mPair.Key.Depth = Depth.Figure; mPair.Value.Width = figure.Width; mPair.Value.Height = figure.Height; mPair.Value.Depth = Depth.Figure; SetNextPair(); result = new Viewport(); result.X = 250; result.Y = 500; result.Width = 350; result.Height = 50; mStartingText = new TextEntity("Crack " + mAttempts + " codes to hack in!\nPress Space to Start"); mStartingText.Width = 600; mStartingText.Height = 300; mStartingText.Color = Color.Black; mStartingText.Depth = Depth.Text; // mStartingText.Height = (int)(mSpriteFont.MeasureString(mStartingText.Text).Y); // mStartingText.Width = (int)(mSpriteFont.MeasureString(mStartingText.Text).X); //TO DO: set max # of fails based off the user difficulty //currently just a hack mMaxFails = 3; //mRight = new Entity("Right", "Right"); base.Initialize(); mSpriteBatch = new SpriteBatch(GraphicsDevice); Viewport mView = GraphicsDevice.Viewport; mMatrix = new MatrixTextEffect(mView, 20, 10, 300.0f, 400.0f); mMatrix2 = new MatrixTextEffect(mView, 10, 10, 100.0f, 200.0f); mHackScreenTop.X = mView.X; mHackScreenTop.Y = mView.Y; mHackScreenTop.Width = mView.Width; mHackScreenTop.Height = mView.Height/5; mHackScreenBottom.Y = mView.Height / 5 * 4; mHackScreenBottom.X = mView.X; mHackScreenBottom.Width = mView.Width; mHackScreenBottom.Height = mView.Height / 5; mLeft = new Button("Left"); mLeft.Width = 100; mLeft.Height = 75; mLeft.Depth = HackingPhaseScreen.Depth.Figure; mLeft.X = (int)(mView.Width * 0.10f); mLeft.Y = (int)(mView.Height * 0.85f); mLeft.AddIcon("Left", "Arrow", "Left", Button.Orientation.Center, 1.0f); mLeft.AddText("Match", "dialogfont", Color.Black, Color.Black, Button.Orientation.ToTheRight, 1.0f); mRight = new Button("Right"); mRight.Width = 100; mRight.Height = 75; mRight.Depth = HackingPhaseScreen.Depth.Figure; mRight.X = (int)(mView.Width * 0.80f); mRight.Y = (int)(mView.Height * 0.85f); mRight.AddIcon("Right", "Arrow", "Right", Button.Orientation.Center, 1.0f); mRight.AddText("No Match", "dialogfont", Color.Black, Color.Black, Button.Orientation.ToTheLeft, 1.0f); LoadContent(); } public override void Reinitialize() { mInputHandler.Enable(); this.Enabled = true; this.Visible = true; } protected override void Dispose(bool disposing) { mSpriteBatch.Dispose(); mInputHandler.Dispose(); base.Dispose(disposing); } protected override void LoadContent() { mStartingText.LoadContent(Content); mHackScreenTop.LoadContent(Content); mHackScreenBottom.LoadContent(Content); if (mMatrix != null) { mMatrix.LoadCOntent(Content); } if (mMatrix2 != null) { mMatrix2.LoadCOntent(Content); } mSpriteFont = Content.Load(@"Fonts\menufont"); mFigures.LoadContent(Content); mHackBack.LoadContent(Content); if (mLeft != null) { mLeft.LoadContent(Content); } if (mRight != null) { mRight.LoadContent(Content); } base.LoadContent(); } protected override void UnloadContent() { base.UnloadContent(); } public void SetNextPair() { KeyValuePair tNext = mFigures.GetNextPair(); mPair.Key.Texture = tNext.Key; mPair.Key.Name = tNext.Key.Name; mPair.Key.Width = tNext.Key.Source.Width; mPair.Key.Height = tNext.Key.Source.Height; mPair.Key.Depth = Depth.Figure; mPair.Key.X =(int)( mKeyCenter.X - mPair.Key.Width / 2.0f); mPair.Key.Y = (int)(mKeyCenter.Y - mPair.Key.Height / 2.0f); mPair.Value.Texture = tNext.Value; mPair.Value.Name = tNext.Value.Name; mPair.Value.Width = tNext.Value.Source.Width; mPair.Value.Height = tNext.Value.Source.Height; mPair.Value.X =(int)( mFigCenter.X - mPair.Value.Width / 2.0f); mPair.Value.Y = (int)(mFigCenter.Y - mPair.Value.Height / 2.0f); } public override void Update(Microsoft.Xna.Framework.GameTime gameTime) { while (mInputHandler.HasEvent()) { InputEvent e = mInputHandler.GetNextEvent(); if (!mPause) { switch ((HackingPhaseEvent)e.EventCode) { case HackingPhaseEvent.Proceed: if (mState == State.Waiting) { mState = State.TransitionOff; e.WriteToLog(mLogger, "SJ_EFT_INPUT_Proceed"); } else { e.WriteToLog(mLogger, "IGNORE"); } break; case HackingPhaseEvent.NoMatchChoice: if (mState == State.FigureTest) { mMatchChoice = false; e.WriteToLog(mLogger, "SJ_EFT_INPUT_NoMatch"); mState = State.Choosing; } else { e.WriteToLog(mLogger, "IGNORE"); } break; case HackingPhaseEvent.MatchChoice: if (mState == State.FigureTest) { mMatchChoice = true; e.WriteToLog(mLogger, "SJ_EFT_INPUT_Match"); mState = State.Choosing; } else { e.WriteToLog(mLogger, "IGNORE"); } break; case HackingPhaseEvent.End: e.WriteToLog(mLogger, "SJ_EFT_END_FAIL"); Done(); break; } } else { e.WriteToLog(mLogger, "IGNORE"); } } if (!mPause) { //Calculate figure stuff switch (mState) { case State.Starting: mStartingText.X = GraphicsDevice.Viewport.Width / 2 - mStartingText.Width / 2; mStartingText.Y = GraphicsDevice.Viewport.Height / 2 - mStartingText.Height / 2; mHackBack.X = GraphicsDevice.Viewport.X; mHackBack.Y = GraphicsDevice.Viewport.Y; mHackBack.Width = GraphicsDevice.Viewport.Width; mHackBack.Height = GraphicsDevice.Viewport.Height; mState = State.Waiting; break; case State.NextDelay: mMatrix.Update(gameTime); mMatrix2.Update(gameTime); spinTime += gameTime.ElapsedGameTime.Milliseconds; if (spinTime > WAIT_TIME) { mState = State.TransitionOn; mHackBack.X = GraphicsDevice.Viewport.Width / 2; mHackBack.Y = GraphicsDevice.Viewport.Height / 2; mHackBack.Width = 0; mHackBack.Height = 0; } break; case State.TransitionOn: mMatrix.Update(gameTime); mMatrix2.Update(gameTime); if (mHackBack.X > 0) { mHackBack.X -= 2*(int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds/1000.0f)) ; mHackBack.Width += 4* (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); } if (mHackBack.Y > 0) { mHackBack.Y -= (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); mHackBack.Height += 2* (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); } if(mHackBack.X <=0 && mHackBack.Y <= 0){ mHackBack.X = 0; mHackBack.Y = 0; mHackBack.Width = GraphicsDevice.Viewport.Width; mHackBack.Height = GraphicsDevice.Viewport.Height; mState = State.FigureTest; SetNextPair(); mLogger.Write((int)HackingPhaseEvent.DisplayPair, "SJ_EFT_Stimulus_Presented Key=" + mPair.Key.Name + " Figure=" + mPair.Value.Name); spinTime = 0; } break; case State.TransitionOff: mMatrix.Update(gameTime); mMatrix2.Update(gameTime); if (mHackBack.X >= 0) { mHackBack.X += (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); mHackBack.Width -= 2 * (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); } if (mHackBack.Y >= 0) { mHackBack.Y += (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); mHackBack.Height -= 2 * (int)(TRANS_SPEED * (gameTime.ElapsedGameTime.Milliseconds / 1000.0f)); } if (mHackBack.X >= GraphicsDevice.Viewport.Width / 2 && mHackBack.Y >= GraphicsDevice.Viewport.Height / 2) { mHackBack.X = 0; mHackBack.Y = 0; mHackBack.Width = 0; mHackBack.Height = 0; mState = State.NextDelay; spinTime = 0; } break; case State.FigureTest: break; case State.Choosing: spinTime += gameTime.ElapsedGameTime.Milliseconds; if (mFigures.IsPair(mPair.Key.Name, mPair.Value.Name) == mMatchChoice) { mSuccess += 1; correct = true; if (mMatchChoice)//correct match { mLogger.Write((int)HackingPhaseEvent.CorrectHit, "SJ_EFT_HIT"); } else//correct nomatch { mLogger.Write((int)HackingPhaseEvent.CorrectReject, "SJ_EFT_REJECT"); } } else { mFail += 1; correct = false; if (mMatchChoice) { mLogger.Write((int)HackingPhaseEvent.IncorrectFalseAlarm, "SJ_EFT_FALSE_ALARM"); } else { mLogger.Write((int)HackingPhaseEvent.IncorrectMiss, "SJ_EFT_MISS"); } } if (mSuccess >= mAttempts||mFail >= mMaxFails) { mState = State.Finish; spinTime = 0; } else { spinTime = 0; mState = State.Result; } break; case State.Result: if(spinTime == 0){ if (correct) { mStartingText.Text = "Code cracked! \n " + (mAttempts - mSuccess) + " codes left."; } else { mStartingText.Text = "Hack attempt detected! \n " + (mMaxFails - mFail) + " misses left."; } // mLogger.Write((int)HackingPhaseEvent.Info, "SJ_EFT_INFO TRIALS_LEFT=" + (mAttempts - mSuccess - mFail) + " SUCCESSES=" + mSuccess + " FAILURES=" + mFail); } spinTime += gameTime.ElapsedGameTime.Milliseconds; if (spinTime >= RESULT_TIME) { mState = State.TransitionOff; } break; case State.Finish: if (mSuccess == mAttempts) { mStartingText.Text = "Success!!"; mWin = true; mLogger.Write((int)HackingPhaseEvent.End, "SJ_EFT_END_SUCCESS"); } else if (mFail == mMaxFails) { mStartingText.Text = "You didn't crack the code!!"; mWin = false; mLogger.Write((int)HackingPhaseEvent.Fail, "SJ_EFT_END_FAIL"); } mState = State.Closing; break; case State.Closing: spinTime += gameTime.ElapsedGameTime.Milliseconds; if (spinTime >= RESULT_TIME) { Done(); } break; } //Shows any dialog stuff!! if (mDialogList.Count > 0) { Raise(new DialogScreen(mDialogList)); mInputHandler.Disable(); mDialogList.Clear(); } } } public override void Draw(Microsoft.Xna.Framework.GameTime gameTime) { mSpriteBatch.GraphicsDevice.Clear(Color.Black); //Text //base.Draw(gameTime); if (mState == State.NextDelay || mState == State.TransitionOff || mState == State.TransitionOn) { mSpriteBatch.Begin(mBelnd, SpriteSortMode.FrontToBack, SaveStateMode.None); mMatrix.Draw(mSpriteBatch); mMatrix2.Draw(mSpriteBatch); mSpriteBatch.End(); } mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.FrontToBack, SaveStateMode.None); if (mState == State.TransitionOff || mState == State.TransitionOn || mState == State.FigureTest ||mState == State.Waiting ||mState == State.Result ||mState == State.Finish ||mState == State.Closing) { mHackBack.Draw(mSpriteBatch); } if (mState == State.FigureTest) { mLeft.Draw(mSpriteBatch); mRight.Draw(mSpriteBatch); } if (mState == State.Waiting || mState == State.Result || mState == State.Finish || mState == State.Closing) { mStartingText.Draw(mSpriteBatch); } mHackScreenTop.Draw(mSpriteBatch); mHackScreenBottom.Draw(mSpriteBatch); mSpriteBatch.End(); if (mState == State.FigureTest) { // Viewport old = GraphicsDevice.Viewport; // GraphicsDevice.Viewport = figure; //Figure mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.FrontToBack, SaveStateMode.None); mPair.Value.Draw(mSpriteBatch); mSpriteBatch.End(); //GraphicsDevice.Viewport = key; mSpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.FrontToBack, SaveStateMode.None); mPair.Key.Draw(mSpriteBatch); mSpriteBatch.End(); // GraphicsDevice.Viewport = old; } //Draw Lines# } public struct Depth { public static float MatrixText = 0.1f; public static float BackGroundCover = 0.4f; public static float Figure = 0.7f; public static float Text = 0.8f; public static float Screen = 0.5f; } } }