/// <summary> /// Updates the game each frame. /// </summary> /// <param name="time">Game time's data</param> public override void Update(GameTime time) { //If winning if (m_Victory) { //Waits 2 seconds m_VictoryWait += time.ElapsedGameTime.Milliseconds / 1000.0f; if (m_VictoryWait > 2.0f) { //Create parameter object[] Parameters = new object[4]; Parameters[1] = m_Timer.GetTime(); if (m_Player == Player.Klotski) { Parameters[0] = 0; } else { Parameters[0] = 1; } int Movement = 0; foreach (Ship ship in m_Ships) { Movement += ship.GetMoveNumber(); } Parameters[2] = Movement; Parameters[3] = 0; //If not player if (m_Player != Player.Klotski) { Parameters[3] = m_VisitedList.Count; } //Go to gameover state Global.StateManager.GoTo(StateID.GameOver, Parameters, true); } } //Otherwise, do the usual update else { //Updates GUI if not editor if (m_Player != Player.Storm) { int MoveNumber = 0; foreach (Ship ship in m_Ships) { MoveNumber += ship.GetMoveNumber(); } m_Counter.SetCounter(MoveNumber, m_VisitedList.Count); m_Timer.Increase(time.ElapsedGameTime); } else { m_Actor.SetLife(3); } //if player controlled); if (m_Player == Player.Klotski || m_Player == Player.Storm) { //Check actor collision); foreach (Ship ship in m_Ships) { if (ship.GetBoundingBox().Intersects(m_Actor.GetBoundingBox())) { m_Actor.OnCollision(ship); } } } else { //Check speed change if (InputManager.Keyboard.KeyPushed(Keys.Q)) { Ship.DecreaseSpeed(); } if (InputManager.Keyboard.KeyPushed(Keys.E)) { Ship.IncreaseSpeed(); } } //Updates based on the player switch (m_Player) { #region Player controlled case Player.Storm: case Player.Klotski: //Camera switching if (InputManager.Keyboard.KeyPushed(Keys.Tab)) { SwitchCamera(); } //Controlled character switching if (InputManager.Mouse.ButtonPushed(Mouse.MouseButtons.LeftButton)) { //If block is not moving and not in bird's view if (!m_ReadyToUpdate && m_ActiveCamera != m_BirdsView) { //If currently controlling a ship if (m_Controlled != m_Actor) { //Place actor on top of the ship m_Actor.SetPosition( (m_Controlled.GetBoundingBox().Max.X + m_Controlled.GetBoundingBox().Min.X) / 2.0f, m_Controlled.GetBoundingBox().Max.Y + 5.0f, (m_Controlled.GetBoundingBox().Max.Z + m_Controlled.GetBoundingBox().Min.Z) / 2.0f); //Return control to actor m_Actor.SetVisibility(true); m_Controlled = m_Actor; } else { //Get the ship below actor Ship Below = GetShipBelowActor(); //If a ship exist if (Below != null) { //Set as controlled m_Controlled = Below; //Turn off actor m_Actor.SetVisibility(false); } } } } break; #endregion #region AI controlled BFS case Player.BFS: //Create iterator if not exist if (m_IteratorStack.Count <= 0) { m_IteratorStack.Push((int)Direction.NegativeY); } //If if (m_Controlled == null || !((Ship)m_Controlled).IsMoving()) { //Get stack info int i = (m_IteratorStack.Peek() - (int)Direction.NegativeY) / 5; int j = m_IteratorStack.Peek() - (i * 5); m_IteratorStack.Pop(); //While there's no moving block and iterator hasn't finished while (m_Controlled == null && (i * 5) + j < (m_Ships.Count * 5) + (int)Direction.NegativeY) { while (m_Controlled == null && j <= (int)Direction.PositiveY) { //If the ship contains a movement if (m_Ships[i].GetBackDirection() != (Direction)j) { if (m_Ships[i].GetAvailableMovement().Contains((Direction)j)) { //Move and Set as active m_Controlled = m_Ships[i]; m_ShipStack.Push(m_Ships[i]); m_Ships[i].Move((Direction)j); m_Depth++; //Save stack j++; if (j > (int)Direction.PositiveY) { j = (int)Direction.NegativeY; i++; } m_IteratorStack.Push((i * 5) + j); } } //Next direction j++; } //Reset j j = (int)Direction.NegativeY; //Next i++; } //If has iterated through all if (m_Controlled == null && i >= m_Ships.Count) { //Increase max depth if at root if (m_Depth == 0) { m_MaxDepth++; } else { //Return via last ship m_Controlled = m_ShipStack.Pop(); ((Ship)m_Controlled).Return(); m_Depth--; } } } //If moving ship exist if (m_Controlled != null) { //Updates m_Controlled.Update(time); //If not moving if (!((Ship)m_Controlled).IsMoving()) { //If maximum depth if (m_Depth >= m_MaxDepth) { //Find current state in list bool Exist = false; GameData CurrentState = new GameData(); foreach (Ship ship in m_Ships) { CurrentState.AddShip(ship); } foreach (GameData state in m_VisitedList) { if (state.Equals(CurrentState)) { Exist = true; } } //If not exist if (!Exist) { m_VisitedList.Add(CurrentState); } ((Ship)m_Controlled).Return(); m_ShipStack.Pop(); m_Depth--; } else { //If returning, no longer returning, otherwise, add a stack if (((Ship)m_Controlled).Returning) { ((Ship)m_Controlled).Returning = false; } else { m_IteratorStack.Push((int)Direction.NegativeY); } //Find a new ship m_Controlled = null; } //Update board CreateBoard(); UpdateBoard(); } } break; #endregion #region AI controlled DFS case Player.DFS: //Create iterator if not exist if (m_IteratorStack.Count <= 0) { m_IteratorStack.Push((int)Direction.NegativeY); } if (m_Controlled == null || !((Ship)m_Controlled).IsMoving()) { //Get stack info int x = (m_IteratorStack.Peek() - (int)Direction.NegativeY) / 5; int y = m_IteratorStack.Peek() - (x * 5); m_IteratorStack.Pop(); //While there's no moving block and iterator hasn't finished while (m_Controlled == null && (x * 5) + y < (m_Ships.Count * 5) + (int)Direction.NegativeY) { while (m_Controlled == null && y <= (int)Direction.PositiveY) { //If the ship contains a movement if (m_Ships[x].GetBackDirection() != (Direction)y) { if (m_Ships[x].GetAvailableMovement().Contains((Direction)y)) { //Move and Set as active m_Controlled = m_Ships[x]; m_ShipStack.Push(m_Ships[x]); m_Ships[x].Move((Direction)y); Console.WriteLine(m_Ships[x].GetBackDirection()); //Save stack y++; if (y > (int)Direction.PositiveY) { y = (int)Direction.NegativeY; x++; } m_IteratorStack.Push((x * 5) + y); } } //Next direction y++; } //Reset y y = (int)Direction.NegativeY; //Next x++; } //If has iterated through all if (m_Controlled == null && x >= m_Ships.Count) { //Return via last ship m_Controlled = m_ShipStack.Pop(); ((Ship)m_Controlled).Return(); } } //If moving ship exist if (m_Controlled != null) { //Updates m_Controlled.Update(time); //If not moving if (!((Ship)m_Controlled).IsMoving()) { //Update board CreateBoard(); UpdateBoard(); //If returning, no longer returning, otherwise, add a stack if (((Ship)m_Controlled).Returning) { ((Ship)m_Controlled).Returning = false; //Find a new ship m_Controlled = null; } else { //Find current state in list bool Exist = false; GameData CurrentState = new GameData(); foreach (Ship ship in m_Ships) { CurrentState.AddShip(ship); } foreach (GameData state in m_VisitedList) { if (state.Equals(CurrentState)) { Exist = true; } } //If exist if (Exist) { ((Ship)m_Controlled).Return(); m_ShipStack.Pop(); } else { m_VisitedList.Add(CurrentState); m_IteratorStack.Push((int)Direction.NegativeY); //Find a new ship m_Controlled = null; } } } } break; #endregion } //Updating #region Entity updating //If camera is not bird view if (m_ActiveCamera != m_BirdsView && (m_Player == Player.Klotski || m_Player == Player.Storm)) { //Ensure controlled entity exist if (m_Controlled != null) { //Set active camera m_ActiveCamera = m_Controlled.GetCamera(); //Update controlled entity only m_Controlled.UpdateControl(time); m_Controlled.Update(time); } //Update life bar m_LifeBar.SetLife(m_Actor.GetLife()); m_LifeBar.Invalidate(); //If actor dies if (m_Actor.GetLife() <= 0) { //Create parameter object[] Parameters = new object[4]; Parameters[0] = -1; Parameters[1] = new TimeSpan(); Parameters[2] = 0; Parameters[3] = 0; //Go to gameover state Global.StateManager.GoTo(StateID.GameOver, Parameters, true); } } #endregion UpdateCamera(); #region Board updating //If currently controlling a ship if (m_Controlled is Ship) { //If moving, prepare for board update if ((m_Controlled as Ship).IsMoving()) { m_ReadyToUpdate = true; } else if (m_ReadyToUpdate) { //Update board CreateBoard(); UpdateBoard(); //No longer need to update board m_ReadyToUpdate = false; } } #endregion //if escape is pressed if (InputManager.Keyboard.KeyPushed(Keys.Escape)) { //Save actor's data if exist if (m_Actor != null) { m_Actor.SaveState(); } //Go to pause state object[] Parameters = new object[1]; Parameters[0] = false; if (m_Player == Player.Storm) { Parameters[0] = true; } Global.StateManager.GoTo(StateID.Pause, Parameters); } } }