forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			406 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
namespace Oculus.Platform.Samples.VrBoardGame
 | 
						|
{
 | 
						|
	using UnityEngine;
 | 
						|
	using UnityEngine.UI;
 | 
						|
 | 
						|
	// This is the primary class that implements the game logic.
 | 
						|
	public class GameController : MonoBehaviour
 | 
						|
	{
 | 
						|
		// instance of the object interfacing with the matchmaking service
 | 
						|
		[SerializeField] private MatchmakingManager m_matchmaking = null;
 | 
						|
 | 
						|
		[SerializeField] private GameBoard m_board = null;
 | 
						|
		[SerializeField] private GamePiece m_pieceA = null;
 | 
						|
		[SerializeField] private GamePiece m_pieceB = null;
 | 
						|
		[SerializeField] private GamePiece m_powerPiece = null;
 | 
						|
 | 
						|
		// colors for the various states of the selectable games pieces
 | 
						|
		[SerializeField] private Color m_unusableColor = Color.white;
 | 
						|
		[SerializeField] private Color m_unselectedColor = Color.white;
 | 
						|
		[SerializeField] private Color m_selectedColor = Color.white;
 | 
						|
		[SerializeField] private Color m_highlightedColor = Color.white;
 | 
						|
 | 
						|
		[SerializeField] private Text m_ballCountText = null;
 | 
						|
		[SerializeField] private Text m_player0Text = null;
 | 
						|
		[SerializeField] private Text m_player1Text = null;
 | 
						|
 | 
						|
		private enum GameState {
 | 
						|
			None,
 | 
						|
			PracticingMyTurn, PracticingAiTurn,
 | 
						|
			OnlineMatchMyTurn, OnlineMatchRemoteTurn
 | 
						|
		}
 | 
						|
 | 
						|
		private GameState m_state;
 | 
						|
 | 
						|
		// the game piece the player is currently looking at
 | 
						|
		private GamePiece m_interestedPiece;
 | 
						|
 | 
						|
		// the piece the player selected with the Fire button
 | 
						|
		private GamePiece m_selectedPiece;
 | 
						|
 | 
						|
		// the piece that would be placed if the player pressed the Fire button
 | 
						|
		private GamePiece m_proposedPiece;
 | 
						|
 | 
						|
		// how many IAP power-balls the user has
 | 
						|
		private uint m_powerBallcount;
 | 
						|
 | 
						|
		// the name of the current opponent
 | 
						|
		private string m_opponentName;
 | 
						|
 | 
						|
		void Start()
 | 
						|
		{
 | 
						|
			TransitionToState(GameState.None);
 | 
						|
			UpdateScores();
 | 
						|
		}
 | 
						|
 | 
						|
		void Update()
 | 
						|
		{
 | 
						|
			PerFrameStateUpdate();
 | 
						|
		}
 | 
						|
 | 
						|
		#region Game State
 | 
						|
 | 
						|
		private void TransitionToState(GameState state)
 | 
						|
		{
 | 
						|
			m_state = state;
 | 
						|
 | 
						|
			UpdateGamePieceColors();
 | 
						|
		}
 | 
						|
 | 
						|
		private void TransitionToNextState()
 | 
						|
		{
 | 
						|
			if (!m_board.IsFull())
 | 
						|
			{
 | 
						|
				switch (m_state)
 | 
						|
				{
 | 
						|
					case GameState.PracticingAiTurn:
 | 
						|
						TransitionToState(GameState.PracticingMyTurn);
 | 
						|
						break;
 | 
						|
					case GameState.PracticingMyTurn:
 | 
						|
						TransitionToState(GameState.PracticingAiTurn);
 | 
						|
						break;
 | 
						|
					case GameState.OnlineMatchRemoteTurn:
 | 
						|
						TransitionToState(GameState.OnlineMatchMyTurn);
 | 
						|
						break;
 | 
						|
					case GameState.OnlineMatchMyTurn:
 | 
						|
						TransitionToState(GameState.OnlineMatchRemoteTurn);
 | 
						|
						break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				switch (m_state)
 | 
						|
				{
 | 
						|
					case GameState.OnlineMatchRemoteTurn:
 | 
						|
					case GameState.OnlineMatchMyTurn:
 | 
						|
						m_matchmaking.EndMatch(m_board.GetPlayerScore(0), m_board.GetPlayerScore(1));
 | 
						|
						break;
 | 
						|
				}
 | 
						|
				TransitionToState(GameState.None);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		private void PerFrameStateUpdate()
 | 
						|
		{
 | 
						|
			switch (m_state)
 | 
						|
			{
 | 
						|
				case GameState.PracticingAiTurn:
 | 
						|
					// don't move immediately to give the AI time to 'think'
 | 
						|
					if (Random.Range(1, 100) < 3)
 | 
						|
					{
 | 
						|
						MakeAIMove(1);
 | 
						|
					}
 | 
						|
					break;
 | 
						|
 | 
						|
				case GameState.PracticingMyTurn:
 | 
						|
				case GameState.OnlineMatchMyTurn:
 | 
						|
					if (Input.GetButton("Fire1"))
 | 
						|
					{
 | 
						|
						TrySelectPiece();
 | 
						|
						TryPlacePiece();
 | 
						|
					}
 | 
						|
					break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Practicing with an AI Player
 | 
						|
 | 
						|
		public void PracticeButtonPressed()
 | 
						|
		{
 | 
						|
			m_opponentName = "* AI *";
 | 
						|
 | 
						|
			switch (m_state)
 | 
						|
			{
 | 
						|
				case GameState.OnlineMatchMyTurn:
 | 
						|
				case GameState.OnlineMatchRemoteTurn:
 | 
						|
					m_matchmaking.EndMatch(m_board.GetPlayerScore(0), m_board.GetPlayerScore(1));
 | 
						|
					break;
 | 
						|
			}
 | 
						|
			m_board.Reset();
 | 
						|
 | 
						|
			// randomly decised whether the player or AI goes first
 | 
						|
			if (Random.Range(0, 2) == 1)
 | 
						|
			{
 | 
						|
				TransitionToState(GameState.PracticingMyTurn);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				TransitionToState(GameState.PracticingAiTurn);
 | 
						|
			}
 | 
						|
 | 
						|
			UpdateScores();
 | 
						|
		}
 | 
						|
 | 
						|
		private void MakeAIMove(int player)
 | 
						|
		{
 | 
						|
			bool moved = false;
 | 
						|
 | 
						|
			// pick a random search start position
 | 
						|
			int rx = Random.Range(0, GameBoard.LENGTH_X - 1);
 | 
						|
			int ry = Random.Range(0, GameBoard.LENGTH_Y - 1);
 | 
						|
 | 
						|
			// from (rx,ry) search of an available move
 | 
						|
			for (int i = 0; i < GameBoard.LENGTH_X && !moved; i++)
 | 
						|
			{
 | 
						|
				for (int j = 0; j < GameBoard.LENGTH_Y && !moved; j++)
 | 
						|
				{
 | 
						|
					int x = (rx + i) % GameBoard.LENGTH_X;
 | 
						|
					int y = (ry + j) % GameBoard.LENGTH_Y;
 | 
						|
 | 
						|
					// first try to place a piece on the current position
 | 
						|
					if (m_board.CanPlayerMoveToPostion(x, y))
 | 
						|
					{
 | 
						|
						GamePiece p = Random.Range(0, 2) == 0 ? m_pieceA : m_pieceB;
 | 
						|
						m_board.AddPiece(player, p.Prefab, x, y);
 | 
						|
						moved = true;
 | 
						|
					}
 | 
						|
					// a random percentage of the time, try to powerup this position
 | 
						|
					else if (m_board.CanPlayerPowerUpPosition(x, y) && Random.Range(0, 8) < 2)
 | 
						|
					{
 | 
						|
						m_board.AddPowerPiece(player, m_powerPiece.Prefab, x, y);
 | 
						|
						moved = true;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if (moved)
 | 
						|
			{
 | 
						|
				UpdateScores();
 | 
						|
				TransitionToNextState();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Playing Online Match
 | 
						|
 | 
						|
		// called from the MatchmakingManager was a successly online match is made
 | 
						|
		public void StartOnlineMatch (string opponentName, bool localUserGoesFirst)
 | 
						|
		{
 | 
						|
			m_board.Reset();
 | 
						|
			m_opponentName = opponentName;
 | 
						|
 | 
						|
			if (localUserGoesFirst)
 | 
						|
			{
 | 
						|
				TransitionToState(GameState.OnlineMatchMyTurn);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				TransitionToState(GameState.OnlineMatchRemoteTurn);
 | 
						|
			}
 | 
						|
 | 
						|
			UpdateScores();
 | 
						|
		}
 | 
						|
 | 
						|
		// called from the Matchmaking Manager when the remote users their next move
 | 
						|
		public void MakeRemoteMove(GamePiece.Piece piece, int x, int y)
 | 
						|
		{
 | 
						|
			GameObject prefab = m_pieceA.PrefabFor(piece);
 | 
						|
 | 
						|
			if (piece == GamePiece.Piece.PowerBall)
 | 
						|
			{
 | 
						|
				m_board.AddPowerPiece(1, prefab, x, y);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				m_board.AddPiece(1, prefab, x, y);
 | 
						|
			}
 | 
						|
 | 
						|
			UpdateScores();
 | 
						|
		}
 | 
						|
 | 
						|
		// called from the MatchmakingManager when the local user becomes the room
 | 
						|
		// owner and thus it's safe for the local user to make their move
 | 
						|
		public void MarkRemoteTurnComplete()
 | 
						|
		{
 | 
						|
			if (m_state == GameState.OnlineMatchRemoteTurn)
 | 
						|
			{
 | 
						|
				TransitionToNextState();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		// the match ended from a player leaving before the board was complete
 | 
						|
		public void RemoteMatchEnded()
 | 
						|
		{
 | 
						|
			m_matchmaking.EndMatch(m_board.GetPlayerScore(0), m_board.GetPlayerScore(1));
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Selecting and Placing a Game Place
 | 
						|
 | 
						|
		public void StartedLookingAtPiece(GamePiece piece)
 | 
						|
		{
 | 
						|
			m_interestedPiece = piece;
 | 
						|
			UpdateGamePieceColors();
 | 
						|
		}
 | 
						|
 | 
						|
		public void StoppedLookingAtPiece()
 | 
						|
		{
 | 
						|
			m_interestedPiece = null;
 | 
						|
			UpdateGamePieceColors();
 | 
						|
		}
 | 
						|
 | 
						|
		// This method is used to display an example piece where the player is looking
 | 
						|
		// so they know what to expect when they press the Fire button.
 | 
						|
		public void StartedLookingAtPosition(BoardPosition position)
 | 
						|
		{
 | 
						|
			if (m_state != GameState.OnlineMatchMyTurn && m_state != GameState.PracticingMyTurn)
 | 
						|
				return;
 | 
						|
 | 
						|
			GamePiece newPiece = null;
 | 
						|
 | 
						|
			if ((m_selectedPiece == m_pieceA || m_selectedPiece == m_pieceB) &&
 | 
						|
				m_board.CanPlayerMoveToPostion(position.x, position.y))
 | 
						|
			{
 | 
						|
				newPiece = m_board.AddProposedPiece(m_selectedPiece.Prefab, position);
 | 
						|
			}
 | 
						|
			else if (m_selectedPiece == m_powerPiece &&
 | 
						|
				m_board.CanPlayerPowerUpPosition(position.x, position.y))
 | 
						|
			{
 | 
						|
				newPiece = m_board.AddProposedPowerPiece(m_selectedPiece.Prefab, position);
 | 
						|
			}
 | 
						|
 | 
						|
			if (newPiece != null)
 | 
						|
			{
 | 
						|
				if (m_proposedPiece != null)
 | 
						|
				{
 | 
						|
					Destroy(m_proposedPiece.gameObject);
 | 
						|
				}
 | 
						|
				m_proposedPiece = newPiece;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public void ClearProposedMove()
 | 
						|
		{
 | 
						|
			if (m_proposedPiece != null)
 | 
						|
			{
 | 
						|
				Destroy(m_proposedPiece.gameObject);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public void TrySelectPiece()
 | 
						|
		{
 | 
						|
			if (m_interestedPiece == m_pieceA || m_interestedPiece == m_pieceB)
 | 
						|
			{
 | 
						|
				m_selectedPiece = m_interestedPiece;
 | 
						|
			}
 | 
						|
			else if (m_interestedPiece == m_powerPiece &&
 | 
						|
					(m_powerBallcount > 0 || m_state == GameState.PracticingMyTurn))
 | 
						|
			{
 | 
						|
				m_selectedPiece = m_interestedPiece;
 | 
						|
			}
 | 
						|
			UpdateGamePieceColors();
 | 
						|
		}
 | 
						|
 | 
						|
		public void TryPlacePiece()
 | 
						|
		{
 | 
						|
			if (m_proposedPiece == null)
 | 
						|
				return;
 | 
						|
 | 
						|
			var position = m_proposedPiece.Position;
 | 
						|
			switch(m_proposedPiece.Type)
 | 
						|
			{
 | 
						|
				case GamePiece.Piece.A:
 | 
						|
				case GamePiece.Piece.B:
 | 
						|
					m_board.AddPiece(0, m_proposedPiece.Prefab, position.x, position.y);
 | 
						|
					break;
 | 
						|
				case GamePiece.Piece.PowerBall:
 | 
						|
					m_board.AddPowerPiece(0, m_proposedPiece.Prefab, position.x, position.y);
 | 
						|
					break;
 | 
						|
			}
 | 
						|
			Destroy(m_proposedPiece.gameObject);
 | 
						|
 | 
						|
			if (m_state == GameState.OnlineMatchMyTurn)
 | 
						|
			{
 | 
						|
				m_matchmaking.SendLocalMove(m_proposedPiece.Type, position.x, position.y);
 | 
						|
			}
 | 
						|
 | 
						|
			UpdateScores();
 | 
						|
			TransitionToNextState();
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region UI
 | 
						|
 | 
						|
		public void QuitButtonPressed()
 | 
						|
		{
 | 
						|
			UnityEngine.Application.Quit();
 | 
						|
		}
 | 
						|
 | 
						|
		public void AddPowerballs(uint count)
 | 
						|
		{
 | 
						|
			m_powerBallcount += count;
 | 
						|
			m_ballCountText.text = "x" + m_powerBallcount.ToString();
 | 
						|
		}
 | 
						|
 | 
						|
		private void UpdateScores()
 | 
						|
		{
 | 
						|
			m_player0Text.text = string.Format("{0}\n\n{1}",
 | 
						|
				PlatformManager.MyOculusID, m_board.GetPlayerScore(0));
 | 
						|
 | 
						|
			m_player1Text.text = string.Format("{0}\n\n{1}",
 | 
						|
				m_opponentName, m_board.GetPlayerScore(1));
 | 
						|
		}
 | 
						|
 | 
						|
		private void UpdateGamePieceColors()
 | 
						|
		{
 | 
						|
			switch (m_state)
 | 
						|
			{
 | 
						|
				case GameState.None:
 | 
						|
				case GameState.PracticingAiTurn:
 | 
						|
				case GameState.OnlineMatchRemoteTurn:
 | 
						|
					m_pieceA.GetComponent<Renderer>().material.color = m_unusableColor;
 | 
						|
					m_pieceB.GetComponent<Renderer>().material.color = m_unusableColor;
 | 
						|
					m_powerPiece.GetComponent<Renderer>().material.color = m_unusableColor;
 | 
						|
					if (m_proposedPiece != null)
 | 
						|
					{
 | 
						|
						Destroy(m_proposedPiece.gameObject);
 | 
						|
					}
 | 
						|
					break;
 | 
						|
 | 
						|
				case GameState.PracticingMyTurn:
 | 
						|
				case GameState.OnlineMatchMyTurn:
 | 
						|
					m_pieceA.GetComponent<Renderer>().material.color = m_unselectedColor;
 | 
						|
					m_pieceB.GetComponent<Renderer>().material.color = m_unselectedColor;
 | 
						|
					m_powerPiece.GetComponent<Renderer>().material.color = m_unselectedColor;
 | 
						|
					if (m_interestedPiece == m_pieceA || m_interestedPiece == m_pieceB ||
 | 
						|
						m_interestedPiece == m_powerPiece)
 | 
						|
					{
 | 
						|
						m_interestedPiece.GetComponent<Renderer>().material.color = m_highlightedColor;
 | 
						|
					}
 | 
						|
					if (m_selectedPiece != null)
 | 
						|
					{
 | 
						|
						m_selectedPiece.GetComponent<Renderer>().material.color = m_selectedColor;
 | 
						|
					}
 | 
						|
					break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
	}
 | 
						|
}
 |