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.

325 lines
11 KiB

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