267 lines
8.6 KiB
C#
267 lines
8.6 KiB
C#
|
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
// <copyright file="AsteroidsGameManager.cs" company="Exit Games GmbH">
|
|||
|
// Part of: Asteroid demo
|
|||
|
// </copyright>
|
|||
|
// <summary>
|
|||
|
// Game Manager for the Asteroid Demo
|
|||
|
// </summary>
|
|||
|
// <author>developer@exitgames.com</author>
|
|||
|
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
using System.Collections;
|
|||
|
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.UI;
|
|||
|
|
|||
|
using Photon.Realtime;
|
|||
|
using Photon.Pun.UtilityScripts;
|
|||
|
using Hashtable = ExitGames.Client.Photon.Hashtable;
|
|||
|
|
|||
|
namespace Photon.Pun.Demo.Asteroids
|
|||
|
{
|
|||
|
public class AsteroidsGameManager : MonoBehaviourPunCallbacks
|
|||
|
{
|
|||
|
public static AsteroidsGameManager Instance = null;
|
|||
|
|
|||
|
public Text InfoText;
|
|||
|
|
|||
|
public GameObject[] AsteroidPrefabs;
|
|||
|
|
|||
|
#region UNITY
|
|||
|
|
|||
|
public void Awake()
|
|||
|
{
|
|||
|
Instance = this;
|
|||
|
}
|
|||
|
|
|||
|
public override void OnEnable()
|
|||
|
{
|
|||
|
base.OnEnable();
|
|||
|
|
|||
|
CountdownTimer.OnCountdownTimerHasExpired += OnCountdownTimerIsExpired;
|
|||
|
}
|
|||
|
|
|||
|
public void Start()
|
|||
|
{
|
|||
|
Hashtable props = new Hashtable
|
|||
|
{
|
|||
|
{AsteroidsGame.PLAYER_LOADED_LEVEL, true}
|
|||
|
};
|
|||
|
PhotonNetwork.LocalPlayer.SetCustomProperties(props);
|
|||
|
}
|
|||
|
|
|||
|
public override void OnDisable()
|
|||
|
{
|
|||
|
base.OnDisable();
|
|||
|
|
|||
|
CountdownTimer.OnCountdownTimerHasExpired -= OnCountdownTimerIsExpired;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region COROUTINES
|
|||
|
|
|||
|
private IEnumerator SpawnAsteroid()
|
|||
|
{
|
|||
|
while (true)
|
|||
|
{
|
|||
|
yield return new WaitForSeconds(Random.Range(AsteroidsGame.ASTEROIDS_MIN_SPAWN_TIME, AsteroidsGame.ASTEROIDS_MAX_SPAWN_TIME));
|
|||
|
|
|||
|
Vector2 direction = Random.insideUnitCircle;
|
|||
|
Vector3 position = Vector3.zero;
|
|||
|
|
|||
|
if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
|
|||
|
{
|
|||
|
// Make it appear on the left/right side
|
|||
|
position = new Vector3(Mathf.Sign(direction.x) * Camera.main.orthographicSize * Camera.main.aspect, 0, direction.y * Camera.main.orthographicSize);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Make it appear on the top/bottom
|
|||
|
position = new Vector3(direction.x * Camera.main.orthographicSize * Camera.main.aspect, 0, Mathf.Sign(direction.y) * Camera.main.orthographicSize);
|
|||
|
}
|
|||
|
|
|||
|
// Offset slightly so we are not out of screen at creation time (as it would destroy the asteroid right away)
|
|||
|
position -= position.normalized * 0.1f;
|
|||
|
|
|||
|
|
|||
|
Vector3 force = -position.normalized * 1000.0f;
|
|||
|
Vector3 torque = Random.insideUnitSphere * Random.Range(500.0f, 1500.0f);
|
|||
|
object[] instantiationData = {force, torque, true};
|
|||
|
|
|||
|
PhotonNetwork.InstantiateRoomObject("BigAsteroid", position, Quaternion.Euler(Random.value * 360.0f, Random.value * 360.0f, Random.value * 360.0f), 0, instantiationData);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private IEnumerator EndOfGame(string winner, int score)
|
|||
|
{
|
|||
|
float timer = 5.0f;
|
|||
|
|
|||
|
while (timer > 0.0f)
|
|||
|
{
|
|||
|
InfoText.text = string.Format("Player {0} won with {1} points.\n\n\nReturning to login screen in {2} seconds.", winner, score, timer.ToString("n2"));
|
|||
|
|
|||
|
yield return new WaitForEndOfFrame();
|
|||
|
|
|||
|
timer -= Time.deltaTime;
|
|||
|
}
|
|||
|
|
|||
|
PhotonNetwork.LeaveRoom();
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region PUN CALLBACKS
|
|||
|
|
|||
|
public override void OnDisconnected(DisconnectCause cause)
|
|||
|
{
|
|||
|
UnityEngine.SceneManagement.SceneManager.LoadScene("DemoAsteroids-LobbyScene");
|
|||
|
}
|
|||
|
|
|||
|
public override void OnLeftRoom()
|
|||
|
{
|
|||
|
PhotonNetwork.Disconnect();
|
|||
|
}
|
|||
|
|
|||
|
public override void OnMasterClientSwitched(Player newMasterClient)
|
|||
|
{
|
|||
|
if (PhotonNetwork.LocalPlayer.ActorNumber == newMasterClient.ActorNumber)
|
|||
|
{
|
|||
|
StartCoroutine(SpawnAsteroid());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override void OnPlayerLeftRoom(Player otherPlayer)
|
|||
|
{
|
|||
|
CheckEndOfGame();
|
|||
|
}
|
|||
|
|
|||
|
public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
|
|||
|
{
|
|||
|
if (changedProps.ContainsKey(AsteroidsGame.PLAYER_LIVES))
|
|||
|
{
|
|||
|
CheckEndOfGame();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (!PhotonNetwork.IsMasterClient)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// if there was no countdown yet, the master client (this one) waits until everyone loaded the level and sets a timer start
|
|||
|
int startTimestamp;
|
|||
|
bool startTimeIsSet = CountdownTimer.TryGetStartTime(out startTimestamp);
|
|||
|
|
|||
|
if (changedProps.ContainsKey(AsteroidsGame.PLAYER_LOADED_LEVEL))
|
|||
|
{
|
|||
|
if (CheckAllPlayerLoadedLevel())
|
|||
|
{
|
|||
|
if (!startTimeIsSet)
|
|||
|
{
|
|||
|
CountdownTimer.SetStartTime();
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// not all players loaded yet. wait:
|
|||
|
Debug.Log("setting text waiting for players! ",this.InfoText);
|
|||
|
InfoText.text = "Waiting for other players...";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
// called by OnCountdownTimerIsExpired() when the timer ended
|
|||
|
private void StartGame()
|
|||
|
{
|
|||
|
Debug.Log("StartGame!");
|
|||
|
|
|||
|
// on rejoin, we have to figure out if the spaceship exists or not
|
|||
|
// if this is a rejoin (the ship is already network instantiated and will be setup via event) we don't need to call PN.Instantiate
|
|||
|
|
|||
|
|
|||
|
float angularStart = (360.0f / PhotonNetwork.CurrentRoom.PlayerCount) * PhotonNetwork.LocalPlayer.GetPlayerNumber();
|
|||
|
float x = 20.0f * Mathf.Sin(angularStart * Mathf.Deg2Rad);
|
|||
|
float z = 20.0f * Mathf.Cos(angularStart * Mathf.Deg2Rad);
|
|||
|
Vector3 position = new Vector3(x, 0.0f, z);
|
|||
|
Quaternion rotation = Quaternion.Euler(0.0f, angularStart, 0.0f);
|
|||
|
|
|||
|
PhotonNetwork.Instantiate("Spaceship", position, rotation, 0); // avoid this call on rejoin (ship was network instantiated before)
|
|||
|
|
|||
|
if (PhotonNetwork.IsMasterClient)
|
|||
|
{
|
|||
|
StartCoroutine(SpawnAsteroid());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool CheckAllPlayerLoadedLevel()
|
|||
|
{
|
|||
|
foreach (Player p in PhotonNetwork.PlayerList)
|
|||
|
{
|
|||
|
object playerLoadedLevel;
|
|||
|
|
|||
|
if (p.CustomProperties.TryGetValue(AsteroidsGame.PLAYER_LOADED_LEVEL, out playerLoadedLevel))
|
|||
|
{
|
|||
|
if ((bool) playerLoadedLevel)
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
private void CheckEndOfGame()
|
|||
|
{
|
|||
|
bool allDestroyed = true;
|
|||
|
|
|||
|
foreach (Player p in PhotonNetwork.PlayerList)
|
|||
|
{
|
|||
|
object lives;
|
|||
|
if (p.CustomProperties.TryGetValue(AsteroidsGame.PLAYER_LIVES, out lives))
|
|||
|
{
|
|||
|
if ((int) lives > 0)
|
|||
|
{
|
|||
|
allDestroyed = false;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (allDestroyed)
|
|||
|
{
|
|||
|
if (PhotonNetwork.IsMasterClient)
|
|||
|
{
|
|||
|
StopAllCoroutines();
|
|||
|
}
|
|||
|
|
|||
|
string winner = "";
|
|||
|
int score = -1;
|
|||
|
|
|||
|
foreach (Player p in PhotonNetwork.PlayerList)
|
|||
|
{
|
|||
|
if (p.GetScore() > score)
|
|||
|
{
|
|||
|
winner = p.NickName;
|
|||
|
score = p.GetScore();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
StartCoroutine(EndOfGame(winner, score));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnCountdownTimerIsExpired()
|
|||
|
{
|
|||
|
StartGame();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|