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.

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