You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
10 KiB

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using UnityEngine.SceneManagement;
  6. public class Character : MonoBehaviour
  7. {
  8. public string nextScene;
  9. Animator characterAnimator;
  10. #region Inspector Fields
  11. [SerializeField]
  12. [Tooltip("Will move to this block at start, else will try and find a block below")]
  13. private Block _currentBlock;
  14. [SerializeField]
  15. [Tooltip("Layers to ignore when checking for blocks")]
  16. private LayerMask Ignore;
  17. [Tooltip("Current Inventory of the player")]
  18. public Inventory Inventory;
  19. [SerializeField]
  20. [Tooltip("Character to display")]
  21. private string CharacterModel = "Bear";
  22. #endregion Inspector Fields
  23. #region Read Only
  24. public Block CurrentBlock { get { return _currentBlock; } }
  25. #endregion Read Only
  26. #region Unity Functions
  27. private void Start()
  28. {
  29. if (Inventory != null)
  30. Inventory = Inventory.Clone(Inventory);
  31. //If no starting block find one below it
  32. if (_currentBlock == null)
  33. Block.isBlockAtPosition(transform.position + Vector3.down / 2, 1, ~Ignore, out _currentBlock);
  34. //move to starting block
  35. transform.position = _currentBlock.VisualPosition;
  36. //get character string from player replace from "Bear"
  37. GameObject prefab = Resources.Load(CharacterModel) as GameObject;
  38. GameObject Bear = Instantiate(prefab, this.gameObject.transform);
  39. characterAnimator = GetComponentInChildren<Animator>();
  40. }
  41. #endregion Unity Functions
  42. #region Class Implementation
  43. public void Initialise(Block startingBlock, Inventory inventory, string Character) {
  44. _currentBlock = startingBlock;
  45. Inventory = inventory;
  46. CharacterModel = Character;
  47. }
  48. public Vector3 yValue(float time, float heightMultiplier)
  49. {
  50. float y = Mathf.Sin((Mathf.PI*time)) * heightMultiplier;
  51. return new Vector3(0, y, 0);
  52. }
  53. IEnumerator JumpCoroutine(Block Target, Transform Current, float time, float heightMax)
  54. {
  55. float elapsedTime = 0;
  56. Vector3 startPosition = Current.position;
  57. time *= 0.8f;
  58. characterAnimator.Play("Jump Inplace");
  59. yield return new WaitForSeconds(0.15f);
  60. while (elapsedTime < time)
  61. {
  62. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  63. transform.position += yValue((elapsedTime / time), heightMax);
  64. yield return new WaitForEndOfFrame();
  65. elapsedTime += Time.deltaTime;
  66. }
  67. transform.position = Target.VisualPosition;
  68. }
  69. IEnumerator MoveCoroutine(Block Target, Transform Current, float time, float heightMax)
  70. {
  71. float elapsedTime = 0;
  72. Vector3 startPosition = Current.position;
  73. time *= 0.8f;
  74. characterAnimator.Play("Walk");
  75. yield return new WaitForSeconds(0.05f);
  76. while (elapsedTime < time)
  77. {
  78. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  79. yield return new WaitForEndOfFrame();
  80. elapsedTime += Time.deltaTime;
  81. }
  82. transform.position = Target.VisualPosition;
  83. }
  84. IEnumerator MoveDownCoroutine(Block Target, Transform Current, float time, float heightMax)
  85. {
  86. float elapsedTime = 0;
  87. Vector3 startPosition = Current.position;
  88. time *= 0.8f;
  89. characterAnimator.Play("Walk");
  90. while (elapsedTime < time)
  91. {
  92. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  93. transform.position += yValue((elapsedTime / time), heightMax);
  94. yield return new WaitForEndOfFrame();
  95. elapsedTime += Time.deltaTime;
  96. }
  97. transform.position = Target.VisualPosition;
  98. }
  99. IEnumerator rotateCoroutine(Direction direction, Transform Current, float time, float heightMax)
  100. {
  101. float elapsedTime = 0;
  102. time *= 0.8f;
  103. Vector3 endDirection = direction.ToVector(Current);
  104. Vector3 startDirection = Current.forward;
  105. Vector3 startPosition = transform.position;
  106. while (elapsedTime < time)
  107. {
  108. characterAnimator.Play("Jump");
  109. transform.forward = Vector3.Slerp(startDirection, endDirection, (elapsedTime / time));
  110. yield return new WaitForEndOfFrame();
  111. elapsedTime += Time.deltaTime;
  112. }
  113. transform.forward = endDirection;
  114. }
  115. /// <summary>
  116. /// Moves one block in specefied direction, Can walk off obstacles
  117. /// </summary>
  118. /// <param name="direction">direction to walk</param>
  119. /// <remarks>Technically is same as JumpLong(1) but kept seperate to avoid confusion</remarks>
  120. public void Move(Direction direction, float speed)
  121. {
  122. //setting up variables
  123. Vector3 position = _currentBlock.position + direction.ToVector(transform); // position wanted
  124. Block hit; //output of block detection
  125. Block moveTo = _currentBlock; //block we'll actually move to
  126. //if move is obstucted no where to move
  127. if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
  128. return;
  129. //If block at Position is walkable set it to moveTo
  130. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)){
  131. moveTo = hit;
  132. _currentBlock = moveTo;
  133. StartCoroutine(MoveCoroutine(_currentBlock, transform, speed, 0.3f)); }
  134. //else if block down one is walkable
  135. else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)){
  136. moveTo = hit;
  137. _currentBlock = moveTo;
  138. StartCoroutine(MoveDownCoroutine(_currentBlock, transform, speed, 0.3f));
  139. }
  140. //set current block && move
  141. //CurrentBlock = moveTo;
  142. //StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.3f));
  143. //transform.position = CurrentBlock.VisualPosition;
  144. }
  145. /// <summary>
  146. /// Upon collision with a floating block, collect its
  147. /// Upon collision with the end portal, end of level
  148. /// </summary>
  149. /// <param name="other">name of collided object</param>
  150. void OnTriggerEnter(Collider other)
  151. {
  152. Collectable collectable = other.GetComponentInChildren<Collectable>();
  153. if (collectable != null)
  154. {
  155. collectable.OnCollect(this);
  156. }
  157. if (other.gameObject.name == "collect_sphere"){
  158. other.gameObject.SetActive(false);
  159. //player.collected +=1;
  160. }
  161. if (other.gameObject.name == "End Portal")
  162. {
  163. other.GetComponent<Collider>().enabled = false;
  164. SceneManager.LoadScene(nextScene);
  165. }
  166. }
  167. /// <summary>
  168. /// Rotates to point in specific direction based on current direction
  169. /// </summary>
  170. /// <param name="direction">Local direction to point</param>
  171. public void Rotate(Direction direction, float speed)
  172. {
  173. StartCoroutine(rotateCoroutine(direction, transform, speed, 0.15f));
  174. //transform.forward = direction.ToVector(transform);
  175. }
  176. /// <summary>
  177. /// Jumps in specefied direction, picks between Long Jump and Jumping up
  178. /// </summary>
  179. /// <param name="direction">Direction to Jump</param>
  180. public void Jump(Direction direction, float speed)
  181. {
  182. //if there is a block infront JumpUp else LongJump
  183. if (Block.isBlockAtPosition(_currentBlock.position + direction.ToVector(transform) + Vector3.up, 1, ~Ignore))
  184. JumpUp(direction, speed);
  185. else
  186. JumpLong(direction, speed);
  187. }
  188. #endregion Class Implementation
  189. #region Private Functions
  190. /// <summary>
  191. /// Jumps up obstacle of specific height. Jumps as high as possible
  192. /// </summary>
  193. /// <param name="direction">Direction of obstacle</param>
  194. /// <param name="height">max height</param>
  195. private void JumpUp(Direction direction, float speed, int height = 1)
  196. {
  197. //setting up variables
  198. Vector3 position; // position wanted
  199. Block hit; //output of block detection
  200. Block moveTo = _currentBlock; //block we'll actually move to
  201. //Check blocks in going up then move to the heighest walkable one
  202. for (int i = 0; i <= height; i++)
  203. {
  204. //next position up the tower
  205. position = _currentBlock.position + direction.ToVector(transform) + (Vector3.up * i);
  206. //if block is walkable set it to last known position
  207. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  208. moveTo = hit;
  209. }
  210. //set current block && move
  211. _currentBlock = moveTo;
  212. StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
  213. //transform.position = CurrentBlock.VisualPosition;
  214. }
  215. /// <summary>
  216. /// Long jumps forward a specified distance. Can Jump gaps. Stops at obstruction
  217. /// </summary>
  218. /// <param name="direction">Direction to Jump</param>
  219. /// <param name="Distance">Max distance</param>
  220. private void JumpLong(Direction direction, float speed, int Distance = 2)
  221. {
  222. //setting up variables
  223. Vector3 position; // position wanted
  224. Block hit; //output of block detection
  225. Block moveTo = _currentBlock; //block we'll actually move to
  226. //Check blocks in front until we hit an obstruction or went the distance
  227. for (int i = 1; i <= Distance; i++)
  228. {
  229. //Next position to MoveTo
  230. position = _currentBlock.position + (direction.ToVector(transform) * i);
  231. //if jump is obstructed, stop and go to last known block
  232. if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
  233. break;
  234. //If block at Position is walkable set it to last known position
  235. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  236. moveTo = hit;
  237. //else if block down one is walkable
  238. else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  239. moveTo = hit;
  240. }//end for
  241. //Set Current Block and move
  242. _currentBlock = moveTo;
  243. StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
  244. //transform.position = CurrentBlock.VisualPosition;
  245. }
  246. #endregion Private Functions
  247. }