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.

328 lines
10 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. this.transform.position = new Vector3(respawnPosition.VisualPosition.x, 0.5f, respawnPosition.VisualPosition.z);
  174. this.respawnNeeded = false;
  175. this._currentBlock = respawnPosition;
  176. respawnPosition.CurrentPlayer = this;
  177. this.stuck = false;
  178. }
  179. else
  180. {
  181. //Debug.Log("Failed to find anywhere to put " + this.name);
  182. }
  183. }
  184. /// <summary>
  185. /// Upon collision with a floating block, collect its
  186. /// Upon collision with the end portal, end of level
  187. /// </summary>
  188. /// <param name="other">name of collided object</param>
  189. void OnTriggerEnter(Collider other)
  190. {
  191. Collectable collectable = other.GetComponentInChildren<Collectable>();
  192. if (collectable != null)
  193. {
  194. //get position from average;
  195. ClientList list = spawn.clientDataList;
  196. float average = 0;
  197. int livePlayerCount = 0;
  198. foreach (ClientData data in list.ConnectedClients)
  199. {
  200. if (data.Lives > 0)
  201. {
  202. average += data.playerCharacter.transform.position.x;
  203. livePlayerCount++;
  204. }
  205. }
  206. average /= livePlayerCount;
  207. float tosend = lives + (transform.position.x - average);
  208. spawn.assignLogicBlock(collectable.gameObject, tosend);
  209. collectable.OnCollect(this);
  210. }
  211. }
  212. #endregion Class Implementation
  213. #region Private Functions
  214. private IEnumerator LerpToBlock(Vector3 target, float time, System.Func<float, float> heightOffset = null)
  215. {
  216. Vector3 _startPos = transform.position;
  217. Vector3 _endPos = target;
  218. Vector3 _newPos;
  219. float elapsedTime = 0;
  220. while (elapsedTime / time < 1)
  221. {
  222. _newPos = Vector3.Lerp(_startPos, _endPos, (elapsedTime / time));
  223. if (heightOffset != null)
  224. _newPos.y += heightOffset(elapsedTime / time);
  225. transform.position = _newPos;
  226. yield return new WaitForEndOfFrame();
  227. elapsedTime += Time.deltaTime;
  228. }
  229. _newPos = _endPos;
  230. if (heightOffset != null)
  231. _newPos.y += heightOffset(1);
  232. transform.position = _newPos;
  233. }
  234. private IEnumerator Rotate(Direction direction, float angles, float time, System.Func<float, float> heightOffset = null)
  235. {
  236. int RotationDir = 0;
  237. switch (direction)
  238. {
  239. case Direction.Forward:
  240. RotationDir = 0;
  241. break;
  242. case Direction.Left:
  243. RotationDir = -1;
  244. break;
  245. case Direction.Right:
  246. RotationDir = 1;
  247. break;
  248. case Direction.Back:
  249. RotationDir = 2;
  250. break;
  251. }
  252. lastRotation = angles * RotationDir;
  253. float elapsedTime = 0;
  254. float anglePerSecond = (angles * RotationDir) / time;
  255. Vector3 _startPos = transform.position;
  256. Vector3 startDirection = transform.forward;
  257. while (elapsedTime < time)
  258. {
  259. transform.Rotate(Vector3.up, anglePerSecond * Time.deltaTime);
  260. if (heightOffset != null)
  261. transform.position = _startPos + Vector3.up * heightOffset(elapsedTime / time);
  262. yield return new WaitForEndOfFrame();
  263. elapsedTime += Time.deltaTime;
  264. }
  265. transform.forward = Quaternion.AngleAxis(angles * RotationDir, Vector3.up) * startDirection;
  266. if (heightOffset != null)
  267. transform.position = _startPos + Vector3.up * heightOffset(1);
  268. }
  269. #endregion Private Functions
  270. }