using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public class Character : MonoBehaviour
|
|
{
|
|
public string nextScene;
|
|
Animator characterAnimator;
|
|
|
|
#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")]
|
|
private LayerMask Ignore;
|
|
|
|
[Tooltip("Current Inventory of the player")]
|
|
public Inventory Inventory;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Character to display")]
|
|
private string CharacterModel = "Bear";
|
|
|
|
#endregion Inspector Fields
|
|
|
|
#region Read Only
|
|
public Block CurrentBlock { get { return _currentBlock; } }
|
|
#endregion Read Only
|
|
|
|
#region Unity Functions
|
|
|
|
private void Start()
|
|
{
|
|
if (Inventory != null)
|
|
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(CharacterModel) as GameObject;
|
|
GameObject Bear = Instantiate(prefab, this.gameObject.transform);
|
|
|
|
characterAnimator = GetComponentInChildren<Animator>();
|
|
}
|
|
|
|
|
|
|
|
#endregion Unity Functions
|
|
|
|
#region Class Implementation
|
|
|
|
public void Initialise(Block startingBlock, Inventory inventory, string Character) {
|
|
_currentBlock = startingBlock;
|
|
Inventory = inventory;
|
|
CharacterModel = Character;
|
|
}
|
|
|
|
|
|
public Vector3 yValue(float time, float heightMultiplier)
|
|
{
|
|
float y = Mathf.Sin((Mathf.PI*time)) * heightMultiplier;
|
|
return new Vector3(0, y, 0);
|
|
}
|
|
|
|
IEnumerator JumpCoroutine(Block Target, Transform Current, float time, float heightMax)
|
|
{
|
|
float elapsedTime = 0;
|
|
Vector3 startPosition = Current.position;
|
|
time *= 0.8f;
|
|
characterAnimator.Play("Jump Inplace");
|
|
yield return new WaitForSeconds(0.15f);
|
|
while (elapsedTime < time)
|
|
{
|
|
transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
|
|
transform.position += yValue((elapsedTime / time), heightMax);
|
|
yield return new WaitForEndOfFrame();
|
|
elapsedTime += Time.deltaTime;
|
|
}
|
|
transform.position = Target.VisualPosition;
|
|
}
|
|
|
|
IEnumerator MoveCoroutine(Block Target, Transform Current, float time, float heightMax)
|
|
{
|
|
float elapsedTime = 0;
|
|
Vector3 startPosition = Current.position;
|
|
time *= 0.8f;
|
|
characterAnimator.Play("Walk");
|
|
yield return new WaitForSeconds(0.05f);
|
|
while (elapsedTime < time)
|
|
{
|
|
|
|
transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
|
|
yield return new WaitForEndOfFrame();
|
|
elapsedTime += Time.deltaTime;
|
|
}
|
|
transform.position = Target.VisualPosition;
|
|
}
|
|
|
|
IEnumerator MoveDownCoroutine(Block Target, Transform Current, float time, float heightMax)
|
|
{
|
|
float elapsedTime = 0;
|
|
Vector3 startPosition = Current.position;
|
|
time *= 0.8f;
|
|
characterAnimator.Play("Walk");
|
|
while (elapsedTime < time)
|
|
{
|
|
transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
|
|
transform.position += yValue((elapsedTime / time), heightMax);
|
|
yield return new WaitForEndOfFrame();
|
|
elapsedTime += Time.deltaTime;
|
|
}
|
|
transform.position = Target.VisualPosition;
|
|
}
|
|
|
|
IEnumerator rotateCoroutine(Direction direction, Transform Current, float time, float heightMax)
|
|
{
|
|
float elapsedTime = 0;
|
|
time *= 0.8f;
|
|
Vector3 endDirection = direction.ToVector(Current);
|
|
Vector3 startDirection = Current.forward;
|
|
Vector3 startPosition = transform.position;
|
|
while (elapsedTime < time)
|
|
{
|
|
characterAnimator.Play("Jump");
|
|
transform.forward = Vector3.Slerp(startDirection, endDirection, (elapsedTime / time));
|
|
yield return new WaitForEndOfFrame();
|
|
elapsedTime += Time.deltaTime;
|
|
}
|
|
transform.forward = endDirection;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Moves one block in specefied direction, Can walk off obstacles
|
|
/// </summary>
|
|
/// <param name="direction">direction to walk</param>
|
|
/// <remarks>Technically is same as JumpLong(1) but kept seperate to avoid confusion</remarks>
|
|
public void Move(Direction direction, float speed)
|
|
{
|
|
//setting up variables
|
|
Vector3 position = _currentBlock.position + direction.ToVector(transform); // position wanted
|
|
Block hit; //output of block detection
|
|
Block moveTo = _currentBlock; //block we'll actually move to
|
|
|
|
//if move is obstucted no where to move
|
|
if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
|
|
return;
|
|
|
|
|
|
//If block at Position is walkable set it to moveTo
|
|
if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)){
|
|
moveTo = hit;
|
|
_currentBlock = moveTo;
|
|
StartCoroutine(MoveCoroutine(_currentBlock, transform, speed, 0.3f)); }
|
|
//else if block down one is walkable
|
|
else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)){
|
|
moveTo = hit;
|
|
_currentBlock = moveTo;
|
|
StartCoroutine(MoveDownCoroutine(_currentBlock, transform, speed, 0.3f));
|
|
}
|
|
//set current block && move
|
|
//CurrentBlock = moveTo;
|
|
//StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.3f));
|
|
//transform.position = CurrentBlock.VisualPosition;
|
|
}
|
|
|
|
/// <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)
|
|
{
|
|
collectable.OnCollect(this);
|
|
}
|
|
if (other.gameObject.name == "collect_sphere"){
|
|
other.gameObject.SetActive(false);
|
|
//player.collected +=1;
|
|
|
|
}
|
|
if (other.gameObject.name == "End Portal")
|
|
{
|
|
other.GetComponent<Collider>().enabled = false;
|
|
SceneManager.LoadScene(nextScene);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rotates to point in specific direction based on current direction
|
|
/// </summary>
|
|
/// <param name="direction">Local direction to point</param>
|
|
public void Rotate(Direction direction, float speed)
|
|
{
|
|
StartCoroutine(rotateCoroutine(direction, transform, speed, 0.15f));
|
|
//transform.forward = direction.ToVector(transform);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Jumps in specefied direction, picks between Long Jump and Jumping up
|
|
/// </summary>
|
|
/// <param name="direction">Direction to Jump</param>
|
|
public void Jump(Direction direction, float speed)
|
|
{
|
|
//if there is a block infront JumpUp else LongJump
|
|
if (Block.isBlockAtPosition(_currentBlock.position + direction.ToVector(transform) + Vector3.up, 1, ~Ignore))
|
|
JumpUp(direction, speed);
|
|
else
|
|
JumpLong(direction, speed);
|
|
}
|
|
|
|
#endregion Class Implementation
|
|
|
|
#region Private Functions
|
|
|
|
/// <summary>
|
|
/// Jumps up obstacle of specific height. Jumps as high as possible
|
|
/// </summary>
|
|
/// <param name="direction">Direction of obstacle</param>
|
|
/// <param name="height">max height</param>
|
|
private void JumpUp(Direction direction, float speed, int height = 1)
|
|
{
|
|
//setting up variables
|
|
Vector3 position; // position wanted
|
|
Block hit; //output of block detection
|
|
Block moveTo = _currentBlock; //block we'll actually move to
|
|
|
|
//Check blocks in going up then move to the heighest walkable one
|
|
for (int i = 0; i <= height; i++)
|
|
{
|
|
//next position up the tower
|
|
position = _currentBlock.position + direction.ToVector(transform) + (Vector3.up * i);
|
|
|
|
//if block is walkable set it to last known position
|
|
if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
|
|
moveTo = hit;
|
|
}
|
|
|
|
//set current block && move
|
|
_currentBlock = moveTo;
|
|
StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
|
|
//transform.position = CurrentBlock.VisualPosition;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Long jumps forward a specified distance. Can Jump gaps. Stops at obstruction
|
|
/// </summary>
|
|
/// <param name="direction">Direction to Jump</param>
|
|
/// <param name="Distance">Max distance</param>
|
|
private void JumpLong(Direction direction, float speed, int Distance = 2)
|
|
{
|
|
//setting up variables
|
|
Vector3 position; // position wanted
|
|
Block hit; //output of block detection
|
|
Block moveTo = _currentBlock; //block we'll actually move to
|
|
|
|
//Check blocks in front until we hit an obstruction or went the distance
|
|
for (int i = 1; i <= Distance; i++)
|
|
{
|
|
//Next position to MoveTo
|
|
position = _currentBlock.position + (direction.ToVector(transform) * i);
|
|
|
|
//if jump is obstructed, stop and go to last known block
|
|
if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
|
|
break;
|
|
|
|
|
|
//If block at Position is walkable set it to last known position
|
|
if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
|
|
moveTo = hit;
|
|
//else if block down one is walkable
|
|
else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
|
|
moveTo = hit;
|
|
|
|
}//end for
|
|
|
|
//Set Current Block and move
|
|
_currentBlock = moveTo;
|
|
StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
|
|
//transform.position = CurrentBlock.VisualPosition;
|
|
}
|
|
|
|
#endregion Private Functions
|
|
|
|
}
|