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.

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