
Added graphics options and rendering quality level settings Added new movement patterns to the dumb enemy AI Added chance for Coward Enemies to drop a random Added method to correctly reset the game variables on death and win screens Updated the UI to work on different resolutions without breaking Moved Sprites into a sprites folder Fixed issue where score would overflow the int because the multiplier was too high Fixed issue where new lives gained from the score breakpoints were not being calculated correctly Fixed issue where clicking off a menu element then trying to control the menu with the controller did not correctly reselect a menu item Fixed issue where enemies colliding with the outer boundary too much would break the sfx and music (i assume from a buffering issue)
593 lines
20 KiB
C#
593 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;
|
|
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);
|
|
}
|
|
} |