This commit is contained in:
Gerard Gascón 2025-04-24 17:29:51 +02:00
commit 3b4c6e0ec6
506 changed files with 434142 additions and 0 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: deba05c3348cf404bb0ba0a77380267a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,71 @@
using UnityEngine;
using System;
public class AudioManager : MonoBehaviour{
[SerializeField] Sound[] sounds = default;
public static AudioManager instance;
// Start is called before the first frame update
void Awake(){
if(instance == null){
instance = this;
}else{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
foreach(Sound s in sounds){
s.source = gameObject.AddComponent<AudioSource>();
s.source.clip = s.clip;
s.source.volume = s.volume;
s.source.pitch = s.pitch;
s.source.loop = s.loop;
}
}
public void Play(string name){
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("Sound: " + name + " not found!");
return;
}
s.source.Play();
}
public void PlayOneShot(string name){
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("Sound: " + name + " not found!");
return;
}
s.source.PlayOneShot(s.clip);
}
public void Stop(string name){
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("Sound: " + name + " not found!");
return;
}
s.source.Stop();
}
public void PlayWithRandomPitch(string name){
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("Sound: " + name + " not found!");
return;
}
s.source.volume = s.volume * (1f + UnityEngine.Random.Range(-s.volumeVariance / 2f, s.volumeVariance / 2f));
s.source.pitch = s.pitch * (1f + UnityEngine.Random.Range(-s.pitchVariance / 2f, s.pitchVariance / 2f));
s.source.PlayOneShot(s.clip);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6ad4d560a5e7c24480d454ea82006f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
using UnityEngine;
[System.Serializable]
public class Sound{
public string name;
public AudioClip clip;
[Range(0f, 1f)] public float volume;
[Range(0f, 1f)] public float volumeVariance;
[Range(.1f, 3f)] public float pitch;
[Range(0f, 1f)] public float pitchVariance;
public bool loop;
[HideInInspector] public AudioSource source;
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42f73f4d81953754c96cc4e7a2a7bed5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,77 @@
using Cinemachine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombController : MonoBehaviour, IPooledObject{
[SerializeField, Range(0, 5f)] float timeToExplode = 1.5f;
float currentTime;
[SerializeField, Range(1, 10)] int maxDistance = 5;
[Space]
[SerializeField, Range(0, .3f)] float timeBetweenExplosions = .05f;
bool exploded;
[SerializeField] LayerMask whatIsWall = -1;
bool canRightSpawn, canLeftSpawn, canForwardSpawn, canBackSpawn;
public void OnObjectSpawn(){
currentTime = 0;
exploded = false;
canRightSpawn = canLeftSpawn = canForwardSpawn = canBackSpawn = true;
}
// Update is called once per frame
void Update(){
currentTime += Time.deltaTime;
if(currentTime >= timeToExplode && !exploded){
StartCoroutine(Explode());
ScreenShakeCall.instance.ShakeCamera(10f, .4f);
exploded = true;
}
}
IEnumerator Explode(){
for (int i = 0; i < maxDistance; i++){
yield return new WaitForSeconds(timeBetweenExplosions);
if (i == 0){
ObjectPooler.instance.SpawnFromPool("Explosion", transform.position, Quaternion.identity);
}else{
if(!Physics.CheckSphere(transform.position + Vector3.right * i, .3f, whatIsWall) && canRightSpawn){
ObjectPooler.instance.SpawnFromPool("Explosion", transform.position + Vector3.right * i, Quaternion.identity);
}else{
canRightSpawn = false;
}
if (!Physics.CheckSphere(transform.position + Vector3.left * i, .3f, whatIsWall) && canLeftSpawn){
ObjectPooler.instance.SpawnFromPool("Explosion", transform.position + Vector3.left * i, Quaternion.identity);
}else{
canLeftSpawn = false;
}
if (!Physics.CheckSphere(transform.position + Vector3.forward * i, .3f, whatIsWall) && canForwardSpawn){
ObjectPooler.instance.SpawnFromPool("Explosion", transform.position + Vector3.forward * i, Quaternion.identity);
}else{
canForwardSpawn = false;
}
if (!Physics.CheckSphere(transform.position + Vector3.back * i, .3f, whatIsWall) && canBackSpawn){
ObjectPooler.instance.SpawnFromPool("Explosion", transform.position + Vector3.back * i, Quaternion.identity);
}else{
canBackSpawn = false;
}
}
AudioManager.instance.PlayWithRandomPitch("Explode");
}
gameObject.SetActive(false);
}
void OnDrawGizmos(){
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, transform.position + Vector3.right * maxDistance);
Gizmos.DrawLine(transform.position, transform.position + Vector3.left * maxDistance);
Gizmos.DrawLine(transform.position, transform.position + Vector3.forward * maxDistance);
Gizmos.DrawLine(transform.position, transform.position + Vector3.back * maxDistance);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2353ab88c05d124b9ccfd9cebf58df0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,38 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombSpawner : MonoBehaviour{
[SerializeField, Range(1, 10)] float spawnRate = 5f;
float currentTime;
[SerializeField] GameObject bomb = default;
SphereCollider col;
PlayerController player;
// Start is called before the first frame update
void Awake(){
col = GetComponent<SphereCollider>();
player = FindObjectOfType<PlayerController>();
}
// Update is called once per frame
void Update(){
currentTime -= Time.deltaTime;
if(currentTime <= 0){
col.enabled = true;
bomb.SetActive(true);
}
}
void OnTriggerEnter(Collider col){
if(col.CompareTag("Player")){
currentTime = spawnRate;
this.col.enabled = false;
bomb.SetActive(false);
player.numberOfBombs++;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27c73ea4a98056f4082879e332cd9b2f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoinController : MonoBehaviour{
GameController gameController;
[SerializeField] GameObject child = default;
void Awake(){
gameController = FindObjectOfType<GameController>();
}
void OnTriggerEnter(Collider col){
if (col.CompareTag("Player") || col.CompareTag("Explosion")){
GetComponent<SphereCollider>().enabled = false;
gameController.PlayButtonScale();
gameController.numberOfCoins--;
child.SetActive(true);
GameOverCanvas.instance.tilesEnabled++;
ObjectPooler.instance.SpawnFromPool("Light", new Vector3(transform.position.x, 0, transform.position.z), Quaternion.identity);
}
}
public void Disable(){
if(GetComponent<SphereCollider>().enabled == true){
child.SetActive(false);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee0cf260523b1bc438ab7b65ee096400
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,307 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour {
[SerializeField, Range(0, 2)] int angryLevel = 0;
[SerializeField] float[] speedLevels = new float[3];
[SerializeField] SkinnedMeshRenderer meshRenderer = default;
[SerializeField] Animator enemyAnimator = default;
[Space]
[SerializeField] Material defaultMat = default;
[SerializeField] Material angryMat = default;
[SerializeField] Material reallyAngryMat = default;
[SerializeField] Material defaultAttackMat = default;
[SerializeField] Material angryAttackMat = default;
[SerializeField] Material reallyAngryAttackMat = default;
[Space]
[SerializeField] float speed = 5f;
[HideInInspector] public Vector3 directionLooking = Vector3.forward;
[SerializeField, Range(0, .2f)] float rotationTime = .1f;
[HideInInspector] public float targetAngle;
float rotationVelocity;
[SerializeField] LayerMask whatIsWall = -1;
Vector3 currentPosition;
List<Vector3> possiblePositions;
List<Vector3> availablePositions;
[HideInInspector] public Vector3 positionToGo;
Transform player;
bool dead;
[HideInInspector] public bool canMove;
GameController gameController;
void Awake(){
PlayerController playerController = FindObjectOfType<PlayerController>();
player = playerController.transform;
playerController.onDie.AddListener(() => OnPlayerDie());
gameController = FindObjectOfType<GameController>();
}
void Start(){
positionToGo = currentPosition = transform.position;
speed = speedLevels[angryLevel];
}
public void OnPlayerDie(){
positionToGo = currentPosition = transform.position;
switch (angryLevel){
case 0:
meshRenderer.material = defaultMat;
break;
case 1:
meshRenderer.material = angryMat;
break;
case 2:
meshRenderer.material = reallyAngryMat;
break;
}
}
public void EnterRespawn(){
switch (angryLevel){
case 0:
angryLevel = 1;
break;
case 1:
angryLevel = 2;
break;
}
switch (angryLevel){
case 0:
meshRenderer.material = defaultMat;
break;
case 1:
meshRenderer.material = angryMat;
break;
case 2:
meshRenderer.material = reallyAngryMat;
break;
}
}
public void Respawn(){
positionToGo = currentPosition = transform.position;
dead = false;
speed = speedLevels[angryLevel];
}
// Update is called once per frame
void Update(){
enemyAnimator.SetBool("Attacking", !dead && canMove);
if (!dead && canMove){
switch (angryLevel){
case 0:
meshRenderer.material = defaultAttackMat;
break;
case 1:
meshRenderer.material = angryAttackMat;
break;
case 2:
meshRenderer.material = reallyAngryAttackMat;
break;
}
if (transform.position == positionToGo){
CalculateDirection();
}
transform.position = Vector3.MoveTowards(transform.position, new Vector3(positionToGo.x, transform.position.y, positionToGo.z), speed * Time.deltaTime);
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref rotationVelocity, rotationTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
}
else{
}
}
void CalculateDirection(){
currentPosition = transform.position;
possiblePositions = new List<Vector3>();
Vector3 forward = Vector3.forward;
Vector3 back = Vector3.back;
Vector3 left = Vector3.left;
Vector3 right = Vector3.right;
if (forward == -directionLooking){
possiblePositions.Add(Vector3.back);
possiblePositions.Add(Vector3.left);
possiblePositions.Add(Vector3.right);
}else if (back == -directionLooking){
possiblePositions.Add(Vector3.forward);
possiblePositions.Add(Vector3.left);
possiblePositions.Add(Vector3.right);
}else if (left == -directionLooking){
possiblePositions.Add(Vector3.back);
possiblePositions.Add(Vector3.forward);
possiblePositions.Add(Vector3.right);
}else if (right == -directionLooking){
possiblePositions.Add(Vector3.back);
possiblePositions.Add(Vector3.left);
possiblePositions.Add(Vector3.forward);
}
availablePositions = new List<Vector3>();
foreach(Vector3 pos in possiblePositions){
if(directionLooking == Vector3.forward || directionLooking == Vector3.back){
if(pos == Vector3.right){
if(player.position.x > transform.position.x){
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}else{
if (!Physics.CheckSphere(transform.position + directionLooking, .3f, whatIsWall)){
availablePositions.Add(directionLooking);
}else{
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}
}
}else if(pos == Vector3.left){
if (player.position.x < transform.position.x){
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}else{
if (!Physics.CheckSphere(transform.position + directionLooking, .3f, whatIsWall)){
availablePositions.Add(directionLooking);
}else{
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}
}
}else{
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}
}else{
if (pos == Vector3.forward){
if (player.position.z > transform.position.z){
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}else{
if (!Physics.CheckSphere(transform.position + directionLooking, .3f, whatIsWall)){
availablePositions.Add(directionLooking);
}else{
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}
}
}else if (pos == Vector3.back){
if (player.position.z < transform.position.z){
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}else{
if (!Physics.CheckSphere(transform.position + directionLooking, .3f, whatIsWall)){
availablePositions.Add(directionLooking);
}else{
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}
}
}else{
if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}
}
}
/*if (!Physics.CheckSphere(transform.position + pos, .3f, whatIsWall)){
availablePositions.Add(pos);
}*/
}
float nearestDist = float.MaxValue;
Vector3 nearestPos = new Vector3();
foreach (Vector3 v in availablePositions){
if (v != Vector3.zero){
float dist = Vector3.Distance(currentPosition + v, player.position);
if (dist < nearestDist){
nearestDist = dist;
nearestPos = currentPosition + v;
}
}
}
if(nearestPos - currentPosition == Vector3.left){
targetAngle = Mathf.Atan2(-1, 0) * Mathf.Rad2Deg;
}else if (nearestPos - currentPosition == Vector3.right){
targetAngle = Mathf.Atan2(1, 0) * Mathf.Rad2Deg;
}else if (nearestPos - currentPosition == Vector3.forward){
targetAngle = Mathf.Atan2(0, 1) * Mathf.Rad2Deg;
}else if (nearestPos - currentPosition == Vector3.back){
targetAngle = Mathf.Atan2(0, -1) * Mathf.Rad2Deg;
}
directionLooking = nearestPos - currentPosition;
positionToGo = nearestPos;
}
void OnDrawGizmos(){
Vector3 forward = Vector3.forward;
Vector3 back = Vector3.back;
Vector3 left = Vector3.left;
Vector3 right = Vector3.right;
if(forward == -directionLooking){
Gizmos.color = Color.blue;
Gizmos.DrawSphere(transform.position + Vector3.forward, .15f);
Gizmos.color = Color.red;
Gizmos.DrawSphere(transform.position + Vector3.back, .15f);
Gizmos.DrawSphere(transform.position + Vector3.left, .15f);
Gizmos.DrawSphere(transform.position + Vector3.right, .15f);
}else if(back == -directionLooking){
Gizmos.color = Color.blue;
Gizmos.DrawSphere(transform.position + Vector3.back, .15f);
Gizmos.color = Color.red;
Gizmos.DrawSphere(transform.position + Vector3.forward, .15f);
Gizmos.DrawSphere(transform.position + Vector3.left, .15f);
Gizmos.DrawSphere(transform.position + Vector3.right, .15f);
}else if (left == -directionLooking){
Gizmos.color = Color.blue;
Gizmos.DrawSphere(transform.position + Vector3.left, .15f);
Gizmos.color = Color.red;
Gizmos.DrawSphere(transform.position + Vector3.back, .15f);
Gizmos.DrawSphere(transform.position + Vector3.forward, .15f);
Gizmos.DrawSphere(transform.position + Vector3.right, .15f);
}else if (right == -directionLooking){
Gizmos.color = Color.blue;
Gizmos.DrawSphere(transform.position + Vector3.right, .15f);
Gizmos.color = Color.red;
Gizmos.DrawSphere(transform.position + Vector3.back, .15f);
Gizmos.DrawSphere(transform.position + Vector3.left, .15f);
Gizmos.DrawSphere(transform.position + Vector3.forward, .15f);
}
}
void OnTriggerEnter(Collider col){
if(col.gameObject.tag == "Explosion"){
AudioManager.instance.PlayOneShot("EnemyDeath");
GameOverCanvas.instance.enemiesKilled++;
dead = true;
canMove = false;
gameController.EnemyDeath(this);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e47f88b86432ef549a65f364b3382025
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,33 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExplosionController : MonoBehaviour, IPooledObject{
float currentTime;
[SerializeField, Range(0, 3)] float timeToDisappear = 1f;
BoxCollider col;
void Start(){
col = GetComponent<BoxCollider>();
}
// Start is called before the first frame update
public void OnObjectSpawn(){
currentTime = 0;
if(col != null){
col.enabled = true;
}
}
// Update is called once per frame
void Update(){
currentTime += Time.deltaTime;
if(currentTime >= .05f){
col.enabled = false;
}
if (currentTime >= timeToDisappear){
gameObject.SetActive(false);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 631231dffee2743448ba2585062cd0b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,212 @@
using Cinemachine;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
[System.Serializable] public class StartGame : UnityEvent { }
public class GameController : MonoBehaviour{
[SerializeField] Vector3 playerStartPos = Vector3.zero;
[Space]
public int numberOfCoins;
[SerializeField] TextMeshProUGUI coinsText = default;
[Space]
[SerializeField] Vector3 spawnerExitPosition = Vector3.zero;
public List<Vector3> spawnerPositions;
List<EnemyController> deadEnemies;
[SerializeField, Range(0f, 15f)] float timeBetweenSpawns = 7.5f;
float currentTime;
int currentEnemy;
public List<EnemyController> enemies = new List<EnemyController>();
[HideInInspector] public StartGame onStart;
bool started;
[SerializeField] CinemachineVirtualCamera dollyTrackCamera = default;
[SerializeField, Range(.1f, 5f)] float timeToStart = 3f;
// Start is called before the first frame update
void Start(){
limboEnemies = new List<Vector3>();
deadEnemies = new List<EnemyController>();
currentTime = timeBetweenSpawns - 2;
AudioManager.instance.Stop("Menu");
AudioManager.instance.Play("Intro");
StartCoroutine(StartGame());
}
List<Vector3> limboEnemies;
public void EnemyDeath(EnemyController enemy){
enemy.gameObject.SetActive(false);
foreach(Vector3 spawnPos in spawnerPositions){
deadEnemies.Add(enemy);
enemy.transform.position = spawnPos + Vector3.up;
spawnerPositions.Remove(spawnPos);
StartCoroutine(RespawnEnemy(enemy));
break;
}
}
public void PlayerDeath(PlayerController player){
player.gameObject.SetActive(false);
player.transform.position = playerStartPos;
player.Respawn();
player.gameObject.SetActive(true);
for (int i = 0; i < spawnerPositions.Count; i++){
enemies[i].gameObject.SetActive(false);
enemies[i].transform.position = spawnerPositions[i] + Vector3.up;
enemies[i].OnPlayerDie();
enemies[i].gameObject.SetActive(true);
enemies[i].directionLooking = Vector3.forward;
enemies[i].canMove = false;
}
deadEnemies.Clear();
limboEnemies.Clear();
currentEnemy = 0;
currentTime = timeBetweenSpawns - 2;
}
IEnumerator RespawnEnemy(EnemyController enemy){
yield return new WaitForSeconds(.5f);
spawnerPositions.Add(enemy.transform.position + Vector3.down);
limboEnemies.Remove(enemy.transform.position + Vector3.down);
enemy.EnterRespawn();
enemy.gameObject.SetActive(true);
}
bool won;
// Update is called once per frame
void Update(){
dollyTrackCamera.GetCinemachineComponent<CinemachineTrackedDolly>().m_PathPosition += Time.deltaTime / timeToStart * 2;
if(dollyTrackCamera.GetCinemachineComponent<CinemachineTrackedDolly>().m_PathPosition >= 2){
dollyTrackCamera.enabled = false;
}
if (started){
currentTime += Time.deltaTime;
if(currentTime >= timeBetweenSpawns){
if(currentEnemy < enemies.Count){
enemies[currentEnemy].positionToGo = new Vector3(spawnerExitPosition.x, enemies[currentEnemy].positionToGo.y, spawnerExitPosition.z);
enemies[currentEnemy].targetAngle = -90f;
enemies[currentEnemy].directionLooking = Vector3.left;
enemies[currentEnemy].canMove = true;
currentEnemy++;
currentTime = 0;
}else if(deadEnemies.Count != 0){
EnemyController enemy = deadEnemies[0];
//EnemyController enemy = deadEnemies.Dequeue();
enemy.Respawn();
enemy.positionToGo = new Vector3(spawnerExitPosition.x, enemy.positionToGo.y, spawnerExitPosition.z);
enemy.targetAngle = -90f;
enemy.directionLooking = Vector3.left;
enemy.canMove = true;
deadEnemies.Remove(enemy);
currentTime = 0;
}
}else if(deadEnemies.Count == 0 && currentEnemy >= enemies.Count){
currentTime = 0;
}
}
coinsText.text = "x" + numberOfCoins;
if(numberOfCoins == 0 && !won){
GameOverCanvas.instance.Win();
won = true;
}
}
int currentScale;
public void PlayButtonScale(){
switch (currentScale){
case 0:
AudioManager.instance.PlayOneShot("Scale1");
currentScale++;
break;
case 1:
AudioManager.instance.PlayOneShot("Scale2");
currentScale++;
break;
case 2:
AudioManager.instance.PlayOneShot("Scale3");
currentScale++;
break;
case 3:
AudioManager.instance.PlayOneShot("Scale4");
currentScale++;
break;
case 4:
AudioManager.instance.PlayOneShot("Scale2");
currentScale++;
break;
case 5:
AudioManager.instance.PlayOneShot("Scale3");
currentScale++;
break;
case 6:
AudioManager.instance.PlayOneShot("Scale4");
currentScale++;
break;
case 7:
AudioManager.instance.PlayOneShot("Scale5");
currentScale++;
break;
case 8:
AudioManager.instance.PlayOneShot("Scale3");
currentScale++;
break;
case 9:
AudioManager.instance.PlayOneShot("Scale4");
currentScale++;
break;
case 10:
AudioManager.instance.PlayOneShot("Scale5");
currentScale++;
break;
case 11:
AudioManager.instance.PlayOneShot("Scale6");
currentScale++;
break;
case 12:
AudioManager.instance.PlayOneShot("Scale5");
currentScale++;
break;
case 13:
AudioManager.instance.PlayOneShot("Scale4");
currentScale++;
break;
case 14:
AudioManager.instance.PlayOneShot("Scale3");
currentScale++;
break;
case 15:
AudioManager.instance.PlayOneShot("Scale2");
currentScale = 0;
break;
}
}
IEnumerator StartGame(){
yield return new WaitForSeconds(timeToStart + 2.5f);
onStart.Invoke();
AudioManager.instance.Play("Main");
started = true;
}
void OnDrawGizmos(){
Gizmos.color = Color.green;
Gizmos.DrawSphere(spawnerExitPosition, .2f);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f1f41e7150dab964cb1d6d2ce50f7bb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

18
Assets/Scripts/Light.cs Normal file
View file

@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Light : MonoBehaviour {
[SerializeField, Range(0, 1)] float animationDuration = .5f;
// Start is called before the first frame update
void OnEnable(){
StartCoroutine(Disable());
}
IEnumerator Disable(){
yield return new WaitForSeconds(animationDuration);
gameObject.SetActive(false);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3959e7125f29b614997ab1ce062d543e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,190 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MapCellCalculator : MonoBehaviour{
[SerializeField] bool cutscene = false;
[SerializeField] Vector3[] enemySpawnerPositions = new Vector3[9];
[Space]
[SerializeField] Vector3 bottomLeftCorner = Vector3.zero;
[SerializeField] Vector2 size = Vector2.zero;
[SerializeField] LayerMask whatIsWall = -1;
[SerializeField] GameObject coin = default;
[SerializeField, Range(0, 1)] float coinHeight = 1;
List<Vector3> positions;
List<Vector3> availablePositions;
GameController gameController;
[Header("Powerups")]
[SerializeField, Range(1, 10f)] float timeToSpawn = 5f;
float currentTime;
[SerializeField] bool canSpawnEnergy = true;
[SerializeField] Vector2 energySpawnSize = Vector2.zero;
[SerializeField] Vector3 energySpawnBottomLeftCorner = Vector3.zero;
List<Vector3> energyPos;
List<Vector3> energyAvailablePos;
[Space]
[SerializeField] Vector3[] bombSpawnPositions = new Vector3[4];
[SerializeField] GameObject bombSpawner = default;
void Awake(){
gameController = FindObjectOfType<GameController>();
gameController.spawnerPositions = new List<Vector3>();
foreach(Vector3 v in enemySpawnerPositions){
gameController.spawnerPositions.Add(v);
}
positions = new List<Vector3>();
availablePositions = new List<Vector3>();
for (int i = 0; i < size.x; i++){
for (int j = 0; j < size.y; j++){
positions.Add(bottomLeftCorner + new Vector3(i, 0, j));
}
}
positions = positions.Distinct().ToList();
foreach (Vector3 v in positions){
if (!Physics.CheckSphere(v, .3f, whatIsWall)){
availablePositions.Add(v);
}
}
for (int i = 0; i < availablePositions.Count; i++){
Vector3 temp = availablePositions[i];
int randomIndex = Random.Range(i, availablePositions.Count);
availablePositions[i] = availablePositions[randomIndex];
availablePositions[randomIndex] = temp;
}
gameController.numberOfCoins = availablePositions.Count;
StartCoroutine(SpawnCoins());
foreach (Vector3 v in bombSpawnPositions){
Instantiate(bombSpawner, v, Quaternion.identity);
}
energyPos = new List<Vector3>();
energyAvailablePos = new List<Vector3>();
for (int i = 0; i < energySpawnSize.x; i++){
for (int j = 0; j < energySpawnSize.y; j++){
energyPos.Add(energySpawnBottomLeftCorner + new Vector3(i, 0, j));
}
}
energyPos = energyPos.Distinct().ToList();
foreach (Vector3 v in energyPos){
if (!Physics.CheckSphere(v, .3f, whatIsWall)){
energyAvailablePos.Add(v);
}
}
}
void Start(){
gameController.enemies = new List<EnemyController>();
foreach (Vector3 v in enemySpawnerPositions){
GameObject enemy = ObjectPooler.instance.SpawnFromPool("Enemy", v + Vector3.up, Quaternion.identity);
gameController.enemies.Add(enemy.GetComponent<EnemyController>());
}
}
public void CanSpawnEnergy(){
canSpawnEnergy = true;
}
void Update(){
if (canSpawnEnergy){
currentTime -= Time.deltaTime;
if(currentTime <= 0){
ObjectPooler.instance.SpawnFromPool("BulletPickup", energyAvailablePos[Random.Range(0, energyAvailablePos.Count)] + Vector3.up * coinHeight, Quaternion.identity);
currentTime = timeToSpawn;
canSpawnEnergy = false;
}
}
}
IEnumerator SpawnCoins(){
List<CoinController> coins = new List<CoinController>();
foreach (Vector3 v in availablePositions){
GameObject coinController = Instantiate(coin, v + Vector3.up * coinHeight, Quaternion.identity, transform);
coins.Add(coinController.GetComponent<CoinController>());
}
if (cutscene){
foreach (CoinController c in coins){
yield return new WaitForSeconds(10 / availablePositions.Count);
//Instantiate(coin, v + Vector3.up * coinHeight, Quaternion.identity, transform);
c.Disable();
}
}else{
foreach (CoinController c in coins){
c.Disable();
}
}
yield break;
}
void OnDrawGizmos(){
if (!Application.isPlaying){
Gizmos.color = Color.yellow;
positions = new List<Vector3>();
availablePositions = new List<Vector3>();
for (int i = 0; i < size.x; i++){
for (int j = 0; j < size.y; j++){
positions.Add(bottomLeftCorner + new Vector3(i, 0, j));
}
}
positions = positions.Distinct().ToList();
foreach (Vector3 v in positions){
if (!Physics.CheckSphere(v, .3f, whatIsWall)){
availablePositions.Add(v);
}
}
foreach (Vector3 v in availablePositions){
Gizmos.DrawSphere(v + Vector3.up * coinHeight, .15f);
}
energyPos = new List<Vector3>();
energyAvailablePos = new List<Vector3>();
for (int i = 0; i < energySpawnSize.x; i++){
for (int j = 0; j < energySpawnSize.y; j++){
energyPos.Add(energySpawnBottomLeftCorner + new Vector3(i, 0, j));
}
}
energyPos = energyPos.Distinct().ToList();
foreach (Vector3 v in energyPos){
if (!Physics.CheckSphere(v, .3f, whatIsWall)){
energyAvailablePos.Add(v);
}
}
Gizmos.color = Color.blue;
foreach(Vector3 v in energyAvailablePos){
Gizmos.DrawSphere(v + Vector3.up * coinHeight, .15f);
}
Gizmos.color = Color.red;
foreach(Vector3 v in bombSpawnPositions){
Gizmos.DrawSphere(v + Vector3.up * coinHeight, .25f);
}
Gizmos.color = Color.magenta;
foreach (Vector3 v in enemySpawnerPositions){
Gizmos.DrawSphere(v + Vector3.up * coinHeight, .15f);
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2d40d53b9c46ce4dae1595a2d53e69d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Scripts/Menu.meta Normal file
View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 877cf31755870984784d25ec0901e29f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,88 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class GameOverCanvas : MonoBehaviour{
public int enemiesKilled;
public int tilesEnabled;
public float timeSurvived;
int finalScore;
[Header("Win Canvas")]
[SerializeField] GameObject winCanvas = default;
[Space]
[SerializeField] GameObject maxScoreText = default;
[SerializeField] TextMeshProUGUI enemiesText = default;
[SerializeField] TextMeshProUGUI tilesText = default;
[SerializeField] TextMeshProUGUI scoreText = default;
[Header("Game Over Canvas")]
[SerializeField] GameObject gameOverCanvas = default;
[Space]
[SerializeField] GameObject gameOverMaxScoreText = default;
[SerializeField] TextMeshProUGUI gameOverEnemiesText = default;
[SerializeField] TextMeshProUGUI gameOverTilesText = default;
[SerializeField] TextMeshProUGUI gameOverScoreText = default;
public static GameOverCanvas instance;
// Start is called before the first frame update
void Awake(){
instance = this;
}
public void Win(){
PlayerPrefs.SetInt("Tutorial", 1);
AudioManager.instance.Stop("Main");
Time.timeScale = 0;
winCanvas.SetActive(true);
enemiesText.text = enemiesKilled.ToString();
tilesText.text = tilesEnabled.ToString();
if(enemiesKilled == 0){
finalScore = Mathf.RoundToInt(2 * 8 * (tilesEnabled / 4) * (timeSurvived / 60));
}else{
finalScore = Mathf.RoundToInt(enemiesKilled * 8 * (tilesEnabled / 4) * (timeSurvived / 60));
}
scoreText.text = finalScore.ToString();
if (PlayerPrefs.HasKey("MaxScore")){
if (PlayerPrefs.GetInt("MaxScore") >= finalScore){
maxScoreText.SetActive(false);
}else{
PlayerPrefs.SetInt("MaxScore", finalScore);
}
}else{
PlayerPrefs.SetInt("MaxScore", finalScore);
}
}
public void Lose(){
PlayerPrefs.SetInt("Tutorial", 1);
Time.timeScale = 0;
gameOverCanvas.SetActive(true);
gameOverEnemiesText.text = enemiesKilled.ToString();
gameOverTilesText.text = tilesEnabled.ToString();
if (enemiesKilled == 0){
finalScore = Mathf.RoundToInt(2 * 8 * (tilesEnabled / 4) * (timeSurvived / 60));
}else{
finalScore = Mathf.RoundToInt(enemiesKilled * 8 * (tilesEnabled / 4) * (timeSurvived / 60));
}
gameOverScoreText.text = finalScore.ToString();
if (PlayerPrefs.HasKey("MaxScore")){
if (PlayerPrefs.GetInt("MaxScore") >= finalScore){
gameOverMaxScoreText.SetActive(false);
}else{
PlayerPrefs.SetInt("MaxScore", finalScore);
}
}else{
PlayerPrefs.SetInt("MaxScore", finalScore);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 090f21fda4ea3c349a33fd2f5b5d5cf1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelLoader : MonoBehaviour{
Animator anim;
[SerializeField, Range(0f, 3f)] float fadeDuration = 1f;
public static LevelLoader instance;
void Awake(){
instance = this;
anim = GetComponent<Animator>();
}
public void LoadScene(int scene){
StartCoroutine(LoadLevel(scene));
}
IEnumerator LoadLevel(int scene){
anim.SetTrigger("Fade");
yield return new WaitForSecondsRealtime(fadeDuration);
SceneManager.LoadSceneAsync(scene);
Time.timeScale = 1;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fa9abfe5e6b6491418ec5cf5874c8960
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,80 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
using TMPro;
public class SettingsMenu : MonoBehaviour{
[SerializeField] GameObject startButton;
[SerializeField] GameObject[] mainMenu;
[Space]
[SerializeField] TMP_Dropdown resolutionDropdown = default;
Resolution[] resolutions;
int currentResolutionIndex;
void Awake(){
foreach(GameObject o in mainMenu){
o.SetActive(false);
}
if(resolutionDropdown != null){
resolutions = Screen.resolutions.Select(resolution => new Resolution { width = resolution.width, height = resolution.height }).Distinct().ToArray();
resolutionDropdown.ClearOptions();
List<string> options = new List<string>();
for (int i = 0; i < resolutions.Length; i++){
string option = resolutions[i].width + "x" + resolutions[i].height;
options.Add(option);
if (resolutions[i].width == Screen.currentResolution.width && resolutions[i].height == Screen.currentResolution.height){
currentResolutionIndex = i;
}
}
resolutions.Reverse();
resolutionDropdown.AddOptions(options);
resolutionDropdown.value = currentResolutionIndex;
resolutionDropdown.RefreshShownValue();
}
}
bool started;
void Update(){
if (Input.anyKeyDown && !started){
AudioManager.instance.PlayOneShot("Start");
AudioManager.instance.Play("Menu");
startButton.SetActive(false);
foreach(GameObject o in mainMenu){
o.SetActive(true);
}
started = true;
}
}
public void SetQuality(int qualityIndex){
QualitySettings.SetQualityLevel(qualityIndex);
}
public void SetResolution(int resolutionIndex){
Resolution resolution = resolutions[resolutionIndex];
Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen);
}
public void Play(){
if (PlayerPrefs.HasKey("Tutorial")){
LevelLoader.instance.LoadScene(2);
}else{
LevelLoader.instance.LoadScene(1);
}
AudioManager.instance.PlayOneShot("Play");
}
public void Quit(){
Application.Quit();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49bb5047f0f5ba845a7bc043bafa8fab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c78a38d7b34c0b845ab0d7eb05008991
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
public interface IPooledObject{
void OnObjectSpawn();
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f2e800d3634e96c43aadb2187d5b1eea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPooler : MonoBehaviour{
[System.Serializable] public class Pool{
public string tag;
public GameObject prefab;
public int size;
}
public List<Pool> pools;
public Dictionary<string, Queue<GameObject>> poolDictionary;
public static ObjectPooler instance;
void Awake(){
instance = this;
poolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (Pool pool in pools){
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++){
GameObject obj = Instantiate(pool.prefab);
obj.SetActive(false);
obj.transform.parent = transform;
objectPool.Enqueue(obj);
}
poolDictionary.Add(pool.tag, objectPool);
}
}
// Start is called before the first frame update
void Start(){
}
public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation){
if (!poolDictionary.ContainsKey(tag)){
Debug.LogWarning("Pool with tag " + tag + " doesn't exist.");
return null;
}
GameObject objectToSpawn = poolDictionary[tag].Dequeue();
objectToSpawn.SetActive(true);
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if(pooledObj != null){
pooledObj.OnObjectSpawn();
}
poolDictionary[tag].Enqueue(objectToSpawn);
return objectToSpawn;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3aa18ca9ca01041479594f2fa8dfa166
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,217 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
[System.Serializable] public class OnDie : UnityEvent { }
public class PlayerController : MonoBehaviour{
[HideInInspector] public OnDie onDie;
[SerializeField] int numberOfLifes = 3;
[SerializeField] TextMeshProUGUI lifesText = default;
public int numberOfBombs = 0;
[SerializeField] TextMeshProUGUI bombsText = default;
public int numberOfCharge = 1;
[SerializeField] TextMeshProUGUI chargeText = default;
[Space]
[SerializeField] float speed = 5;
[SerializeField] LayerMask whatIsWall = -1;
Vector3 targetPosition;
[SerializeField, Range(0, .2f)] float rotationTime = .1f;
float targetAngle;
float rotationVelocity;
[Space]
[SerializeField] LayerMask whereCannotSpawnBombs = -1;
[Space]
[SerializeField] Transform verticalPortals = default;
[SerializeField] Transform horizontalPortals = default;
Vector2 lookDirection;
Vector2 lastPressed;
[HideInInspector] public bool canShoot = true;
bool teleporting;
bool canMove;
[SerializeField] GameObject explosion = default;
Animator anim;
bool dead;
void Awake(){
anim = GetComponent<Animator>();
FindObjectOfType<GameController>().onStart.AddListener(() => GameStart());
}
// Start is called before the first frame update
void Start(){
lookDirection = Vector2.up;
targetPosition = transform.position;
verticalPortals.gameObject.SetActive(false);
horizontalPortals.gameObject.SetActive(false);
}
public void Respawn(){
anim.SetBool("Dead", false);
dead = false;
lookDirection = Vector2.up;
targetPosition = transform.position;
verticalPortals.gameObject.SetActive(false);
horizontalPortals.gameObject.SetActive(false);
}
float timeSurvived;
bool alreadyDead;
// Update is called once per frame
void Update(){
if (!dead){
timeSurvived += Time.deltaTime;
}else{
GameOverCanvas.instance.timeSurvived = timeSurvived;
}
if (!teleporting && canMove && !dead){
transform.position = Vector3.MoveTowards(transform.position, new Vector3(targetPosition.x, transform.position.y, targetPosition.z), speed * Time.deltaTime);
if(targetPosition == new Vector3(transform.position.x, targetPosition.y, transform.position.z)){
if (!CheckCollision(new Vector3(lookDirection.x, 0, lookDirection.y))){
if(!CheckCollision(new Vector3(lastPressed.x, 0, lastPressed.y)) && lastPressed != Vector2.zero){
lookDirection = lastPressed;
targetPosition += new Vector3(lookDirection.x, 0, lookDirection.y);
targetAngle = Mathf.Atan2(1 * lookDirection.x, 1 * lookDirection.y) * Mathf.Rad2Deg;
lastPressed = Vector2.zero;
}else{
targetPosition += new Vector3(lookDirection.x, 0, lookDirection.y);
}
}else if(!CheckCollision(new Vector3(lastPressed.x, 0, lastPressed.y)) && lastPressed != Vector2.zero){
lookDirection = lastPressed;
targetPosition += new Vector3(lookDirection.x, 0, lookDirection.y);
targetAngle = Mathf.Atan2(1 * lookDirection.x, 1 * lookDirection.y) * Mathf.Rad2Deg;
lastPressed = Vector2.zero;
}else{
lastPressed = Vector2.zero;
}
}
}
Vector2 axisDirection = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
if(axisDirection.magnitude > .1f && !teleporting && canMove && !dead){
if(axisDirection.x != 0 && axisDirection.x == -lookDirection.x || axisDirection.x != 0 && (lookDirection == Vector2.up || lookDirection == Vector2.down)){
lastPressed = Vector2.right * axisDirection.x;
}
if (axisDirection.y != 0 && axisDirection.y == -lookDirection.y || axisDirection.y != 0 && (lookDirection == Vector2.right || lookDirection == Vector2.left)){
lastPressed = Vector2.up * axisDirection.y;
}
}
if (Input.GetMouseButtonDown(1) && canShoot && canMove && numberOfCharge > 0 && !dead && !alreadyDead){
horizontalPortals.gameObject.SetActive(false);
verticalPortals.gameObject.SetActive(false);
AudioManager.instance.PlayOneShot("Bullet");
if (lookDirection == Vector2.right){
GameObject bullet = ObjectPooler.instance.SpawnFromPool("Bullet", transform.position + Vector3.right, Quaternion.Euler(55, 0, 0));
bullet.GetComponent<PortalBullet>().SetImportantThings(verticalPortals, horizontalPortals, Vector3.right, targetPosition, this);
}else if (lookDirection == Vector2.left){
GameObject bullet = ObjectPooler.instance.SpawnFromPool("Bullet", transform.position + Vector3.left, Quaternion.Euler(55, 0, 0));
bullet.GetComponent<PortalBullet>().SetImportantThings(verticalPortals, horizontalPortals, Vector3.left, targetPosition, this);
}else if (lookDirection == Vector2.up){
GameObject bullet = ObjectPooler.instance.SpawnFromPool("Bullet", transform.position + Vector3.forward, Quaternion.Euler(55, 0, 0));
bullet.GetComponent<PortalBullet>().SetImportantThings(verticalPortals, horizontalPortals, Vector3.forward, targetPosition, this);
}else if (lookDirection == Vector2.down){
GameObject bullet = ObjectPooler.instance.SpawnFromPool("Bullet", transform.position + Vector3.back, Quaternion.Euler(55, 0, 0));
bullet.GetComponent<PortalBullet>().SetImportantThings(verticalPortals, horizontalPortals, Vector3.back, targetPosition, this);
}else{
GameObject bullet = ObjectPooler.instance.SpawnFromPool("Bullet", transform.position + Vector3.forward, Quaternion.Euler(55, 0, 0));
bullet.GetComponent<PortalBullet>().SetImportantThings(verticalPortals, horizontalPortals, Vector3.forward, targetPosition, this);
}
horizontalPortals.position = new Vector3(horizontalPortals.position.x, horizontalPortals.position.y, targetPosition.z);
verticalPortals.position = new Vector3(targetPosition.x, verticalPortals.position.y, verticalPortals.position.z);
canShoot = false;
numberOfCharge--;
}
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref rotationVelocity, rotationTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
if (Input.GetMouseButtonDown(0) && canMove && numberOfBombs > 0 && !dead && !alreadyDead){
if (!Physics.CheckSphere(new Vector3(targetPosition.x, transform.position.y - .5f, targetPosition.z), .3f, whereCannotSpawnBombs)){
ObjectPooler.instance.SpawnFromPool("Bomb", new Vector3(targetPosition.x, transform.position.y - .5f, targetPosition.z), Quaternion.identity);
AudioManager.instance.PlayOneShot("DropBomb");
numberOfBombs--;
}
}
chargeText.text = "x" + numberOfCharge;
bombsText.text = "x" + numberOfBombs;
lifesText.text = "x" + numberOfLifes;
}
public void Teleport(Vector3 position){
teleporting = true;
targetPosition = new Vector3(position.x, transform.position.y, position.z);
StartCoroutine(StopTeleporting());
AudioManager.instance.PlayOneShot("PortalEnter");
}
void GameStart(){
canMove = true;
}
IEnumerator Damage(){
dead = true;
ScreenShakeCall.instance.ShakeCamera(10f, .8f);
Instantiate(explosion, transform.position, Quaternion.identity);
anim.SetBool("Dead", true);
AudioManager.instance.PlayWithRandomPitch("Explode");
yield return new WaitForSeconds(1f);
if(numberOfLifes == 1){
AudioManager.instance.Stop("Main");
onDie.Invoke();
GameOverCanvas.instance.Lose();
alreadyDead = true;
numberOfLifes--;
}else if (numberOfLifes > 1){
numberOfLifes--;
}
FindObjectOfType<GameController>().PlayerDeath(this);
AudioManager.instance.Play("Death");
}
void OnTriggerEnter(Collider col){
if (col.CompareTag("Explosion")){
if (dead)
return;
StartCoroutine(Damage());
}
}
void OnCollisionEnter(Collision col){
if (col.gameObject.tag == "Enemy"){
if (dead)
return;
StartCoroutine(Damage());
}
}
IEnumerator StopTeleporting(){
yield return new WaitForSeconds(.1f);
transform.position = targetPosition;
yield return new WaitForSeconds(.1f);
teleporting = false;
}
bool CheckCollision(Vector3 dir){
return Physics.Raycast(transform.position, dir, 1, whatIsWall);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8fb3544b315535a44bcee63acb7583bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,60 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PortalBullet : MonoBehaviour{
[SerializeField] float speed = 10f;
[SerializeField, Range(1, 10)] float maxDistanceTravel = 5;
Transform verticalPortals;
Transform horizontalPortals;
Vector3 direction;
Vector3 playerPosition;
PlayerController player;
// Start is called before the first frame update
void Start(){
}
// Update is called once per frame
void Update(){
float targetAngle = Mathf.Atan2(1 * direction.x, 1 * direction.z) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, targetAngle, 0f);
transform.position = Vector3.MoveTowards(transform.position, new Vector3(playerPosition.x, transform.position.y, playerPosition.z) + direction * maxDistanceTravel, speed * Time.deltaTime);
if (transform.position == new Vector3(playerPosition.x, transform.position.y, playerPosition.z) + direction * maxDistanceTravel){
player.canShoot = true;
gameObject.SetActive(false);
}
}
void OnCollisionEnter(Collision col){
if(col.gameObject.tag == "LateralWalls"){
if(direction == Vector3.right || direction == Vector3.left){
horizontalPortals.gameObject.SetActive(true);
player.canShoot = true;
gameObject.SetActive(false);
}else if(direction == Vector3.forward || direction == Vector3.back){
verticalPortals.gameObject.SetActive(true);
player.canShoot = true;
gameObject.SetActive(false);
}
AudioManager.instance.PlayOneShot("PortalPlace");
}
else{
player.canShoot = true;
gameObject.SetActive(false);
}
}
public void SetImportantThings(Transform vPortals, Transform hPortals, Vector3 dir, Vector3 playerPos, PlayerController player){
verticalPortals = vPortals;
horizontalPortals = hPortals;
direction = dir;
playerPosition = playerPos;
this.player = player;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c67bbdab8e8d40d4e81575dc69d6644c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,24 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PortalBulletSpawner : MonoBehaviour{
PlayerController player;
MapCellCalculator map;
void Awake(){
player = FindObjectOfType<PlayerController>();
map = FindObjectOfType<MapCellCalculator>();
}
void OnTriggerEnter(Collider col){
if (col.CompareTag("Player")){
AudioManager.instance.PlayOneShot("Powerup");
player.numberOfCharge++;
map.CanSpawnEnergy();
gameObject.SetActive(false);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b122e433652ff964aa7795145464c372
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,68 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PortalController : MonoBehaviour{
[System.Serializable] public enum Direction{Left, Right, Up, Down}
[SerializeField] Direction direction = default;
[SerializeField] Transform exitPos = default;
bool teleporting;
PlayerController player;
Animator anim;
void Awake(){
anim = GetComponentInParent<Animator>();
player = FindObjectOfType<PlayerController>();
}
void OnEnable(){
anim.SetBool("Close", false);
teleporting = false;
}
void OnTriggerStay(Collider col){
if (col.CompareTag("Player")){
switch (direction){
case Direction.Left:
if (Input.GetAxisRaw("Horizontal") < 0 && !teleporting){
player.Teleport(exitPos.position);
StartCoroutine(ClosePortal());
teleporting = true;
}
break;
case Direction.Right:
if (Input.GetAxisRaw("Horizontal") > 0 && !teleporting){
player.Teleport(exitPos.position);
StartCoroutine(ClosePortal());
teleporting = true;
}
break;
case Direction.Up:
if (Input.GetAxisRaw("Vertical") > 0 && !teleporting){
player.Teleport(exitPos.position);
StartCoroutine(ClosePortal());
teleporting = true;
}
break;
case Direction.Down:
if (Input.GetAxisRaw("Vertical") < 0 && !teleporting){
player.Teleport(exitPos.position);
StartCoroutine(ClosePortal());
teleporting = true;
}
break;
}
}
}
IEnumerator ClosePortal(){
yield return new WaitForSeconds(.25f);
anim.SetBool("Close", true);
yield return new WaitForSeconds(.5f);
transform.parent.gameObject.SetActive(false);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 790d0b02696621b48aedc6f0c1cfd327
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,33 @@
using Cinemachine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScreenShakeCall : MonoBehaviour{
CinemachineVirtualCamera vCam;
float shakeTimer;
float shakeTimerTotal;
float startingIntensity;
public static ScreenShakeCall instance { get; private set; }
void Awake(){
instance = this;
vCam = GetComponent<CinemachineVirtualCamera>();
}
public void ShakeCamera(float intensity, float time){
CinemachineBasicMultiChannelPerlin multiChannelPerlin = vCam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
startingIntensity = intensity;
shakeTimer = shakeTimerTotal = time;
}
void Update(){
if(shakeTimer > 0){
shakeTimer -= Time.deltaTime;
CinemachineBasicMultiChannelPerlin multiChannelPerlin = vCam.GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
multiChannelPerlin.m_AmplitudeGain = Mathf.Lerp(startingIntensity, 0f, 1 - (shakeTimer / shakeTimerTotal));
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d74226738a791e43a762541fb0b2e71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: