594 lines
20 KiB
C#
594 lines
20 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.EventSystems;
|
|
|
|
public class GameEngine : MonoBehaviour
|
|
{
|
|
[Header("Game Attributes")]
|
|
public GameObject currentBlackHole;
|
|
public GameObject currentPlayer;
|
|
public static GameObject mainPlayer;
|
|
public GameObject winCinematicGO;
|
|
private PlayerHoverMovement _playerHoverMovement;
|
|
private PlayerObjectShared _playerObjectShared;
|
|
private BlackHoleManager _currentBlackHoleManager;
|
|
public float arenaSize;
|
|
|
|
[Header("Sound Elements")]
|
|
public BackgroundMusicManager currentBGMManager;
|
|
public AudioSource currentSFXAudioSource;
|
|
public MenuAudioManager currentMenuAudioManager;
|
|
public AudioClip lifeUpSFX;
|
|
|
|
//public TMPro.TextMeshProUGUI coreCountText;
|
|
|
|
[Header("Gameplay UI Elements")]
|
|
public GameObject livesBar;
|
|
public GameObject coresText;
|
|
public GameObject coresBar;
|
|
public GameObject coresFillBar;
|
|
public GameObject boostStatus;
|
|
public GameObject boostBar;
|
|
public GameObject abilityDesc;
|
|
public GameObject abilityStatus;
|
|
public GameObject abilityBar;
|
|
public GameObject scoreText;
|
|
public GameObject levelText;
|
|
public GameObject startTimeline;
|
|
public GoTextFadeHelper goText;
|
|
public GameObject jumpTextGO;
|
|
|
|
private bool boostBarShown = false;
|
|
private bool abilityBarShown = false;
|
|
|
|
[Header("Pause Menu Elements")]
|
|
public TMPro.TextMeshProUGUI versionText;
|
|
public GameObject pauseMenu;
|
|
public GameObject mainPausePanel;
|
|
public GameObject optionsPanel;
|
|
public GameObject confirmPanel;
|
|
public static bool isPaused = true;
|
|
public static bool playerPaused = false;
|
|
public GameObject pauseMenuFirstItem;
|
|
private GameObject _lastControlSelected;
|
|
|
|
private float _prevTimeScale;
|
|
|
|
public static bool gameStarted = false;
|
|
private bool _musicSwappedA = false;
|
|
|
|
private HiddenValueInt _lastScoreCheck;
|
|
private HiddenValueInt _scorePerLifeUp;
|
|
private bool _gameOverHit;
|
|
private bool _playerJumped;
|
|
private TimerHelper _playerJumpFlash;
|
|
private bool _winCinematicDone;
|
|
|
|
[Header("Dialog Elements")]
|
|
public GameObject dialogMainUIGO;
|
|
public float dialogDisplayTime;
|
|
public AudioClip dialogSFXClip;
|
|
public List<GameObject> dialogGOList;
|
|
|
|
private List<bool> _dialogRanCheck = new List<bool>();
|
|
private Queue<int> _dialogQueue = new Queue<int>();
|
|
private int _currentDialogIndex;
|
|
private TimerHelper _dialogTimer;
|
|
private bool _dialogActive;
|
|
|
|
private TimerHelper _bonusTimeLimit;
|
|
|
|
// Start is called before the first frame update
|
|
void Awake()
|
|
{
|
|
// Make sure godmode is off when starting.
|
|
GameManager.Instance.currentGameState = GameState.GAME;
|
|
GameManager.Instance.godMode = false;
|
|
GameManager.Instance.SetupLevel();
|
|
|
|
// Get the current blackhole so we have easy access to its variables
|
|
_currentBlackHoleManager = currentBlackHole.GetComponent<BlackHoleManager>();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
// Start the game, make sure the play GO is active
|
|
//currentPlayer.SetActive(true);
|
|
gameStarted = false;
|
|
if (currentBGMManager)
|
|
{
|
|
currentBGMManager.StartAudioQueueAndPlay(0);
|
|
}
|
|
|
|
_playerHoverMovement = currentPlayer.GetComponent<PlayerHoverMovement>();
|
|
_playerObjectShared = currentPlayer.GetComponent<PlayerObjectShared>();
|
|
versionText.text = versionText.text.Replace("{versionNo}", GameManager.Instance.CurrentVersion);
|
|
mainPlayer = currentPlayer;
|
|
_prevTimeScale = 1.0f;
|
|
_lastScoreCheck = new HiddenValueInt(0);
|
|
_scorePerLifeUp = new HiddenValueInt(10000);
|
|
currentPlayer.SetActive(false);
|
|
startTimeline.SetActive(true);
|
|
_gameOverHit = false;
|
|
_playerJumped = false;
|
|
_playerJumpFlash = new TimerHelper(0.5f);
|
|
_winCinematicDone = false;
|
|
_lastControlSelected = EventSystem.current.firstSelectedGameObject;
|
|
|
|
for (int i = 0; i < dialogGOList.Count; i++)
|
|
{
|
|
_dialogRanCheck.Add(false);
|
|
}
|
|
|
|
_bonusTimeLimit = new TimerHelper(1200, false, TimerDirection.TimerDecrement);
|
|
}
|
|
|
|
public void StartGame()
|
|
{
|
|
currentPlayer.SetActive(true);
|
|
isPaused = false;
|
|
playerPaused = false;
|
|
gameStarted = true;
|
|
Destroy(startTimeline);
|
|
currentBGMManager.CreateLoopQueue(1, 2, 3);
|
|
goText.StartFade();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the current blackhole radius
|
|
/// </summary>
|
|
/// <returns>Current Blackhole size as a float</returns>
|
|
public float GetCurrentBlackHoleRadius()
|
|
{
|
|
return _currentBlackHoleManager.currentBlackHoleRadius;
|
|
}
|
|
|
|
private void UpdateLifeBar()
|
|
{
|
|
if (livesBar != null)
|
|
{
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
Transform currentLife = livesBar.transform.Find("Life" + i.ToString());
|
|
if (currentLife != null)
|
|
{
|
|
if (i <= GameManager.Instance.CurrentLives)
|
|
{
|
|
currentLife.gameObject.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
currentLife.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
Transform lifeOverflow = livesBar.transform.Find("LifeOverflow");
|
|
if (lifeOverflow != null)
|
|
{
|
|
if (GameManager.Instance.CurrentLives > 5)
|
|
{
|
|
lifeOverflow.gameObject.SetActive(true);
|
|
lifeOverflow.GetComponent<TMPro.TextMeshProUGUI>().text = "(+" + (GameManager.Instance.CurrentLives - 5).ToString() + ")";
|
|
}
|
|
else
|
|
{
|
|
lifeOverflow.GetComponent<TMPro.TextMeshProUGUI>().text = "(+0)";
|
|
lifeOverflow.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateCoresBar()
|
|
{
|
|
float corePowerPercent = (float)GameManager.Instance.CurrentCores / (float)GameManager.Instance.CurrentNeededCores;
|
|
|
|
if (coresText != null)
|
|
{
|
|
coresText.GetComponent<TMPro.TextMeshProUGUI>().text = "Core Power: " + Mathf.RoundToInt(corePowerPercent * 100.0f) + "%";
|
|
}
|
|
|
|
if (coresBar != null)
|
|
{
|
|
if (coresFillBar != null)
|
|
{
|
|
RectTransform fillBarImage = coresFillBar.GetComponent<RectTransform>();
|
|
RectTransform parentBar = fillBarImage.parent.GetComponent<RectTransform>();
|
|
float leftOffset = parentBar.rect.size.x - (parentBar.rect.size.x * corePowerPercent);
|
|
fillBarImage.offsetMin = new Vector2(leftOffset, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateScore()
|
|
{
|
|
if (scoreText != null)
|
|
{
|
|
scoreText.GetComponent<TMPro.TextMeshProUGUI>().text = GameManager.Instance.CurrentScore.ToString().PadLeft(9, '0');
|
|
}
|
|
int newLifeCheck = Mathf.FloorToInt(GameManager.Instance.CurrentScore / _scorePerLifeUp.Value);
|
|
if (_lastScoreCheck.Value < newLifeCheck && !_gameOverHit)
|
|
{
|
|
GameManager.Instance.AddLife(newLifeCheck - _lastScoreCheck.Value);
|
|
_lastScoreCheck.Value = newLifeCheck;
|
|
if (lifeUpSFX != null)
|
|
{
|
|
currentSFXAudioSource.PlayOneShot(lifeUpSFX);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateLevel()
|
|
{
|
|
if (levelText != null)
|
|
{
|
|
levelText.GetComponent<TMPro.TextMeshProUGUI>().text = (GameManager.Instance.CurrentLevel + 1).ToString().PadLeft(2, '0');
|
|
}
|
|
}
|
|
|
|
private void UpdateBoostStatus()
|
|
{
|
|
if (boostStatus != null)
|
|
{
|
|
if (_playerHoverMovement != null)
|
|
{
|
|
if (_playerHoverMovement.BoostReady)
|
|
{
|
|
boostStatus.SetActive(true);
|
|
boostBar.SetActive(false);
|
|
boostBarShown = false;
|
|
}
|
|
else
|
|
{
|
|
if (boostBarShown)
|
|
{
|
|
if (boostBar != null)
|
|
{
|
|
Transform boostFillBar = boostBar.transform.Find("BoostBackgroundBar/BoostFillBar");
|
|
if (boostFillBar != null)
|
|
{
|
|
RectTransform fillBarImage = boostFillBar.gameObject.GetComponent<RectTransform>();
|
|
RectTransform parentBar = fillBarImage.parent.GetComponent<RectTransform>();
|
|
float rightOffset = -parentBar.rect.size.x + (parentBar.rect.size.x * _playerHoverMovement.BoostCooldownPosition);
|
|
fillBarImage.offsetMax = new Vector2(rightOffset, 0);
|
|
//fillBarImage.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, leftOffset);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
boostStatus.SetActive(false);
|
|
boostBar.SetActive(true);
|
|
boostBarShown = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateAbilityBar()
|
|
{
|
|
if (_playerObjectShared.currentAbility != null)
|
|
{
|
|
if (abilityDesc != null)
|
|
{
|
|
abilityDesc.SetActive(true);
|
|
abilityDesc.GetComponent<TMPro.TextMeshProUGUI>().text = _playerObjectShared.currentAbility.uiDescText;
|
|
}
|
|
|
|
if (abilityBar != null)
|
|
{
|
|
abilityStatus.GetComponent<TMPro.TextMeshProUGUI>().text = _playerObjectShared.currentAbility.uiReadyText;
|
|
if (!_playerObjectShared.currentAbility.CooldownStatus)
|
|
{
|
|
abilityStatus.SetActive(true);
|
|
abilityBar.SetActive(false);
|
|
abilityBarShown = false;
|
|
}
|
|
else
|
|
{
|
|
if (abilityBarShown)
|
|
{
|
|
if (abilityBar != null)
|
|
{
|
|
Transform abilityFillBar = abilityBar.transform.Find("PowerBackgroundBar/PowerFillBar");
|
|
if (abilityFillBar != null)
|
|
{
|
|
RectTransform fillBarImage = abilityFillBar.gameObject.GetComponent<RectTransform>();
|
|
RectTransform parentBar = fillBarImage.parent.GetComponent<RectTransform>();
|
|
float leftOffset = parentBar.rect.size.x - (parentBar.rect.size.x * _playerObjectShared.currentAbility.CooldownTimePercent);
|
|
fillBarImage.offsetMin = new Vector2(leftOffset, 0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
abilityStatus.SetActive(false);
|
|
abilityBar.SetActive(true);
|
|
abilityBarShown = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
abilityBar.SetActive(false);
|
|
abilityStatus.SetActive(false);
|
|
abilityDesc.SetActive(false);
|
|
abilityBarShown = false;
|
|
}
|
|
|
|
}
|
|
|
|
public void DoDialog(int dialogIndex, bool force = false)
|
|
{
|
|
if ((!_dialogActive && !_dialogRanCheck[dialogIndex]) || force)
|
|
{
|
|
_currentDialogIndex = dialogIndex;
|
|
_dialogTimer = new TimerHelper(dialogDisplayTime, false);
|
|
dialogMainUIGO.SetActive(true);
|
|
dialogGOList[_currentDialogIndex].SetActive(true);
|
|
_dialogActive = true;
|
|
if (dialogSFXClip != null)
|
|
{
|
|
currentSFXAudioSource.PlayOneShot(dialogSFXClip);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void QueueDialog(int dialogIndex)
|
|
{
|
|
if (!_dialogRanCheck[dialogIndex])
|
|
{
|
|
if (_dialogActive)
|
|
{
|
|
_dialogQueue.Enqueue(dialogIndex);
|
|
}
|
|
else
|
|
{
|
|
DoDialog(dialogIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckDialog(float currentTimeStamp)
|
|
{
|
|
if (_dialogActive)
|
|
{
|
|
if (_dialogTimer.HasTicked(currentTimeStamp))
|
|
{
|
|
_dialogRanCheck[_currentDialogIndex] = true;
|
|
dialogGOList[_currentDialogIndex].SetActive(false);
|
|
dialogMainUIGO.SetActive(false);
|
|
_dialogTimer.RestartTimer();
|
|
_dialogActive = false;
|
|
if (_dialogQueue.Count > 0)
|
|
{
|
|
DoDialog(_dialogQueue.Dequeue());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void LateUpdate()
|
|
{
|
|
if (gameStarted)
|
|
{
|
|
UpdateLifeBar();
|
|
UpdateCoresBar();
|
|
UpdateScore();
|
|
UpdateLevel();
|
|
UpdateBoostStatus();
|
|
UpdateAbilityBar();
|
|
|
|
if (GameManager.Instance.CurrentLevel == 3)
|
|
{
|
|
if (!_musicSwappedA)
|
|
{
|
|
currentBGMManager.QueueIntroThenLoopQueue(4, 5, 6, 7, 6, 8);
|
|
_musicSwappedA = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (gameStarted)
|
|
{
|
|
CheckDialog(Time.deltaTime);
|
|
|
|
if (Input.GetButtonDown("Cancel"))
|
|
{
|
|
if (!_gameOverHit)
|
|
{
|
|
if (!isPaused)
|
|
{
|
|
isPaused = true;
|
|
pauseMenu.SetActive(true);
|
|
EventSystem.current.SetSelectedGameObject(pauseMenuFirstItem);
|
|
_lastControlSelected = pauseMenuFirstItem;
|
|
_prevTimeScale = Time.timeScale;
|
|
Time.timeScale = 0;
|
|
}
|
|
else
|
|
{
|
|
UnpauseGame();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isPaused)
|
|
{
|
|
float horzIn = Input.GetAxisRaw("Horizontal");
|
|
float vertIn = Input.GetAxisRaw("Vertical");
|
|
|
|
if (horzIn != 0 || vertIn != 0)
|
|
{
|
|
if (EventSystem.current.currentSelectedGameObject == null)
|
|
{
|
|
EventSystem.current.SetSelectedGameObject(pauseMenuFirstItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!_playerJumped)
|
|
{
|
|
if (Input.GetButtonDown("Jump"))
|
|
{
|
|
DoDialog(0);
|
|
_playerJumped = true;
|
|
jumpTextGO.SetActive(false);
|
|
}
|
|
else
|
|
{
|
|
if (jumpTextGO != null)
|
|
{
|
|
if (_playerJumpFlash.HasTicked(Time.deltaTime))
|
|
{
|
|
jumpTextGO.SetActive(!jumpTextGO.activeSelf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!_gameOverHit)
|
|
{
|
|
if (GameManager.Instance.CurrentLevel >= 5)
|
|
{
|
|
if (winCinematicGO != null)
|
|
{
|
|
winCinematicGO.transform.position = currentPlayer.transform.position;
|
|
winCinematicGO.transform.rotation = currentPlayer.transform.rotation;
|
|
winCinematicGO.SetActive(true);
|
|
currentPlayer.SetActive(false);
|
|
}
|
|
else
|
|
{
|
|
_winCinematicDone = true;
|
|
}
|
|
isPaused = true;
|
|
_gameOverHit = true;
|
|
CalcFinalScore(true);
|
|
}
|
|
|
|
if (GameManager.Instance.CurrentLives < 0)
|
|
{
|
|
CalcFinalScore(false);
|
|
GameManager.Instance.DoGameOver();
|
|
_gameOverHit = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_winCinematicDone)
|
|
{
|
|
GameManager.Instance.DoGameWon();
|
|
_winCinematicDone = false;
|
|
}
|
|
}
|
|
|
|
_bonusTimeLimit.HasTicked(Time.deltaTime);
|
|
}
|
|
}
|
|
|
|
public void CalcFinalScore(bool wonGame)
|
|
{
|
|
int workingScore = GameManager.Instance.CurrentScore;
|
|
workingScore += 10000 * GameManager.Instance.CurrentLevel;
|
|
if (wonGame)
|
|
{
|
|
workingScore += 1000 * GameManager.Instance.CurrentLives;
|
|
workingScore += 5000 * Mathf.FloorToInt(_bonusTimeLimit.Position * 100.0f);
|
|
}
|
|
GameManager.Instance.SetScore(workingScore);
|
|
}
|
|
|
|
public void FlagWin()
|
|
{
|
|
_winCinematicDone = true;
|
|
}
|
|
|
|
public void UnpauseGame()
|
|
{
|
|
isPaused = false;
|
|
mainPausePanel.SetActive(true);
|
|
optionsPanel.SetActive(false);
|
|
confirmPanel.SetActive(false);
|
|
pauseMenu.SetActive(false);
|
|
Time.timeScale = _prevTimeScale;
|
|
}
|
|
|
|
public void SetupVolumeOptions()
|
|
{
|
|
// Gets the volume settings from the player profile and sets it in the game
|
|
float currentMasterVol = PlayerPrefs.GetFloat("currentMasterVol");
|
|
GameObject masterVolSliderGo = GameObject.Find("MainVolSlider");
|
|
|
|
float currentMusicVol = PlayerPrefs.GetFloat("currentMusicVol");
|
|
GameObject musicVolSliderGo = GameObject.Find("MusicVolSlider");
|
|
|
|
float currentSFXVol = PlayerPrefs.GetFloat("currentSFXVol");
|
|
GameObject SFXVolSliderGo = GameObject.Find("SfxVolSlider");
|
|
|
|
masterVolSliderGo.GetComponent<Slider>().value = currentMasterVol;
|
|
musicVolSliderGo.GetComponent<Slider>().value = currentMusicVol;
|
|
SFXVolSliderGo.GetComponent<Slider>().value = currentSFXVol;
|
|
}
|
|
|
|
public void PlayMenuClick()
|
|
{
|
|
if (currentMenuAudioManager)
|
|
{
|
|
currentMenuAudioManager.PlayMenuClick();
|
|
}
|
|
}
|
|
|
|
public void ResumeGame()
|
|
{
|
|
// Play the menu click sound if the audio manager is present
|
|
if (currentMenuAudioManager)
|
|
{
|
|
currentMenuAudioManager.PlayMenuClick();
|
|
}
|
|
UnpauseGame();
|
|
}
|
|
|
|
public void Quit()
|
|
{
|
|
// Play the menu click sound if the audio manager is present
|
|
if (currentMenuAudioManager)
|
|
{
|
|
currentMenuAudioManager.PlayMenuClick();
|
|
}
|
|
|
|
Time.timeScale = 1.0f;
|
|
SceneManager.LoadSceneAsync("MainMenu");
|
|
}
|
|
|
|
public void SetMasterVolume(float value)
|
|
{
|
|
// Converts the master volume into decibels and stores it in the player profile
|
|
GameManager.Instance.currentAudioMixer.SetFloat("masterVol", SharedMethods.ConvertToDecibels(value));
|
|
PlayerPrefs.SetFloat("currentMasterVol", value);
|
|
}
|
|
|
|
public void SetMusicVolume(float value)
|
|
{
|
|
// Converts the music volume into decibels and stores it in the player profile
|
|
GameManager.Instance.currentAudioMixer.SetFloat("musicVol", SharedMethods.ConvertToDecibels(value));
|
|
PlayerPrefs.SetFloat("currentMusicVol", value);
|
|
}
|
|
|
|
public void SetSFXVolume(float value)
|
|
{
|
|
// Converts the sfx volume into decibels and stores it in the player profile
|
|
GameManager.Instance.currentAudioMixer.SetFloat("sfxVol", SharedMethods.ConvertToDecibels(value));
|
|
PlayerPrefs.SetFloat("currentSFXVol", value);
|
|
}
|
|
} |