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.

341 lines
11 KiB

4 years ago
4 years ago
4 years ago
  1. using System.Collections;
  2. using UnityEngine;
  3. using Networking.Server;
  4. using TMPro;
  5. public class Character : MonoBehaviour
  6. {
  7. public enum Animation { Walk, Run, Jump, Sit, Attack, Hit,None }
  8. public blockSpawn spawn;
  9. public int runOrder = 0;
  10. public string nextScene;
  11. Animator characterAnimator;
  12. public bool isTuteLevel = false;
  13. public bool inWater = false; //Am I in the water?
  14. public bool respawnNeeded = false; //Am I waiting on a respawn?
  15. public bool onCrystal = false;
  16. public bool underRock = false;
  17. public bool stuck = false; //Am I still stuck?
  18. public bool justMoved = false; //Was the logic block I just executed a move command?
  19. public bool inPit = false;
  20. Vector3 death = new Vector3(-50, 0, 0);
  21. #region Inspector Fields
  22. [SerializeField]
  23. [Tooltip("Will move to this block at start, else will try and find a block below")]
  24. private Block _currentBlock;
  25. [SerializeField]
  26. [Tooltip("Layers to ignore when checking for blocks")]
  27. public LayerMask Ignore;
  28. [Tooltip("Current Inventory of the player")]
  29. public Inventory Inventory;
  30. public bool CloneInventoryOnStart = false;
  31. [Tooltip("How many lives to start out with")]
  32. public int lives = 3;
  33. [SerializeField]
  34. [Tooltip("Character to display")]
  35. private string CharacterModel = "Bear";
  36. [SerializeField]
  37. public ClientData ClientLink;
  38. [SerializeField]
  39. private TMPro.TextMeshPro BlockTitlePrefab;
  40. #endregion Inspector Fields
  41. #region Read Only
  42. public Block CurrentBlock { get { return _currentBlock; } }
  43. public float lastRotation;
  44. #endregion Read Only
  45. #region Unity Functions
  46. private void Start()
  47. {
  48. spawn = GameObject.Find("GameManager").GetComponent<blockSpawn>();
  49. if (Inventory != null && CloneInventoryOnStart)
  50. Inventory = Inventory.Clone(Inventory);
  51. //If no starting block find one below it
  52. if (_currentBlock == null)
  53. Block.isBlockAtPosition(transform.position + Vector3.down / 2, 1, ~Ignore, out _currentBlock);
  54. //move to starting block
  55. transform.position = _currentBlock.VisualPosition;
  56. //get character string from player replace from "Bear"
  57. GameObject prefab = Resources.Load<GameObject>(CharacterModel);
  58. GameObject animal = Instantiate(prefab, this.gameObject.transform);
  59. characterAnimator = GetComponentInChildren<Animator>();
  60. }
  61. private void Update()
  62. {
  63. if(ClientLink.Lives < 1)
  64. {
  65. this.transform.position = death;
  66. }
  67. GetComponentInChildren<TextMeshPro>().text = runOrder.ToString();
  68. }
  69. #endregion Unity Functions
  70. #region Class Implementation
  71. public void Initialise(Block startingBlock, Inventory inventory, string Character)
  72. {
  73. _currentBlock = startingBlock;
  74. Inventory = inventory;
  75. CharacterModel = Character;
  76. }
  77. public void DisplayBlock(LogicBlock block)
  78. {
  79. if (isTuteLevel == false)
  80. {
  81. if (BlockTitlePrefab == null)
  82. return;
  83. TMPro.TextMeshPro temp = Instantiate(BlockTitlePrefab.gameObject).GetComponent<TMPro.TextMeshPro>();
  84. temp.text = block.DisplayName;
  85. temp.color = ClientLink.Color;
  86. temp.transform.position = transform.position + (Vector3.one * 0.25f);
  87. temp.transform.rotation = Quaternion.LookRotation(temp.transform.position - Camera.main.transform.position);
  88. }
  89. }
  90. public IEnumerator MoveToBlock(Block target, Animation animation, float time)
  91. {
  92. float startTime = Time.time;
  93. Vector3 moveDirection = Vector3.ProjectOnPlane(target.position - _currentBlock.position, Vector3.up).normalized;
  94. _currentBlock.OnLeftByPlayer(this);
  95. System.Func<float, float> yFunction = null;
  96. if (animation == Animation.Jump)
  97. yFunction = (t) => Mathf.Sin((Mathf.PI * t));
  98. StartAnimation(animation, time);
  99. yield return StartCoroutine(LerpToBlock(target.VisualPosition, time * 0.8f, yFunction));
  100. _currentBlock= target;
  101. yield return StartCoroutine (_currentBlock.OnWalkedOnByPlayer(this,moveDirection));
  102. yield return new WaitForSeconds(time - (Time.time - startTime));
  103. StopAnimation(animation);
  104. }
  105. public IEnumerator RotateInDirection(Direction direction,float angles, Animation animation, float time)
  106. {
  107. System.Func<float, float> yFunction = null;
  108. if (animation == Animation.Jump)
  109. yFunction = (t) => Mathf.Sin((Mathf.PI * t));
  110. StartAnimation(animation, time);
  111. yield return StartCoroutine(Rotate(direction,angles, time * 0.8f, yFunction));
  112. StopAnimation(animation);
  113. }
  114. public IEnumerator AnimateToPosition(Vector3 position, Animation animation, float time)
  115. {
  116. System.Func<float, float> yFunction = null;
  117. if (animation == Animation.Jump)
  118. yFunction = (t) => Mathf.Sin((Mathf.PI * t));
  119. StartAnimation(animation, time);
  120. yield return StartCoroutine(LerpToBlock(position, time * 0.8f, yFunction));
  121. StopAnimation(animation);
  122. }
  123. public void StartAnimation(Animation animation,float speed = 1)
  124. {
  125. switch (animation)
  126. {
  127. case Animation.Walk:
  128. characterAnimator.SetBool("isWalking", true);
  129. break;
  130. case Animation.Run:
  131. characterAnimator.SetBool("isRunning", true);
  132. break;
  133. case Animation.Sit:
  134. characterAnimator.SetBool("isSitting", true);
  135. break;
  136. case Animation.Jump:
  137. characterAnimator.SetTrigger("Jump");
  138. break;
  139. case Animation.Attack:
  140. characterAnimator.SetTrigger("Attack");
  141. break;
  142. case Animation.Hit:
  143. characterAnimator.SetTrigger("Hit");
  144. break;
  145. default:
  146. break;
  147. }
  148. }
  149. public void StopAnimation(Animation animation)
  150. {
  151. switch (animation)
  152. {
  153. case Animation.Walk:
  154. characterAnimator.SetBool("isWalking", false);
  155. break;
  156. case Animation.Run:
  157. characterAnimator.SetBool("isRunning", false);
  158. break;
  159. case Animation.Sit:
  160. characterAnimator.SetBool("isSitting", false);
  161. break;
  162. }
  163. }
  164. public void respawnCharacter()
  165. {
  166. respawnCharacter(CurrentBlock);
  167. }
  168. public void respawnCharacter(Block respawnPosition)
  169. {
  170. //Having found our target block, we move the character there
  171. if (respawnPosition != null)
  172. {
  173. if(ClientLink.Lives > 0)
  174. {
  175. this.transform.position = new Vector3(respawnPosition.VisualPosition.x, 0.5f, respawnPosition.VisualPosition.z);
  176. this.respawnNeeded = false;
  177. this._currentBlock = respawnPosition;
  178. respawnPosition.CurrentPlayer = this;
  179. this.stuck = false;
  180. }
  181. else
  182. {
  183. this.transform.position = new Vector3(-50, 0.5f, 0);
  184. this.respawnNeeded = false;
  185. this._currentBlock = respawnPosition;
  186. respawnPosition.CurrentPlayer = this;
  187. this.stuck = false;
  188. }
  189. }
  190. else
  191. {
  192. //Debug.Log("Failed to find anywhere to put " + this.name);
  193. }
  194. }
  195. /// <summary>
  196. /// Upon collision with a floating block, collect its
  197. /// Upon collision with the end portal, end of level
  198. /// </summary>
  199. /// <param name="other">name of collided object</param>
  200. void OnTriggerEnter(Collider other)
  201. {
  202. Collectable collectable = other.GetComponentInChildren<Collectable>();
  203. if (collectable != null)
  204. {
  205. //get position from average;
  206. ClientList list = spawn.clientDataList;
  207. float average = 0;
  208. int livePlayerCount = 0;
  209. foreach (ClientData data in list.ConnectedClients)
  210. {
  211. if (data.Lives > 0)
  212. {
  213. average += data.playerCharacter.transform.position.x;
  214. livePlayerCount++;
  215. }
  216. }
  217. average /= livePlayerCount;
  218. float tosend = lives + (transform.position.x - average);
  219. spawn.assignLogicBlock(collectable.gameObject, tosend);
  220. collectable.OnCollect(this);
  221. }
  222. }
  223. #endregion Class Implementation
  224. #region Private Functions
  225. private IEnumerator LerpToBlock(Vector3 target, float time, System.Func<float, float> heightOffset = null)
  226. {
  227. Vector3 _startPos = transform.position;
  228. Vector3 _endPos = target;
  229. Vector3 _newPos;
  230. float elapsedTime = 0;
  231. while (elapsedTime / time < 1)
  232. {
  233. _newPos = Vector3.Lerp(_startPos, _endPos, (elapsedTime / time));
  234. if (heightOffset != null)
  235. _newPos.y += heightOffset(elapsedTime / time);
  236. transform.position = _newPos;
  237. yield return new WaitForEndOfFrame();
  238. elapsedTime += Time.deltaTime;
  239. }
  240. _newPos = _endPos;
  241. if (heightOffset != null)
  242. _newPos.y += heightOffset(1);
  243. transform.position = _newPos;
  244. }
  245. private IEnumerator Rotate(Direction direction, float angles, float time, System.Func<float, float> heightOffset = null)
  246. {
  247. int RotationDir = 0;
  248. switch (direction)
  249. {
  250. case Direction.Forward:
  251. RotationDir = 0;
  252. break;
  253. case Direction.Left:
  254. RotationDir = -1;
  255. break;
  256. case Direction.Right:
  257. RotationDir = 1;
  258. break;
  259. case Direction.Back:
  260. RotationDir = 2;
  261. break;
  262. }
  263. lastRotation = angles * RotationDir;
  264. float elapsedTime = 0;
  265. float anglePerSecond = (angles * RotationDir) / time;
  266. Vector3 _startPos = transform.position;
  267. Vector3 startDirection = transform.forward;
  268. while (elapsedTime < time)
  269. {
  270. transform.Rotate(Vector3.up, anglePerSecond * Time.deltaTime);
  271. if (heightOffset != null)
  272. transform.position = _startPos + Vector3.up * heightOffset(elapsedTime / time);
  273. yield return new WaitForEndOfFrame();
  274. elapsedTime += Time.deltaTime;
  275. }
  276. transform.forward = Quaternion.AngleAxis(angles * RotationDir, Vector3.up) * startDirection;
  277. if (heightOffset != null)
  278. transform.position = _startPos + Vector3.up * heightOffset(1);
  279. }
  280. #endregion Private Functions
  281. }