예제 #1
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            //if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            //	Exit();

            // TODO: Add your update logic here

            kbState = Keyboard.GetState();

            mState = Mouse.GetState();

            #region Game States FSM - Update() portion
            switch (gameState)
            {
            case (GameStates.StartScreen):
            {
                // "Deactivate" the player.
                playerState = PlayerStates.Idle;

                // Use idle scrolling.
                scrollingState = ScrollingStates.IdleScrolling;

                startScreen.StartButton.Update(mState, prevMState);
                startScreen.LeaderboardButton.Update(mState, prevMState);
                startScreen.QuitButton.Update(mState, prevMState);

                // Giving the buttons on the start screen their functionality
                if (startScreen.StartButton.IsClicked)
                {
                    // Perform necessary data resets here, instead of on the
                    //		pregame screen itself so the code only runs once.
                    if (ResetAction != null)
                    {
                        ResetAction();
                    }

                    // Initialise the map for the current run.
                    // This Reset() method's signature does not match that
                    //		of the event handler's
                    wallManager.ResetGame(wall);

                    gameState = GameStates.Pregame;
                }

                if (startScreen.LeaderboardButton.IsClicked)
                {
                    gameState = GameStates.Leaderboard;
                }

                if (startScreen.QuitButton.IsClicked)
                {
                    Exit();
                }

                break;
            }

            case (GameStates.Leaderboard):
            {
                // Should not need to do anything other than check for
                //		button press, since the start screen must be
                //		accessed prior to the leaderboard.
                leaderboardScreen.BackButton.Update(mState, prevMState);

                // Giving the back button its functionality
                if (leaderboardScreen.BackButton.IsClicked)
                {
                    gameState = GameStates.StartScreen;
                }

                break;
            }

            case (GameStates.Pregame):
            {
                // Do not scroll.
                scrollingState = ScrollingStates.NotScrolling;

                // Pressing any key starts the game.
                // GetPressedKeys() returns an array of all keys that
                //		are currently being pressed. By checking the
                //		array's length, we can effectively see if any
                //		key was pressed at all in the previous frame.
                if (kbState.GetPressedKeys().Length > 0)
                {
                    gameState = GameStates.Playing;
                }

                break;
            }

            case (GameStates.Playing):
            {
                // "Activate" the player.
                playerState = PlayerStates.Active;

                // Scroll normally.
                scrollingState = ScrollingStates.Scrolling;

                break;
            }

            case (GameStates.HiScore):
            {
                // "Deactivate" the player.
                playerState = PlayerStates.Idle;

                // Do not scroll.
                scrollingState = ScrollingStates.NotScrolling;

                hiScoreNameEntryScreen.Submit.Update(mState, prevMState);
                hiScoreNameEntryScreen.Update(kbState, prevKBState);

                // Either clicking the Submit button or hitting enter saves scores
                //		and changes the game's state.
                if (hiScoreNameEntryScreen.Submit.IsClicked ||
                    kbState.IsKeyDown(Keys.Enter))
                {
                    // Update and save leaderboard data.
                    leaderboard.UpdateScores(
                        leaderboardPosition,
                        hiScoreNameEntryScreen.LiveString,
                        scoreCounter.Value);
                    leaderboard.SaveScores();
                    gameState = GameStates.GameOver;
                }

                break;
            }

            case (GameStates.GameOver):
            {
                // Explicitly deactivate the player and stop scrolling here too, in
                //		case no new high score was set.
                playerState    = PlayerStates.Idle;
                scrollingState = ScrollingStates.NotScrolling;

                gameOverScreen.ReturnToStartScreen.Update(mState, prevMState);

                // Pressing Enter restarts the game.
                // Check for single key press so Enter input from high score screen
                //		does not interfere with current.
                if (kbState.IsKeyDown(Keys.Enter) &&
                    prevKBState.IsKeyUp(Keys.Enter))
                {
                    // Perform necessary data resets.
                    if (ResetAction != null)
                    {
                        ResetAction();
                    }

                    // This Reset() method's signature does not match that
                    //		of the event handler's.
                    wallManager.ResetGame(wall);

                    gameState = GameStates.Playing;
                }

                // Giving the button on the game over screen its
                //		functionality
                if (gameOverScreen.ReturnToStartScreen.IsClicked)
                {
                    // Reset and initialise the map to prepare for idle
                    //		scrolling on the start screen.
                    wallManager.ResetMenu(wall);

                    gameState = GameStates.StartScreen;
                }

                break;
            }
            }
            #endregion

            #region Player States FSM
            // This FSM tracks all player-related functions: movement and
            //		collision detection.
            switch (playerState)
            {
            case (PlayerStates.Idle):
            {
                // Do nothing - player character is idle.
                break;
            }

            case (PlayerStates.Active):
            {
                // Player is now active and has access to movement.
                if (kbState.IsKeyDown(Keys.Left))
                {
                    player.Position -= player.StrafeVelocity;
                    player.UpdateTracker();
                }

                if (kbState.IsKeyDown(Keys.Right))
                {
                    player.Position += player.StrafeVelocity;
                    player.UpdateTracker();
                }

                // Touching a wall results in a game over.
                foreach (Wall wall in wallManager.LeftWalls)
                {
                    if (player.Collided(wall))
                    {
                        // Generate a leaderboard position, if applicable.
                        leaderboardPosition = leaderboard.IsHighScore(scoreCounter.Value);

                        // Check whether the score earned this run is a high score.
                        // If it is not, proceed directly to the game over screen.
                        if (leaderboardPosition == -1)
                        {
                            gameState = GameStates.GameOver;
                        }
                        // Display the high score screen if the player earns a
                        //		score that alters the leaderboard.
                        else
                        {
                            gameState = GameStates.HiScore;
                        }
                    }
                }

                foreach (Wall wall in wallManager.RightWalls)
                {
                    if (player.Collided(wall))
                    {
                        // Generate a leaderboard position, if applicable.
                        leaderboardPosition = leaderboard.IsHighScore(scoreCounter.Value);

                        // Check whether the score earned this run is a high score.
                        // If it is not, proceed directly to the game over screen.
                        if (leaderboardPosition == -1)
                        {
                            gameState = GameStates.GameOver;
                        }
                        // Display the high score screen if the player earns a
                        //		score that alters the leaderboard.
                        else
                        {
                            gameState = GameStates.HiScore;
                        }
                    }
                }

                break;
            }
            }
            #endregion

            #region Scrolling States FSM
            // This FSM tracks and controls all scrolling possibilities for
            //		the map.
            switch (scrollingState)
            {
            // Idle scrolling is used on the start and leaderboard screens.
            case (ScrollingStates.IdleScrolling):
            {
                // Continuous scrolling
                wallManager.Scroll();

                // Why is Update() called before SpawnWallPair() and
                //		DespawnWallPair(), and not after?
                // HINT: Variables initialised to 0 before Update()
                wallManager.UpdateMenu(gameTime);

                // Manage memory by spawning and despawning walls as necessary.
                wallManager.SpawnWallPair(wall);
                wallManager.DespawnWallPair();

                break;
            }

            // The game does not scroll during the pregame, high score entry, and game over screens.
            case (ScrollingStates.NotScrolling):
            {
                // Do nothing - no scrolling takes place.

                break;
            }

            // Regular scrolling is used during actual gameplay.
            case (ScrollingStates.Scrolling):
            {
                // Continuous scrolling
                wallManager.Scroll();

                //// Controlled scrolling
                //if (kbState.IsKeyDown(Keys.Up))
                //{
                //	wallManager.Scroll();
                //}

                // Why is Update() called before SpawnWallPair() and
                //		DespawnWallPair(), and not after?
                // HINT: Variables initialised to 0 before Update()
                wallManager.UpdateGame(gameTime);

                // Manage memory by spawning and despawning walls as necessary.
                wallManager.SpawnWallPair(wall);
                wallManager.DespawnWallPair();

                // Update the player's score, level, and strafe speed.
                scoreCounter.Update(gameTime, levelCounter.Value);

                // This method invokes the event, calling all the other
                //		level up methods along with it.
                if (levelCounter.LevelUp(gameTime))
                {
                    // When the above method is executed, alter the bool flag.
                    levelUpAnimation.HasLeveledUp = true;

                    currentColour = bgColourArray[generator.Next(bgColourArray.Length)];
                }

                // The bool flag is used here to scroll the text.
                // levelUpAnimation.LevelUp() cannot be grouped together with
                //		levelUpAction because the code only runs once per level
                //		up. Text scrolling needs to be performed each frame
                //		after a level up, as long as the text has not cleared
                //		the screen. Hence, this if statement is necessary.
                if (levelUpAnimation.HasLeveledUp)
                {
                    levelUpAnimation.LevelUp();
                }

                break;
            }
            }
            #endregion

            #region Movement debugging code
            //if (kbState.IsKeyDown(Keys.Left))
            //{
            //	player.Position -= player.StrafeVelocity;
            //	player.UpdateTracker();
            //}
            //if (kbState.IsKeyDown(Keys.Right))
            //{
            //	player.Position += player.StrafeVelocity;
            //	player.UpdateTracker();
            //}

            //foreach (Wall wall in wallManager.LeftWalls)
            //{
            //	if (player.Collided(wall))
            //	{
            //		System.Console.WriteLine("LEFT WALL COLLISION");
            //	}
            //}

            //foreach (Wall wall in wallManager.RightWalls)
            //{
            //	if (player.Collided(wall))
            //	{
            //		System.Console.WriteLine("RIGHT WALL COLLISION");
            //	}
            //}

            //// Controlled scrolling
            //if (kbState.IsKeyDown(Keys.Up))
            //{
            //	wallManager.Scroll();
            //}
            ////wallManager.Scroll();

            //// Manage memory by spawning and despawning walls as necessary.
            //wallManager.SpawnWallPair(wall);
            //wallManager.DespawnWallPair();
            #endregion

            prevKBState = kbState;
            prevMState  = mState;

            base.Update(gameTime);
        }