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.

386 lines
14 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 MoveConveyorCoroutine(Block Target, Transform Current, float time, float heightMax)
  105. {
  106. float elapsedTime = 0;
  107. Vector3 startPosition = Current.position;
  108. time *= 0.8f;
  109. yield return new WaitForSeconds(0.05f);
  110. while (elapsedTime < time)
  111. {
  112. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  113. yield return new WaitForEndOfFrame();
  114. elapsedTime += Time.deltaTime;
  115. }
  116. transform.position = Target.VisualPosition;
  117. }
  118. IEnumerator PushLeftCoroutine(Transform Current, float time)
  119. {
  120. float elapsedTime = 0;
  121. Vector3 startPosition = Current.position;
  122. Vector3 endPosition = new Vector3(Current.position.x - 1, Current.position.y, Current.position.z);
  123. time *= 0.8f;
  124. yield return new WaitForSeconds(0.05f);
  125. while (elapsedTime < time)
  126. {
  127. transform.position = Vector3.Lerp(startPosition, endPosition, (elapsedTime / time));
  128. yield return new WaitForEndOfFrame();
  129. elapsedTime += Time.deltaTime;
  130. }
  131. transform.position = endPosition;
  132. }
  133. IEnumerator PushRightCoroutine(Transform Current, float time)
  134. {
  135. float elapsedTime = 0;
  136. Vector3 startPosition = Current.position;
  137. Vector3 endPosition = new Vector3(Current.position.x + 1, Current.position.y, Current.position.z);
  138. time *= 0.8f;
  139. yield return new WaitForSeconds(0.05f);
  140. while (elapsedTime < time)
  141. {
  142. transform.position = Vector3.Lerp(startPosition, endPosition, (elapsedTime / time));
  143. yield return new WaitForEndOfFrame();
  144. elapsedTime += Time.deltaTime;
  145. }
  146. transform.position = endPosition;
  147. }
  148. IEnumerator MoveDownCoroutine(Block Target, Transform Current, float time, float heightMax)
  149. {
  150. float elapsedTime = 0;
  151. Vector3 startPosition = Current.position;
  152. time *= 0.8f;
  153. characterAnimator.Play("Walk");
  154. while (elapsedTime < time)
  155. {
  156. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  157. transform.position += yValue((elapsedTime / time), heightMax);
  158. yield return new WaitForEndOfFrame();
  159. elapsedTime += Time.deltaTime;
  160. }
  161. transform.position = Target.VisualPosition;
  162. }
  163. IEnumerator rotateCoroutine(Direction direction, Transform Current, float time, float heightMax)
  164. {
  165. float elapsedTime = 0;
  166. time *= 0.8f;
  167. Vector3 endDirection = direction.ToVector(Current);
  168. Vector3 startDirection = Current.forward;
  169. Vector3 startPosition = transform.position;
  170. while (elapsedTime < time)
  171. {
  172. characterAnimator.Play("Jump");
  173. transform.forward = Vector3.Slerp(startDirection, endDirection, (elapsedTime / time));
  174. yield return new WaitForEndOfFrame();
  175. elapsedTime += Time.deltaTime;
  176. }
  177. transform.forward = endDirection;
  178. }
  179. /// <summary>
  180. /// Moves one block in specefied direction, Can walk off obstacles
  181. /// </summary>
  182. /// <param name="direction">direction to walk</param>
  183. /// <remarks>Technically is same as JumpLong(1) but kept seperate to avoid confusion</remarks>
  184. public void Move(Direction direction, float speed)
  185. {
  186. //setting up variables
  187. Vector3 position = _currentBlock.position + direction.ToVector(transform); // position wanted
  188. Block hit; //output of block detection
  189. Block moveTo = _currentBlock; //block we'll actually move to
  190. //if move is obstucted no where to move
  191. if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
  192. return;
  193. //If block at Position is walkable set it to moveTo
  194. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  195. {
  196. moveTo = hit;
  197. _currentBlock = moveTo;
  198. StartCoroutine(MoveCoroutine(_currentBlock, transform, speed, 0.3f));
  199. }
  200. //else if block down one is walkable
  201. else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  202. {
  203. moveTo = hit;
  204. _currentBlock = moveTo;
  205. StartCoroutine(MoveDownCoroutine(_currentBlock, transform, speed, 0.3f));
  206. }
  207. //set current block && move
  208. //CurrentBlock = moveTo;
  209. //StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.3f));
  210. //transform.position = CurrentBlock.VisualPosition;
  211. }
  212. public void conveyorMove(Direction direction, float speed)
  213. {
  214. Vector3 position = _currentBlock.position + direction.ToVector(transform); // position wanted
  215. StartCoroutine(MoveConveyorCoroutine(_currentBlock, transform, speed, 0.3f));
  216. }
  217. public void CannonRMove(Direction direction, float speed)
  218. {
  219. StartCoroutine(PushRightCoroutine(transform, speed));
  220. }
  221. public void CannonLMove(Direction direction, float speed)
  222. {
  223. StartCoroutine(PushLeftCoroutine(transform, speed));
  224. }
  225. /// <summary>
  226. /// Upon collision with a floating block, collect its
  227. /// Upon collision with the end portal, end of level
  228. /// </summary>
  229. /// <param name="other">name of collided object</param>
  230. void OnTriggerEnter(Collider other)
  231. {
  232. Collectable collectable = other.GetComponentInChildren<Collectable>();
  233. if (collectable != null)
  234. {
  235. collectable.OnCollect(this);
  236. }
  237. if (other.gameObject.name == "collect_sphere")
  238. {
  239. other.gameObject.SetActive(false);
  240. //player.collected +=1;
  241. }
  242. if (other.gameObject.name == "End Portal")
  243. {
  244. other.GetComponent<Collider>().enabled = false;
  245. SceneManager.LoadScene(nextScene);
  246. }
  247. }
  248. /// <summary>
  249. /// Rotates to point in specific direction based on current direction
  250. /// </summary>
  251. /// <param name="direction">Local direction to point</param>
  252. public void Rotate(Direction direction, float speed)
  253. {
  254. StartCoroutine(rotateCoroutine(direction, transform, speed, 0.15f));
  255. //transform.forward = direction.ToVector(transform);
  256. }
  257. /// <summary>
  258. /// Jumps in specefied direction, picks between Long Jump and Jumping up
  259. /// </summary>
  260. /// <param name="direction">Direction to Jump</param>
  261. public void Jump(Direction direction, float speed)
  262. {
  263. //if there is a block infront JumpUp else LongJump
  264. if (Block.isBlockAtPosition(_currentBlock.position + direction.ToVector(transform) + Vector3.up, 1, ~Ignore))
  265. JumpUp(direction, speed);
  266. else
  267. JumpLong(direction, speed);
  268. }
  269. #endregion Class Implementation
  270. #region Private Functions
  271. /// <summary>
  272. /// Jumps up obstacle of specific height. Jumps as high as possible
  273. /// </summary>
  274. /// <param name="direction">Direction of obstacle</param>
  275. /// <param name="height">max height</param>
  276. private void JumpUp(Direction direction, float speed, int height = 1)
  277. {
  278. //setting up variables
  279. Vector3 position; // position wanted
  280. Block hit; //output of block detection
  281. Block moveTo = _currentBlock; //block we'll actually move to
  282. //Check blocks in going up then move to the heighest walkable one
  283. for (int i = 0; i <= height; i++)
  284. {
  285. //next position up the tower
  286. position = _currentBlock.position + direction.ToVector(transform) + (Vector3.up * i);
  287. //if block is walkable set it to last known position
  288. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  289. moveTo = hit;
  290. }
  291. //set current block && move
  292. _currentBlock = moveTo;
  293. StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
  294. //transform.position = CurrentBlock.VisualPosition;
  295. }
  296. /// <summary>
  297. /// Long jumps forward a specified distance. Can Jump gaps. Stops at obstruction
  298. /// </summary>
  299. /// <param name="direction">Direction to Jump</param>
  300. /// <param name="Distance">Max distance</param>
  301. private void JumpLong(Direction direction, float speed, int Distance = 2)
  302. {
  303. //setting up variables
  304. Vector3 position; // position wanted
  305. Block hit; //output of block detection
  306. Block moveTo = _currentBlock; //block we'll actually move to
  307. //Check blocks in front until we hit an obstruction or went the distance
  308. for (int i = 1; i <= Distance; i++)
  309. {
  310. //Next position to MoveTo
  311. position = _currentBlock.position + (direction.ToVector(transform) * i);
  312. //if jump is obstructed, stop and go to last known block
  313. if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
  314. break;
  315. //If block at Position is walkable set it to last known position
  316. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  317. moveTo = hit;
  318. //else if block down one is walkable
  319. else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  320. moveTo = hit;
  321. }//end for
  322. //Set Current Block and move
  323. _currentBlock = moveTo;
  324. StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
  325. //transform.position = CurrentBlock.VisualPosition;
  326. }
  327. #endregion Private Functions
  328. }