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

using System.Collections;
using UnityEngine;
using Networking.Server;
using TMPro;
public class Character : MonoBehaviour
{
public enum Animation { Walk, Run, Jump, Sit, Attack, Hit,None }
public blockSpawn spawn;
public int runOrder = 0;
public string nextScene;
Animator characterAnimator;
public bool isTuteLevel = false;
public bool inWater = false; //Am I in the water?
public bool respawnNeeded = false; //Am I waiting on a respawn?
public bool onCrystal = false;
public bool underRock = false;
public bool stuck = false; //Am I still stuck?
public bool justMoved = false; //Was the logic block I just executed a move command?
public bool inPit = false;
Vector3 death = new Vector3(-50, 0, 0);
#region Inspector Fields
[SerializeField]
[Tooltip("Will move to this block at start, else will try and find a block below")]
private Block _currentBlock;
[SerializeField]
[Tooltip("Layers to ignore when checking for blocks")]
public LayerMask Ignore;
[Tooltip("Current Inventory of the player")]
public Inventory Inventory;
public bool CloneInventoryOnStart = false;
[Tooltip("How many lives to start out with")]
public int lives = 3;
[SerializeField]
[Tooltip("Character to display")]
private string CharacterModel = "Bear";
[SerializeField]
public ClientData ClientLink;
[SerializeField]
private TMPro.TextMeshPro BlockTitlePrefab;
#endregion Inspector Fields
#region Read Only
public Block CurrentBlock { get { return _currentBlock; } }
public float lastRotation;
#endregion Read Only
#region Unity Functions
private void Start()
{
spawn = GameObject.Find("GameManager").GetComponent<blockSpawn>();
if (Inventory != null && CloneInventoryOnStart)
Inventory = Inventory.Clone(Inventory);
//If no starting block find one below it
if (_currentBlock == null)
Block.isBlockAtPosition(transform.position + Vector3.down / 2, 1, ~Ignore, out _currentBlock);
//move to starting block
transform.position = _currentBlock.VisualPosition;
//get character string from player replace from "Bear"
GameObject prefab = Resources.Load<GameObject>(CharacterModel);
GameObject animal = Instantiate(prefab, this.gameObject.transform);
characterAnimator = GetComponentInChildren<Animator>();
}
private void Update()
{
if(ClientLink.Lives < 1)
{
this.transform.position = death;
}
GetComponentInChildren<TextMeshPro>().text = runOrder.ToString();
}
#endregion Unity Functions
#region Class Implementation
public void Initialise(Block startingBlock, Inventory inventory, string Character)
{
_currentBlock = startingBlock;
Inventory = inventory;
CharacterModel = Character;
}
public void DisplayBlock(LogicBlock block)
{
if (isTuteLevel == false)
{
if (BlockTitlePrefab == null)
return;
TMPro.TextMeshPro temp = Instantiate(BlockTitlePrefab.gameObject).GetComponent<TMPro.TextMeshPro>();
temp.text = block.DisplayName;
temp.color = ClientLink.Color;
temp.transform.position = transform.position + (Vector3.one * 0.25f);
temp.transform.rotation = Quaternion.LookRotation(temp.transform.position - Camera.main.transform.position);
}
}
public IEnumerator MoveToBlock(Block target, Animation animation, float time)
{
float startTime = Time.time;
Vector3 moveDirection = Vector3.ProjectOnPlane(target.position - _currentBlock.position, Vector3.up).normalized;
_currentBlock.OnLeftByPlayer(this);
System.Func<float, float> yFunction = null;
if (animation == Animation.Jump)
yFunction = (t) => Mathf.Sin((Mathf.PI * t));
StartAnimation(animation, time);
yield return StartCoroutine(LerpToBlock(target.VisualPosition, time * 0.8f, yFunction));
_currentBlock= target;
yield return StartCoroutine (_currentBlock.OnWalkedOnByPlayer(this,moveDirection));
yield return new WaitForSeconds(time - (Time.time - startTime));
StopAnimation(animation);
}
public IEnumerator RotateInDirection(Direction direction,float angles, Animation animation, float time)
{
System.Func<float, float> yFunction = null;
if (animation == Animation.Jump)
yFunction = (t) => Mathf.Sin((Mathf.PI * t));
StartAnimation(animation, time);
yield return StartCoroutine(Rotate(direction,angles, time * 0.8f, yFunction));
StopAnimation(animation);
}
public IEnumerator AnimateToPosition(Vector3 position, Animation animation, float time)
{
System.Func<float, float> yFunction = null;
if (animation == Animation.Jump)
yFunction = (t) => Mathf.Sin((Mathf.PI * t));
StartAnimation(animation, time);
yield return StartCoroutine(LerpToBlock(position, time * 0.8f, yFunction));
StopAnimation(animation);
}
public void StartAnimation(Animation animation,float speed = 1)
{
switch (animation)
{
case Animation.Walk:
characterAnimator.SetBool("isWalking", true);
break;
case Animation.Run:
characterAnimator.SetBool("isRunning", true);
break;
case Animation.Sit:
characterAnimator.SetBool("isSitting", true);
break;
case Animation.Jump:
characterAnimator.SetTrigger("Jump");
break;
case Animation.Attack:
characterAnimator.SetTrigger("Attack");
break;
case Animation.Hit:
characterAnimator.SetTrigger("Hit");
break;
default:
break;
}
}
public void StopAnimation(Animation animation)
{
switch (animation)
{
case Animation.Walk:
characterAnimator.SetBool("isWalking", false);
break;
case Animation.Run:
characterAnimator.SetBool("isRunning", false);
break;
case Animation.Sit:
characterAnimator.SetBool("isSitting", false);
break;
}
}
public void respawnCharacter()
{
respawnCharacter(CurrentBlock);
}
public void respawnCharacter(Block respawnPosition)
{
//Having found our target block, we move the character there
if (respawnPosition != null)
{
if(ClientLink.Lives > 0)
{
this.transform.position = new Vector3(respawnPosition.VisualPosition.x, 0.5f, respawnPosition.VisualPosition.z);
this.respawnNeeded = false;
this._currentBlock = respawnPosition;
respawnPosition.CurrentPlayer = this;
this.stuck = false;
}
else
{
this.transform.position = new Vector3(-50, 0.5f, 0);
this.respawnNeeded = false;
this._currentBlock = respawnPosition;
respawnPosition.CurrentPlayer = this;
this.stuck = false;
}
}
else
{
//Debug.Log("Failed to find anywhere to put " + this.name);
}
}
/// <summary>
/// Upon collision with a floating block, collect its
/// Upon collision with the end portal, end of level
/// </summary>
/// <param name="other">name of collided object</param>
void OnTriggerEnter(Collider other)
{
Collectable collectable = other.GetComponentInChildren<Collectable>();
if (collectable != null)
{
//get position from average;
ClientList list = spawn.clientDataList;
float average = 0;
int livePlayerCount = 0;
foreach (ClientData data in list.ConnectedClients)
{
if (data.Lives > 0)
{
average += data.playerCharacter.transform.position.x;
livePlayerCount++;
}
}
average /= livePlayerCount;
float tosend = lives + (transform.position.x - average);
spawn.assignLogicBlock(collectable.gameObject, tosend);
collectable.OnCollect(this);
}
}
#endregion Class Implementation
#region Private Functions
private IEnumerator LerpToBlock(Vector3 target, float time, System.Func<float, float> heightOffset = null)
{
Vector3 _startPos = transform.position;
Vector3 _endPos = target;
Vector3 _newPos;
float elapsedTime = 0;
while (elapsedTime / time < 1)
{
_newPos = Vector3.Lerp(_startPos, _endPos, (elapsedTime / time));
if (heightOffset != null)
_newPos.y += heightOffset(elapsedTime / time);
transform.position = _newPos;
yield return new WaitForEndOfFrame();
elapsedTime += Time.deltaTime;
}
_newPos = _endPos;
if (heightOffset != null)
_newPos.y += heightOffset(1);
transform.position = _newPos;
}
private IEnumerator Rotate(Direction direction, float angles, float time, System.Func<float, float> heightOffset = null)
{
int RotationDir = 0;
switch (direction)
{
case Direction.Forward:
RotationDir = 0;
break;
case Direction.Left:
RotationDir = -1;
break;
case Direction.Right:
RotationDir = 1;
break;
case Direction.Back:
RotationDir = 2;
break;
}
lastRotation = angles * RotationDir;
float elapsedTime = 0;
float anglePerSecond = (angles * RotationDir) / time;
Vector3 _startPos = transform.position;
Vector3 startDirection = transform.forward;
while (elapsedTime < time)
{
transform.Rotate(Vector3.up, anglePerSecond * Time.deltaTime);
if (heightOffset != null)
transform.position = _startPos + Vector3.up * heightOffset(elapsedTime / time);
yield return new WaitForEndOfFrame();
elapsedTime += Time.deltaTime;
}
transform.forward = Quaternion.AngleAxis(angles * RotationDir, Vector3.up) * startDirection;
if (heightOffset != null)
transform.position = _startPos + Vector3.up * heightOffset(1);
}
#endregion Private Functions
}