diff --git a/C#/FX_Destroy.cs b/C#/FX_Destroy.cs new file mode 100644 index 0000000..6c1876a --- /dev/null +++ b/C#/FX_Destroy.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class FX_Destroy : MonoBehaviour +{ + + public float m_timer = 1.0f; + + // Start is called before the first frame update + void Start() + { + + Destroy(this.gameObject, m_timer);//Automatic destruction after 1s + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/C#/GameManager.cs b/C#/GameManager.cs new file mode 100644 index 0000000..9a35a6a --- /dev/null +++ b/C#/GameManager.cs @@ -0,0 +1,135 @@ +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.SceneManagement; + +[AddComponentMenu("Game/GameManager")] +public class GameManager : MonoBehaviour +{ + + public static GameManager Instance = null; + public static int _ammo = 1;//Type of bullets + //Number of pistol bullets + public static int n_ammo = 30; + //Number of machine gun bullets + public static int m_ammo = 100; + + public Text txt_ammo01; //Pistol ammunition text + public Text txt_ammo02; //Machine gun ammunition text + + public GameObject ShezhiPanel; //Settings panel + + public Button GameAgainPlayButton; //Game restart button + public Button GameRePlayButton; //Game continue button + public Button GameQuitButton; //Game quit button + public static bool MoveController = false;//Pause or not + + + Player m_player; + + public int Level_num = 3; + + // Use this for initialization + void Start() + { + MoveController = false; + Instance = this; + GameAgainPlayButton.onClick.AddListener(GameAgainPlayButtonListener); //Add game restart button listener + GameRePlayButton.onClick.AddListener(GameRePlayButtonClickListener); //Add game continue button listener + GameQuitButton.onClick.AddListener(GameQuitButtonClickListener); //Add game quit button listener + + //Get the player + m_player = GameObject.FindGameObjectWithTag("Player").GetComponent(); + } + + void Update() + { + if (Input.GetKeyDown(KeyCode.O)) + { + StopButtonClickListener(); + } + } + + // Update ammunition + public void SetAmmo(int ammo) + { + if (_ammo == 1) + { + m_ammo -= ammo; + txt_ammo02.text = m_ammo.ToString() ; + } + else + { + n_ammo -= ammo; + txt_ammo01.text = n_ammo.ToString() ; + } + } + + //Reload ammunition + public void AddAmmo() + { + if (_ammo == 1) + { + m_ammo = 100; + txt_ammo02.text = m_ammo.ToString() ; + } + else + { + n_ammo = 30; + txt_ammo01.text = n_ammo.ToString() ; + } + } + + //Switch gun + public void ReAmmo() + { + if (_ammo == 1) + { + txt_ammo02.text = m_ammo.ToString() ; + } + else + { + txt_ammo01.text = n_ammo.ToString() ; + } + } + + void StopButtonClickListener() + { + GameManager.MoveController = true;//Pause movement + + //Unlock mouse cursor + Cursor.lockState = CursorLockMode.None; + Cursor.visible = true; + + ShezhiPanel.SetActive(true);//Show pause panel + Time.timeScale = 0;//Game pause + } + + void GameAgainPlayButtonListener() + { + n_ammo = 30;//Number of pistol bullets + m_ammo = 100;//Number of machine gun bullets + + SceneManager.LoadScene(Level_num);//Restart + Time.timeScale = 1;//resume the game + } + + void GameRePlayButtonClickListener() + { + n_ammo = 30; + m_ammo = 100; + + GameManager.MoveController = false; + Cursor.lockState = CursorLockMode.Locked;//Lock mouse cursor + + ShezhiPanel.SetActive(false);//Close pause panel + + Time.timeScale = 1; + } + + void GameQuitButtonClickListener() + { + SceneManager.LoadScene(2); + Time.timeScale = 1; + } + +} \ No newline at end of file diff --git a/C#/Level01/Enemy01.cs b/C#/Level01/Enemy01.cs new file mode 100644 index 0000000..032e188 --- /dev/null +++ b/C#/Level01/Enemy01.cs @@ -0,0 +1,253 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AI; +using UnityEngine.UI; + +public class Enemy01 : MonoBehaviour +{ + + Transform m_transform; + Player m_player; + //Player + private Transform player; + + //Navigation components + UnityEngine.AI.NavMeshAgent m_agent; + + //Moving speed + public float m_movSpeed = 3.5f; + + //Animation components + Animator m_ani; + + //Spinning speed + public float m_rotSpeed = 5.0f; + + //Timer + float m_timer = 0; + + int m_life = 60;//HP + public Slider HP_Enemy; //Quote the UI of the enemy's hp + public GameObject Slider_HP_Enemy;//Game object hp + + //Character explosion effect + public GameObject BombPre; + //Bullet explosion effect + public GameObject BulletPre; + + public int dis_gj = 15;//Attack distance + + //Redefine the point coordinates of the maximum value of the upper and lower front and rear, + //which are used to control the movement of the character when it is not in the range + public float Max_dis = 4;//The maximum value of up, down, left, and right + public Vector3 Vec_U;//The position of the top coordinate point + public Vector3 Vec_D;//The bottom coordinate point position + public Vector3 Vec_R;//Foremost coordinate point position + public Vector3 Vec_L;//The last coordinate point position + public Vector3 Vec_Next;//The point position to move forward randomly next time + + public float speed = 2;//Moving speed + + void Start() + { + m_transform = this.transform; + + //Get the animation player + m_ani = this.GetComponent(); + //Get the protagonist + m_player = GameObject.FindGameObjectWithTag("Player").GetComponent(); + m_agent = GetComponent(); + m_agent.speed = m_movSpeed; + player = GameObject.FindWithTag("Player").transform; + + + //Assign values to the point coordinates of the maximum values above, below, left and right + Vec_U = m_transform.position; + Vec_D = m_transform.position; + Vec_R = m_transform.position; + Vec_L = m_transform.position; + + Vec_U.x = m_transform.position.x + Max_dis; + Vec_D.x = m_transform.position.x - Max_dis; + Vec_R.z = m_transform.position.z + Max_dis; + Vec_L.z = m_transform.position.z - Max_dis; + + Vec_Next = this.transform.position;//Set the point position of the next random advance as the initial position + + transform.LookAt(Vec_Next); + } + + // Update is called once per frame + void Update() + { + //If the player's hp is 0, do nothing + if (m_player.life <= 0) + return; + + if (Vector3.Distance(m_transform.position, m_player.transform.position) >= dis_gj) + { + Enemy_AI_(); + return; + }else + { + m_ani.SetBool("run", false); + } + + //Update Timer + m_timer -= Time.deltaTime; + + //Get the current animator state + AnimatorStateInfo stateInfo = m_ani.GetCurrentAnimatorStateInfo(0); + + // If idle but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.idle02") && !m_ani.IsInTransition(0)) + { + m_ani.SetBool("idle", false); + + //Idle a certain time + if (m_timer > 0) + return; + + //If the distance to the protagonist is less than a certain distance, enter the attack animation state + if (Vector3.Distance(m_transform.position, m_player.transform.position) < dis_gj) + { + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 4f) + { + //Stop pathfinding + m_agent.ResetPath(); + m_ani.SetBool("attack", true); + } + else + { + //Reset timer + m_timer = 1; + //Enter the running animation state + m_ani.SetBool("run", true); + m_agent.SetDestination(GameObject.Find("Player").transform.position); + } + } + } + + //If running but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.run") && !m_ani.IsInTransition(0)) + { + m_ani.SetBool("run", false); + + //Relocate the protagonist's position every 0.2s + if (m_timer < 0) + { + m_agent.SetDestination(GameObject.Find("Player").transform.position); + m_timer = 0.2f; + } + } + + //If the distance to the protagonist is less than 4m, enter the attack animation state + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 4f) + { + //Stop pathfinding + m_agent.ResetPath(); + //Attack animation status + m_ani.SetBool("attack", true); + } + + //If attack but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.attack01") && !m_ani.IsInTransition(0)) + { + //Facing the protagonist + RotateTo(); + m_ani.SetBool("attack", false); + + //If the animation is finished, enter the idle state again + if (stateInfo.normalizedTime >= 1.0f) + { + m_ani.SetBool("idle", true); + //Reset timer, idle 1s + m_timer = 1; + m_player.OnDamage(10);//Add damage to the protagonist + } + } + } + + void RotateTo() + { + //Get the direction of the target (player) + Vector3 targetdir = m_player.transform.position - m_transform.position; + //Calculate the new direction + Vector3 newDir = Vector3.RotateTowards(transform.forward, targetdir, m_rotSpeed * Time.deltaTime, 0.0f); + //Rotate to new direction + m_transform.rotation = Quaternion.LookRotation(newDir); + } + + void OnTriggerEnter(Collider other) + { + if (other.tag == "Bolt") + { + //Destroy bullets + Destroy(other.gameObject); + //Instantiate collision effects + Instantiate(BulletPre, transform.position, Quaternion.identity); + //Self-damage + OnDamage(30); + } + } + + public void OnDamage(int damage) + { + m_life -= damage; + HP_Enemy.value = m_life; + + //If the hp is 0, play the death animation + if (m_life == 0) + { + m_ani.SetBool("death", true); + Slider_HP_Enemy.SetActive(false);//Switch off the wellness display bar + //Stop pathfinding + m_agent.ResetPath(); + + //Instantiate collision effects + Instantiate(BombPre, transform.position, Quaternion.identity); + + //Destroy itself after 0.2s + Destroy(this.gameObject, 0.2f); + } + } + + //Self AI movement + void Enemy_AI_() + { + // Distance from the next starting position + float dis_r = Vector3.Distance(transform.position, Vec_Next); + if (dis_r >= 2) + { + //When the distance is greater than 2m, continue self-movement + transform.position = Vector3.MoveTowards(transform.position, Vec_Next, speed * Time.deltaTime); + } + else + { + //Otherwise, when the distance is less than 2m, reconfirm the position of the next random forward point + int n = Random.Range(0, 4);//Randamly select one number from 0,1,2,3 to represent the value of the coordinates + if (n == 0) + { + Vec_Next = Vec_U; + } + if (n == 1) + { + Vec_Next = Vec_D; + } + if (n == 2) + { + Vec_Next = Vec_R; + } + if (n == 3) + { + Vec_Next = Vec_L; + } + } + //Enter the running animation state + m_ani.SetBool("run", true); + transform.LookAt(Vec_Next); + } + + +} diff --git a/C#/Level02/Enemy.cs b/C#/Level02/Enemy.cs new file mode 100644 index 0000000..ec1b0ca --- /dev/null +++ b/C#/Level02/Enemy.cs @@ -0,0 +1,233 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AI; +using UnityEngine.UI; + +public class Enemy : MonoBehaviour +{ + + Transform m_transform; + Player m_player; + //Player + private Transform player; + + //Navigation components + UnityEngine.AI.NavMeshAgent m_agent; + + //Moving speed + float m_movSpeed = 3.5f; + + //Animation components + Animator m_ani; + + //Spinning speed + public float m_rotSpeed = 5.0f; + + //Timer + float m_timer = 0; + + int m_life = 80;//HP + public Slider HP_Enemy; //Quote the UI of the enemy's hp + public GameObject Slider_HP_Enemy;//Game object hp + + public int attack_JL = 20;//Attack distance + + //Redefine the point coordinates of the maximum value of the upper and lower front and rear, + //which are used to control the movement of the character when it is not in the range + public float Max_dis = 4;//The maximum value of up, down, left, and right + public Vector3 Vec_U;//The position of the top coordinate point + public Vector3 Vec_D;//The bottom coordinate point position + public Vector3 Vec_R;//Foremost coordinate point position + public Vector3 Vec_L;//The last coordinate point position + public Vector3 Vec_Next;//The point position to move forward randomly next time + + public float speed = 2;//Moving speed + + void Start() + { + m_transform = this.transform; + + //Get the animation player + m_ani = this.GetComponent(); + //Get the protagonist + m_player = GameObject.FindGameObjectWithTag("Player").GetComponent(); + m_agent = GetComponent(); + m_agent.speed = m_movSpeed; + player = GameObject.FindWithTag("Player").transform; + + //Assign values to the point coordinates of the maximum values above, below, left and right + Vec_U = m_transform.position; + Vec_D = m_transform.position; + Vec_R = m_transform.position; + Vec_L = m_transform.position; + + Vec_U.x = m_transform.position.x + Max_dis; + Vec_D.x = m_transform.position.x - Max_dis; + Vec_R.z = m_transform.position.z + Max_dis; + Vec_L.z = m_transform.position.z - Max_dis; + + Vec_Next = this.transform.position;//Set the point position of the next random advance as the initial position + + transform.LookAt(Vec_Next); + } + + // Update is called once per frame + void Update() + { + //If the player's hp is 0, do nothing + if (m_player.life <= 0) + return; + + if (Vector3.Distance(m_transform.position, m_player.transform.position) >= attack_JL) + { + Enemy_AI_(); + return; + } + else + { + m_ani.SetBool("run", false); + } + + //Update Timer + m_timer -= Time.deltaTime; + + //Get the current animator state + AnimatorStateInfo stateInfo = m_ani.GetCurrentAnimatorStateInfo(0); + + // If idle but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.idle02") && !m_ani.IsInTransition(0)) + { + m_ani.SetBool("idle", false); + + //Idle a certain time + if (m_timer > 0) + return; + + //When the distance from the protagonist is less than the set value, enter the attack animation state + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 20f) + { + + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 2.5f) + { + //Stop pathfinding + m_agent.ResetPath(); + m_ani.SetBool("attack", true); + } + else + { + //Reset timer + m_timer = 1; + //Enter the running animation state + m_ani.SetBool("run", true); + m_agent.SetDestination(GameObject.Find("Player").transform.position); + } + } + } + + // If running but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.run") && !m_ani.IsInTransition(0)) + { + m_ani.SetBool("run", false); + + //Relocate the protagonist's position every 1s + if (m_timer < 0) + { + m_agent.SetDestination(GameObject.Find("Player").transform.position); + m_timer = 1; + } + } + + //If the distance to the protagonist is less than 2.5m, enter the attack animation state + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 2.5f) + { + //Reset timer + m_agent.ResetPath(); + //Attack animation status + m_ani.SetBool("attack", true); + } + + //If attack but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.attack01") && !m_ani.IsInTransition(0)) + { + //Facing the protagonist + RotateTo(); + m_ani.SetBool("attack", false); + + //If the animation is ended, enter the idle state again + if (stateInfo.normalizedTime >= 1.0f) + { + m_ani.SetBool("idle", true); + //Reset timer, idle 1s + m_timer = 1; + m_player.OnDamage(10);//Add damage to the protagonist + } + } + } + + void RotateTo() + { + //Get the direction of the target (player) + Vector3 targetdir = m_player.transform.position - m_transform.position; + //Calculate the new direction + Vector3 newDir = Vector3.RotateTowards(transform.forward, targetdir, m_rotSpeed * Time.deltaTime, 0.0f); + //Rotate to new direction + m_transform.rotation = Quaternion.LookRotation(newDir); + } + + public void OnDamage(int damage) + { + m_life -= damage; + HP_Enemy.value = m_life; + + + //If the hp is 0, play the death animation + if (m_life == 0) + { + m_ani.SetBool("death", true); + Slider_HP_Enemy.SetActive(false);//Switch off the wellness display bar + //Stop pathfinding + m_agent.ResetPath(); + //Destroy itself after 0.5s + Destroy(this.gameObject,0.5f); + } + } + + //Close AI automated movement + void Enemy_AI_() + { + //Distance from the next starting position + float dis_r = Vector3.Distance(transform.position, Vec_Next); + if (dis_r >= 2) + { + //When the distance is greater than 2m, continue self-movement + transform.position = Vector3.MoveTowards(transform.position, Vec_Next, speed * Time.deltaTime); + } + else + { + //Otherwise, when the distance is less than 2m, reconfirm the position of the next random forward point + int n = Random.Range(0, 4);//Randamly select one number from 0,1,2,3 to represent the value of the coordinates + if (n == 0) + { + Vec_Next = Vec_U; + } + if (n == 1) + { + Vec_Next = Vec_D; + } + if (n == 2) + { + Vec_Next = Vec_R; + } + if (n == 3) + { + Vec_Next = Vec_L; + } + } + //Enter the running animation state + m_ani.SetBool("run", true); + transform.LookAt(Vec_Next); + } + + +} diff --git a/C#/Level03/BulletControl.cs b/C#/Level03/BulletControl.cs new file mode 100644 index 0000000..ddda266 --- /dev/null +++ b/C#/Level03/BulletControl.cs @@ -0,0 +1,44 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class BulletControl : MonoBehaviour { + + Player m_player; + //Collision effect + public GameObject EffectPre; + //Speed + public float Speed = 9; + //Attacking power + public int Attack = 0; + + public int AttackHurt = 5;//Bullet damage value + + void Start () { + //Get player + m_player = GameObject.FindGameObjectWithTag("Player").GetComponent(); + //Speed + GetComponent().velocity = transform.forward * Speed; + //Destroy itself + Destroy(gameObject, 3f); + } + + + private void OnCollisionEnter (Collision collision) + { + //If enemy got hit + + if (collision.collider.tag == "Player") + { + m_player.OnDamage(AttackHurt);//Add damage to the protagonist + } + + //if (collision.collider.tag != "enemy") + // { + //Instantiate collision effects + Instantiate(EffectPre, transform.position, Quaternion.identity); + Destroy(gameObject); + // } + + } +} diff --git a/C#/Level03/Door.cs b/C#/Level03/Door.cs new file mode 100644 index 0000000..31321c6 --- /dev/null +++ b/C#/Level03/Door.cs @@ -0,0 +1,37 @@ +using UnityEngine; +using System.Collections; + +public class Door : MonoBehaviour +{ + + + public AudioSource musicDoorOpen;//Door opening sound + private Animator anim;//Door opening animation + + void Start() + { + anim = this.GetComponent();//Get the current door animation + } + + void OnTriggerEnter(Collider other) + { + if (other.tag == "Player" ) + { + anim.SetBool("Close", false);//Open the door + GetComponent().Play();//Play sound + } + } + + void OnTriggerExit(Collider other) + { + if (other.tag == "Player" ) + { + anim.SetBool("Close", true);//Close the door + GetComponent().Play(); + } + } + +} + +//Reference from + diff --git a/C#/Level03/Door02.cs b/C#/Level03/Door02.cs new file mode 100644 index 0000000..d2cd261 --- /dev/null +++ b/C#/Level03/Door02.cs @@ -0,0 +1,69 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Door02 : MonoBehaviour +{ + + + public AudioSource musicDoorOpen;//Door opening sound + public GameObject Hingle; + public GameObject Hingle2; + + public bool Move = false; + public bool Move2 = false; + + void Update() + { + if(Move == true) + { + if (Hingle.transform.position.z > 11.5 ) + { + + Hingle.transform.position -= new Vector3(0,0,0.1f); + Hingle2.transform.position += new Vector3(0, 0, 0.1f); + } + else + { + Move = false; + } + } + + + if (Move2 == true) + { + if (Hingle.transform.position.z <= 12.5) + { + Hingle.transform.position += new Vector3(0, 0, 0.01f); + Hingle2.transform.position -= new Vector3(0, 0, 0.01f); + } + else + { + Move2 = false; + } + } + + } + + void OnTriggerEnter(Collider other) + { + if (other.tag == "Player") + { + Move = true; + Move2 = false; + GetComponent().Play();//Sound playing + } + } + + void OnTriggerExit(Collider other) + { + if (other.tag == "Player") + { + Move = false; + Move2 = true; + GetComponent().Play(); + } + } +} + +//reference from diff --git a/C#/Level03/Enemy03.cs b/C#/Level03/Enemy03.cs new file mode 100644 index 0000000..315609b --- /dev/null +++ b/C#/Level03/Enemy03.cs @@ -0,0 +1,286 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AI; +using UnityEngine.UI; + +public class Enemy03 : MonoBehaviour +{ + + Transform m_transform; + Player m_player; + //Player + private Transform player; + + //Navigation components + UnityEngine.AI.NavMeshAgent m_agent; + + //Moving speed + public float m_movSpeed = 4f; + + //Animation components + public Animator m_ani; + + //Spinning speed + public float m_rotSpeed = 5.0f; + + //Timer + float m_timer = 0; + + public int m_life = 100;//HP + public Slider HP_Enemy; //Quote the UI of the enemy's hp + public GameObject Slider_HP_Enemy;//Game object hp + + //Character explosion effect + public GameObject BombPre; + //Bullet explosion effect + public GameObject BulletPre; + + public int attack_JL =20;//Attack distance + + public Transform Enemygun1;//Launch point 1 + public Transform Enemygun2;//Launch point 2 + public GameObject enemyBullet;//Bullet prefab unity + public bool BulletAttack = false;//Shooting with bullet or not + public float BulletAttackTime = 10;//Bullet attack interval + + //Redefine the point coordinates of the maximum value of the upper and lower front and rear, + //which are used to control the movement of the character when it is not in the range + public float Max_dis = 4;//The maximum value of up, down, left, and right + public Vector3 Vec_U;//The position of the top coordinate point + public Vector3 Vec_D;//The bottom coordinate point position + public Vector3 Vec_R;//Foremost coordinate point position + public Vector3 Vec_L;//The last coordinate point position + public Vector3 Vec_Next;//The point position to move forward randomly next time + + public float speed = 2;//Moving speed + + void Start() + { + m_transform = this.transform; + + //Get the protagonist + m_player = GameObject.FindGameObjectWithTag("Player").GetComponent(); + m_agent = GetComponent(); + m_agent.speed = m_movSpeed; + player = GameObject.FindWithTag("Player").transform; + + BulletAttackTime = Random.Range(5, 12);//Random shooting interval + + + //Assign values to the point coordinates of the maximum values above, below, left and right + Vec_U = m_transform.position; + Vec_D = m_transform.position; + Vec_R = m_transform.position; + Vec_L = m_transform.position; + + Vec_U.x = m_transform.position.x + Max_dis; + Vec_D.x = m_transform.position.x - Max_dis; + Vec_R.z = m_transform.position.z + Max_dis; + Vec_L.z = m_transform.position.z - Max_dis; + + Vec_Next = this.transform.position;//Set the point position of the next random advance as the initial position + transform.LookAt(Vec_Next); + } + + // Update is called once per frame + void Update() + { + //If the player's hp is 0, do nothing + if (m_player.life <= 0) + return; + + + if (Vector3.Distance(m_transform.position, m_player.transform.position) >= attack_JL) + { + Enemy_AI_(); + return; + } + else + { + m_ani.SetBool("run", false); + } + + //Update Timer + m_timer -= Time.deltaTime; + + //Bullet attack + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 10f) + { + BulletAttack = true; + } + else + { + BulletAttack = false; + } + + if (BulletAttack == true) + { + BulletAttackTime -= Time.deltaTime; + + if (BulletAttackTime <= 0) + { + Instantiate(enemyBullet, Enemygun1.position, Enemygun1.rotation);//Instantiate bullet + Instantiate(enemyBullet, Enemygun2.position, Enemygun2.rotation); + + BulletAttackTime = Random.Range(5, 12);//Random shooting interval + } + } + + //Get the current animator state + AnimatorStateInfo stateInfo = m_ani.GetCurrentAnimatorStateInfo(0); + + //If idle but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.idle02") && !m_ani.IsInTransition(0)) + { + m_ani.SetBool("idle", false); + + //Idle a certain time + if (m_timer > 0) + return; + + //If the distance to the protagonist is less than the attack distance, enter the attack animation state + if (Vector3.Distance(m_transform.position, m_player.transform.position) < attack_JL) + { + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 1f) + { + //Stop pathfinding + m_agent.ResetPath(); + //Attack animation status + m_ani.SetBool("attack", true); + } + else + { + //Reset timer + m_timer = 2; + //Enter the running animation state + m_ani.SetBool("run", true); + m_agent.SetDestination(GameObject.Find("Player").transform.position); + } + } + } + + //If running but not in transition + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.run") && !m_ani.IsInTransition(0)) + { + m_ani.SetBool("run", false); + + //Relocate the protagonist's position every 2s + if (m_timer < 0) + { + m_agent.SetDestination(GameObject.Find("Player").transform.position); + m_timer = 2; + } + } + + //If the distance to the protagonist is less than 1m, enter the attack animation state + if (Vector3.Distance(m_transform.position, m_player.transform.position) < 1f) + { + //Stop pathfinding + m_agent.ResetPath(); + //Attack animation status + m_ani.SetBool("attack", true); + } + + //If attack but not in transition + + if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.attack01") && !m_ani.IsInTransition(0)) + { + //Facing the protagonist + RotateTo(); + m_ani.SetBool("attack", false); + + //If the animation is ended, enter the idle state again + if (stateInfo.normalizedTime >= 2.0f) + { + m_ani.SetBool("idle", true); + //Reset timer, idle 2s + m_timer = 2; + + m_player.OnDamage(10);//Add damage to the protagonist + } + } + } + + void RotateTo() + { + //Get the direction of the target (player) + Vector3 targetdir = m_player.transform.position - m_transform.position; + //Calculate the new direction + Vector3 newDir = Vector3.RotateTowards(transform.forward, targetdir, m_rotSpeed * Time.deltaTime, 0.0f); + //Rotate to new direction + m_transform.rotation = Quaternion.LookRotation(newDir); + } + + void OnTriggerEnter(Collider other) + { + if (other.tag == "Bolt") + { + //Destroy bullets + Destroy(other.gameObject); + //Instantiate collision effects + Instantiate(BulletPre, transform.position, Quaternion.identity); + //Self-damage + OnDamage(30); + } + } + + public void OnDamage(int damage) + { + m_life -= damage; + HP_Enemy.value = m_life; + + //If the hp is 0, play the death animation + if (m_life <= 0) + { + m_ani.SetBool("death", true); + Slider_HP_Enemy.SetActive(false);//Switch off the wellness display bar + + Instantiate(BombPre, transform.position, Quaternion.identity); + + //Stop pathfinding + m_agent.ResetPath(); + + //Destroy itself + Destroy(this.gameObject); + } + } + + //Close AI automated movement + void Enemy_AI_() + { + //Distance from the next starting position + float dis_r = Vector3.Distance(transform.position, Vec_Next); + if (dis_r >= 2) + { + //When the distance is greater than 2m, continue self-movement + transform.position = Vector3.MoveTowards(transform.position, Vec_Next, speed * Time.deltaTime); + } + else + { + //Otherwise, when the distance is less than 2m, reconfirm the position of the next random forward point + int n = Random.Range(0, 4);//Distance from the next starting position + + if (n == 0) + { + Vec_Next = Vec_U; + } + if (n == 1) + { + Vec_Next = Vec_D; + } + if (n == 2) + { + Vec_Next = Vec_R; + } + if (n == 3) + { + Vec_Next = Vec_L; + } + } + //Enter the running animation state + m_ani.SetBool("run", true); + transform.LookAt(Vec_Next); + } + +} diff --git a/C#/Player/Player.cs b/C#/Player/Player.cs new file mode 100644 index 0000000..096ffde --- /dev/null +++ b/C#/Player/Player.cs @@ -0,0 +1,368 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.SceneManagement; + +[AddComponentMenu("MyGame/Player")] //Put the script in【Component】→【MyGame】→【Player】,Convenient for self-management scripts +public class Player : MonoBehaviour //Inherit the MonoBehaviour class +{ + + public int life = 100;//Protagonist’s hp + public Slider HP_zj;//Quote the UI of the enemy's hp + public AudioSource Audio_hit;//Audio for being hit + + private new Transform transform; + private CharacterController controller; + private Transform cameraTransform;//Tranform component of the camera + private Vector3 cameraRotation;//Rotation angle of the camera + + private float speed = 3.0f; + private float gravity = 3.0f; + //Shooting + public LayerMask layer; //The collision layer that the ray can hit when shooting + public Transform fx; //Particle effect after hitting the target + public Transform muzzlePoint; //Tranform componet of the muzzle point + private float shootTimer = 0.1f; //Timer for shooting intervals + Ray shootRay; //Define the ray + RaycastHit shootHit; + LineRenderer gunLine; + int shootableMask;//Define the face that receives the light + + public AudioClip m_audio;//Audio of the shooting + + public float timeAvailable = 180.0f;//Default 180s countdown + public Text guiTimer;//Countdown timer text + public bool Time_Run = true;//Start the countdown timer or not (no by default) + + public static bool shot_is = false;//Start shooting component or not + public GameObject daoju01;//Hand display + public GameObject daoju02;//Weapon display + public GameObject daoju020;//Pistol display + public GameObject daoju021;//Machinegun display + public GameObject daoju03;//Weapon display + + public GameObject UI_hand;//Image of bare hands + public GameObject UI_amon01;//Image of a pistol + public GameObject UI_amon02;//Image of machine gun + + public int cameraRotation_y = -90; + public float AddSpeed = 1;//Added speed + + void Start() + { + /// + /// Intialize and acquire Transform and Character Controller module + /// + transform = GetComponent(); + controller = GetComponent(); + + // Camera Rotation + cameraRotation.y += cameraRotation_y; + + // Acquiring camera + cameraTransform = Camera.main.GetComponent(); + + // Lock the cursor + Cursor.lockState = CursorLockMode.Locked; + + } + + /// + /// Control protagonist’s action, no action if the hp is 0 + /// + void Update() + { + if (life <= 0 || GameManager.MoveController == true) + { + return; + } + Control(); + + //Renew the shooting time intervalRenew the shooting time interval + if(shot_is == true){ + shot(); + } + + //When countdown timer starts + if (Time_Run == true) + { + //When the countdown timer is more than 0 second, display the current time in seconds, + //otherwise, stop the timer + if (timeAvailable > 0) + { + timeAvailable -= Time.deltaTime; + guiTimer.text = string.Format("{0:0}", timeAvailable); + } + else + { + //Release the lock on the cursor + Cursor.lockState = CursorLockMode.None; + Cursor.visible = true; + + // Time_Run = false; //Stop the timer + // Time.timeScale = 0; //Pause the time + SceneManager.LoadScene(7); + } + } + + if (Input.GetKeyUp(KeyCode.Alpha1)) + { + CloseDaoju(); + daoju01.SetActive(true); + UI_hand.SetActive(true);// Display UI for the hands + } + + if (Input.GetKeyUp(KeyCode.Alpha2)) + { + ReAmmo01(); + } + + if (Input.GetKeyUp(KeyCode.Alpha3)) + { + ReAmmo02(); + } + + if (Input.GetKeyDown(KeyCode.LeftShift)) + { + AddSpeed = 2; + } + if (Input.GetKeyUp(KeyCode.LeftShift)) + { + AddSpeed = 1; + } + + + } + /// + /// Display the avatar for protagonist + /// + void OnDrawGizmos() + { + Gizmos.DrawIcon(GetComponent().position, "Spawn.tif"); + } + + /// + /// Control the gravity movement, forward, backward, and left and right movement + /// + private void Control() + { + //Acquire the distance in the cursor movement + float rh = Input.GetAxis("Mouse X"); + float rv = Input.GetAxis("Mouse Y"); + + //Rotate the camera + cameraRotation.x -= rv; + cameraRotation.y += rh; + cameraTransform.eulerAngles = cameraRotation; + + //Make the protagonist facing the same direction as the camera + Vector3 camrot = cameraTransform.eulerAngles; + camrot.x = 0; camrot.z = 0; + transform.eulerAngles = camrot; + + //Refresh the camera positioning to be in sync with the player + cameraTransform.position = transform.TransformPoint(0, 2, -0.4f); + + float x = 0, y = 0, z = 0; + //Gravity movement + // y -= gravity * Time.deltaTime; + //Backward and forward movement + if (Input.GetKey(KeyCode.W)) + { + z += speed * Time.deltaTime * AddSpeed; + } + else if (Input.GetKey(KeyCode.S)) + { + z -= speed * Time.deltaTime * AddSpeed; + } + + //Left and right movement + if (Input.GetKey(KeyCode.A)) + { + x -= speed * Time.deltaTime; + } + else if (Input.GetKey(KeyCode.D)) + { + x += speed * Time.deltaTime; + } + + //Jump + if (Input.GetKeyDown(KeyCode.Space)) + { + if (this.gameObject.transform.position.y < 7.47f) + { + y += gravity * 30 * Time.deltaTime; + } + } + if (this.gameObject.transform.position.y >= -100) + { + y -= gravity * 10 * Time.deltaTime; + } + //Use the character controller instead of the move method provided by transform + //Because the Charcter Controller can automatically detect the collion + controller.Move(transform.TransformDirection(new Vector3(x, y, z))); + } + + //Shooting component + void shot() + { + shootTimer -= Time.deltaTime; + + //Indentify pistol or machinegun + if (GameManager._ammo == 1) + { + if (GameManager.m_ammo <= 0) + { + return; + } + } + else + { + if (GameManager.n_ammo <= 0) + { + return; + } + } + + // Left click to shoot + if (Input.GetMouseButton(0) && shootTimer <= 0) + { + shootTimer = 0.1f; + + this.GetComponent().PlayOneShot(m_audio);//Play audio for shooting + + GameManager.Instance.SetAmmo(1); //UI Reduce ammunition ; Reload Ammunition + + //RaycastHit save the result for laser detection + RaycastHit info; + //Shoot a laser from muzzle point to the camera + //the layer can only collide with the m_layer + bool hit = Physics.Raycast(muzzlePoint.position, cameraTransform.TransformDirection(Vector3.forward), out info, 100, layer); + if (hit) + { + // If hit tagged enemy + //Level 1 + if (info.transform.tag.CompareTo("enemy01") == 0) + { + Enemy01 enemy = info.transform.GetComponent(); + //Reduce the hp on enemy + enemy.OnDamage(30); + } + + //Level 2 + if (info.transform.tag.CompareTo("enemy") == 0) + { + Enemy enemy = info.transform.GetComponent(); + enemy.OnDamage(40); + } + + //Level 3 + if (info.transform.tag.CompareTo("enemy03") == 0) + { + Enemy03 enemy = info.transform.GetComponent(); + enemy.OnDamage(50); + } + + if (info.transform.tag.CompareTo("enemy04") == 0) + { + Enemy04 enemy = info.transform.GetComponent(); + enemy.OnDamage(25); + } + + //Display visual effects of particles on where being hit + Instantiate(fx, info.point, info.transform.rotation); + } + } + } + + public void OnDamage(int damage) + { + life -= damage;//Reduce hp + HP_zj.value = life;//Display the hp of the protagonist + Audio_hit.Play();//Play the audio of being attacked + if (life <= 0) + { + //Release the cursor lock + Cursor.lockState = CursorLockMode.None; + Cursor.visible = true; + + SceneManager.LoadScene(7); + } + } + + public void AddHp() + { + //Add blood + if (life > 80) + { + life = 100; + } + else + { + life += 20; + } + HP_zj.value = life; + } + + void OnTriggerEnter(Collider other) + { + if (other.tag == "Lose") + { + Cursor.lockState = CursorLockMode.None; + Cursor.visible = true; + + SceneManager.LoadScene(7); + } + } + + //Switch out game objects + void CloseDaoju() + { + daoju01.SetActive(false); + daoju02.SetActive(false); + daoju020.SetActive(false); + daoju021.SetActive(false); + daoju03.SetActive(false); + + UI_hand.SetActive(false);//Hide pistol UI + UI_amon01.SetActive(false);//Hide handheld firearms + UI_amon02.SetActive(false);//Hide machinegun + + shot_is = false;//Start the shooting or not + } + + //Switching the pistol + public void ReAmmo01() + { + CloseDaoju(); + + daoju02.SetActive(true);//Display the weapon terminal + daoju020.SetActive(true);//Display the pistol + + GameManager._ammo = 0;//Pistol instance + GameManager.Instance.ReAmmo();//Define the pistol instance + + UI_amon01.SetActive(true);//Display the pistol UI + + shot_is = true;//Start the shooting + } + + //Swiching machine gun + public void ReAmmo02() + { + CloseDaoju(); + + daoju03.SetActive(true); + daoju021.SetActive(true);//Display the machine gun + + GameManager._ammo = 1;//Machine gun instance + GameManager.Instance.ReAmmo();//Define the instance for machine gun + + UI_amon02.SetActive(true);//Display machine gun UI + + shot_is = true; + } + +} +//Reference from \ No newline at end of file diff --git a/C#/Player/PlayerBB.cs b/C#/Player/PlayerBB.cs new file mode 100644 index 0000000..125a3aa --- /dev/null +++ b/C#/Player/PlayerBB.cs @@ -0,0 +1,138 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.SceneManagement; + +public class PlayerBB : MonoBehaviour //Inherits the monobehavior class +{ + + public AudioSource GetAS;//Audion for picking up the item + public Player m_player; + public Text Text_num_01;//Text on the information bar + public Text Text_num_02; + public Text Text_num_03; + public Text Text_num_04; + public Text Text_num_05; + + public int num_01 = 0;//Number of items on the information bar + public int num_02 = 0; + public int num_03 = 0; + public int num_04 = 0; + public int num_05 = 0; + + public int LevelNum = 3; + + void Start() + { + Text_num_01.text = num_01.ToString(); + Text_num_02.text = num_02.ToString(); + Text_num_03.text = num_03.ToString(); + Text_num_04.text = num_04.ToString(); + Text_num_05.text = num_05.ToString(); + } + + void Update() + { + //Press the H key + if (Input.GetKeyUp(KeyCode.H)) + { + if (num_01 > 0) + { + num_01--;//Items reduced by one on the information bar + Text_num_01.text = num_01.ToString();//Define the number for blood boost + + m_player.AddHp();//Add 20 to the hp + } + } + } + + void OnTriggerEnter(Collider other) + { + //Add tag to backpack + if (other.tag == "HP") + { + GetAS.Play();//Play audio + Destroy(other.gameObject);//Destory + + Add_01();//Add one more blood boost + } + + if (other.tag == "Qiang") + { + GetAS.Play(); + Destroy(other.gameObject); + + Add_02(); + } + + if (other.tag == "XD") + { + GetAS.Play(); + Destroy(other.gameObject); + + Add_03(); + } + + if (other.tag == "YS") + { + GetAS.Play(); + Destroy(other.gameObject); + + Add_04(); + } + + if (other.tag == "Jian") + { + GetAS.Play(); + Destroy(other.gameObject); + + Add_05(); + } + + //Teleport victory + if (other.tag == "Win")// Victory + { + //Indentify victory or not + if (num_02 == 1 && num_03 == 1 && num_04 == 1 && num_05 == 1) + { + //Release the lock for cursor + Cursor.lockState = CursorLockMode.None; + Cursor.visible = true; + + SceneManager.LoadScene(LevelNum+1); + } + } + } + + public void Add_01() + { + num_01++;//Items increase by one on the information bar + Text_num_01.text = num_01.ToString();//Define the number for blood boost + } + + public void Add_02() + { + num_02++; + Text_num_02.text = num_02.ToString(); + } + + public void Add_03() + { + num_03++; + Text_num_03.text = num_03.ToString(); + } + + public void Add_04() + { + num_04++; + Text_num_04.text = num_04.ToString(); + } + + public void Add_05() + { + num_05++; + Text_num_05.text = num_05.ToString(); + } + +} diff --git a/C#/ScenePanel.cs b/C#/ScenePanel.cs new file mode 100644 index 0000000..3fc167c --- /dev/null +++ b/C#/ScenePanel.cs @@ -0,0 +1,108 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +using UnityEngine.UI; +using UnityEngine.SceneManagement; + +public class ScenePanel : MonoBehaviour +{ + /// + /// select the game level + /// + public Button Button_Play; //Confirm level button + public Button Button_Next; //Next level button + public Button Button_Pre; //Previous level button + public static int Level_n = 1; //Number of levels + public GameObject[] Level_img = new GameObject[4]; //Level image array + + // Start is called before the first frame update + void Start() + { + Button_Play.onClick.AddListener(Button_PlayClickListener); //Add start game button listener + Button_Next.onClick.AddListener(Button_NextClickListener); //Add the next button listener + Button_Pre.onClick.AddListener(Button_PreClickListener); //Add previous button listener + + + for (int D = 0; D < 3; D++ ) + { + Level_img[D].SetActive(false); + } + + Level_img[Level_n - 1].SetActive(true); //Open scene image + } + + void Button_PlayClickListener() + { + Time.timeScale = 1; + SceneManager.LoadScene(Level_n+2);//Switching to corresponding level interface + } + + //Next level selection button listener + void Button_NextClickListener() + { + if (Level_n < 3) + { + Level_n += 1; + + CloseLeven();//Method for deploying image for opening the corresponding gaming level + + Level_img[Level_n - 1].SetActive(true);//Image for starting the corresponding interface for the gaming level + } + else + { + Level_n = 1; + + CloseLeven(); + + + Level_img[Level_n - 1].SetActive(true); + } + } + + //previous level selection button listener + void Button_PreClickListener() + { + if (Level_n == 1) + { + Level_n = 3; + + CloseLeven(); + + Level_img[Level_n - 1].SetActive(true); + } + else + { + Level_n -= 1; + + CloseLeven(); + + Level_img[Level_n - 1].SetActive(true); + } + } + + //Image for starting the corresponding interface for the gaming level + void CloseLeven() + { + for (int n=0;n< Level_img.Length; n++) + { + Level_img[n].SetActive(false); + } + } + + void Button_BackClickListener() + { + Time.timeScale = 1; + SceneManager.LoadScene(0);//Back to home page + } + + void Button_OverClickListener() + { +#if UNITY_EDITOR + UnityEditor.EditorApplication.isPlaying = false; +#else + Application.Quit(); +#endif + } + +} diff --git a/C#/WinOrLose.cs b/C#/WinOrLose.cs new file mode 100644 index 0000000..d4e5414 --- /dev/null +++ b/C#/WinOrLose.cs @@ -0,0 +1,33 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.SceneManagement; + +public class WinOrLose : MonoBehaviour +{ + public Button GameAgainButton;//Restart game button + public Button GameQuitButton;//Game quit button + + // Use this for initialization + void Start() + { + GameAgainButton.onClick.AddListener(GameAgainButtonClickListener); //Add re-game button listener + GameQuitButton.onClick.AddListener(GameQuitButtonClickListener); //Add game quit button listener + } + + void GameAgainButtonClickListener() + { + SceneManager.LoadScene(2);//Jump to the level selection interface + } + + void GameQuitButtonClickListener() + { +#if UNITY_EDITOR + UnityEditor.EditorApplication.isPlaying = false; +#else + Application.Quit(); +#endif + } + +} diff --git a/Scripts/ObserverEnemy.cs b/Scripts/ObserverEnemy.cs new file mode 100644 index 0000000..f1724a7 --- /dev/null +++ b/Scripts/ObserverEnemy.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class ObserverEnemy : MonoBehaviour +{ + + public Transform StartPosition;//Original starting position + public Transform Player;//Player + + bool m_IsPlayerInRange;//Is the player within range + + /// + /// collision detection + /// + void OnTriggerEnter(Collider other) + { + if (other.transform == Player) + { + m_IsPlayerInRange = true; + } + } + + void OnTriggerExit(Collider other) + { + if (other.transform == Player) + { + m_IsPlayerInRange = false; + } + } + + void Update() + { + if (m_IsPlayerInRange) + { + //Emission ray judgment + Vector3 direction = Player.position - transform.position + Vector3.up; + Ray ray = new Ray(transform.position, direction); + RaycastHit raycastHit; + + if (Physics.Raycast(ray, out raycastHit)) + { + if (raycastHit.collider.gameObject.tag == "Player") + { + Player.GetComponent().enabled = false; + Player.transform.position = StartPosition.transform.position;//Return to start position + Player.GetComponent().enabled = true; + } + } + } + } + +} diff --git a/Scripts/WaypointEnemy.cs b/Scripts/WaypointEnemy.cs new file mode 100644 index 0000000..8c55257 --- /dev/null +++ b/Scripts/WaypointEnemy.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AI; + +public class WaypointEnemy : MonoBehaviour +{ + + public NavMeshAgent navMeshAgent;//Navigation grid component + public Transform[] waypoints;//Waypoints + + int Enemy_CurrentWaypointIndex;//Current waypoint + + void Start() + { + navMeshAgent.SetDestination(waypoints[0].position);//Enter the position of the next waypoint + } + + void Update() + { + //When the distance from the next waypoint is less than the waypoint pause distance,loop the waypoint path + if (navMeshAgent.remainingDistance < navMeshAgent.stoppingDistance) + { + Enemy_CurrentWaypointIndex = (Enemy_CurrentWaypointIndex + 1) % waypoints.Length; + navMeshAgent.SetDestination(waypoints[Enemy_CurrentWaypointIndex].position); + } + } +} + +//Reference from