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.

369 lines
11 KiB

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