|
|
@ -103,6 +103,9 @@ public class Character : MonoBehaviour |
|
|
|
|
|
|
|
public IEnumerator MoveToBlock(Block target, Animation animation, float time) |
|
|
|
{ |
|
|
|
Block oldBlock = _currentBlock; |
|
|
|
|
|
|
|
_currentBlock.OnLeftByPlayer(this); |
|
|
|
|
|
|
|
System.Func<float, float> yFunction = null; |
|
|
|
if (animation == Animation.Jump) |
|
|
@ -113,6 +116,9 @@ public class Character : MonoBehaviour |
|
|
|
yield return StartCoroutine(LerpToBlock(target.VisualPosition, time, yFunction)); |
|
|
|
|
|
|
|
_currentBlock= target; |
|
|
|
_currentBlock.OnWalkedOnByPlayer(this); |
|
|
|
|
|
|
|
yield return StartCoroutine(DoPush(oldBlock,_currentBlock, time)); |
|
|
|
|
|
|
|
StopAnimation(animation); |
|
|
|
} |
|
|
@ -191,6 +197,49 @@ public class Character : MonoBehaviour |
|
|
|
transform.position = _startPos + Vector3.up * heightOffset(1); |
|
|
|
} |
|
|
|
|
|
|
|
public IEnumerator DoPush(Block lastBlock, Block currentBlock, float animationTime) |
|
|
|
{ |
|
|
|
//Direction player moved in ignoring Y value
|
|
|
|
Vector3 pushDirection = Vector3.ProjectOnPlane(currentBlock.position - lastBlock.position, Vector3.up).normalized; |
|
|
|
|
|
|
|
foreach(Character character in _currentBlock.GetPushablePlayers()) |
|
|
|
{ |
|
|
|
if (character == this) |
|
|
|
continue; |
|
|
|
|
|
|
|
yield return StartCoroutine(character.GetPushed(pushDirection)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public IEnumerator GetPushed(Vector3 direction) |
|
|
|
{ |
|
|
|
yield return null; |
|
|
|
} |
|
|
|
|
|
|
|
private Block getPushLocation(Vector3 pushDirection) |
|
|
|
{ |
|
|
|
//setting up variables
|
|
|
|
Vector3 position = _currentBlock.position + pushDirection; // position wanted
|
|
|
|
Block hit; //output of block detection
|
|
|
|
|
|
|
|
//if move is obstucted no where to move
|
|
|
|
if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore)) |
|
|
|
return _currentBlock; |
|
|
|
|
|
|
|
|
|
|
|
//If block at Position is walkable set it to moveTo
|
|
|
|
if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) |
|
|
|
{ |
|
|
|
return hit; |
|
|
|
} |
|
|
|
//else if block down one is walkable
|
|
|
|
else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) |
|
|
|
{ |
|
|
|
return hit; |
|
|
|
} |
|
|
|
return _currentBlock; |
|
|
|
} |
|
|
|
|
|
|
|
public void StartAnimation(Animation animation,float speed = 1) |
|
|
|
{ |
|
|
|
characterAnimator.SetFloat("AnimationSpeed", (1 / speed)); |
|
|
@ -237,6 +286,214 @@ public class Character : MonoBehaviour |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void respawnCharacter() |
|
|
|
{ |
|
|
|
/* Will introduce more complex criteria for choosing where to respawn the player in future |
|
|
|
* For now: if the square one back (x =- 1) from the pit is walkable and unoccupied, then put them there |
|
|
|
* Otherwise, try the next square back, etc, until we find an available one |
|
|
|
*/ |
|
|
|
|
|
|
|
Block currentBlock = null; |
|
|
|
//We start from the position of our pit, at ground level
|
|
|
|
Vector3 currentPos = new Vector3(this.transform.position.x, this.transform.position.y, this.transform.position.z); |
|
|
|
|
|
|
|
Debug.Log("Commencing respawn"); |
|
|
|
|
|
|
|
//Hardcoding the number of iterations for now for simplicity, should change this later
|
|
|
|
for (int i = 0; i < 100; i++) |
|
|
|
{ |
|
|
|
//First we check one back
|
|
|
|
currentPos.x -= 1; |
|
|
|
Debug.Log("currentPos = " + currentPos.x + ", " + currentPos.y + ", " + currentPos.z); |
|
|
|
if (Block.isBlockAtPosition(currentPos, 1, ~Ignore, out currentBlock)) //Does a block exist here?
|
|
|
|
{ |
|
|
|
Debug.Log("Block exists"); |
|
|
|
if (currentBlock.isWalkable(~Ignore)) //If so, can we walk on it?
|
|
|
|
{ |
|
|
|
Debug.Log("Block is walkable"); |
|
|
|
//Don't yet have a check for whether it's occupied
|
|
|
|
break; //If it is, we stop here
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//If the block one back isn't an option, we check to the left and right
|
|
|
|
currentPos.z += 1; |
|
|
|
Debug.Log("currentPos = " + currentPos.x + ", " + currentPos.y + ", " + currentPos.z); |
|
|
|
if (Block.isBlockAtPosition(currentPos, 1, ~Ignore, out currentBlock)) //Does a block exist here?
|
|
|
|
{ |
|
|
|
Debug.Log("Block exists"); |
|
|
|
if (currentBlock.isWalkable(~Ignore)) //If so, can we walk on it?
|
|
|
|
{ |
|
|
|
Debug.Log("Block is walkable"); |
|
|
|
//Don't yet have a check for whether it's occupied
|
|
|
|
break; //If it is, we stop here
|
|
|
|
} |
|
|
|
} |
|
|
|
currentPos.z -= 2; |
|
|
|
Debug.Log("currentPos = " + currentPos.x + ", " + currentPos.y + ", " + currentPos.z); |
|
|
|
if (Block.isBlockAtPosition(currentPos, 1, ~Ignore, out currentBlock)) //Does a block exist here?
|
|
|
|
{ |
|
|
|
Debug.Log("Block exists"); |
|
|
|
if (currentBlock.isWalkable(~Ignore)) //If so, can we walk on it?
|
|
|
|
{ |
|
|
|
Debug.Log("Block is walkable"); |
|
|
|
//Don't yet have a check for whether it's occupied
|
|
|
|
break; //If it is, we stop here
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//If we've gotten this far and haven't found an available spot, we move back a row and try again
|
|
|
|
currentPos.z += 1; |
|
|
|
} |
|
|
|
|
|
|
|
//Having found our target block, we move the character there
|
|
|
|
if (currentBlock != null) |
|
|
|
{ |
|
|
|
this.transform.position = currentBlock.VisualPosition; |
|
|
|
this.inPit = false; |
|
|
|
this._currentBlock = currentBlock; |
|
|
|
Debug.Log("Moved " + this.name + " to " |
|
|
|
+ this.transform.position.x + ", " |
|
|
|
+ this.transform.position.y + ", " |
|
|
|
+ this.transform.position.z + ", " |
|
|
|
+ " inPit = " + inPit); |
|
|
|
} |
|
|
|
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) |
|
|
|
{ |
|
|
|
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);
|
|
|
|
} |
|
|
|
public void RotateHalf(Direction direction, float speed) |
|
|
|
{ |
|
|
|
StartCoroutine(rotateHalfCoroutine(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
|
|
|
|
|
|
|
|
#region Depricated
|
|
|
|
IEnumerator JumpCoroutine(Block Target, Transform Current, float time, float heightMax) |
|
|
|
{ |
|
|
|
float elapsedTime = 0; |
|
|
@ -515,210 +772,6 @@ public class Character : MonoBehaviour |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void respawnCharacter() |
|
|
|
{ |
|
|
|
/* Will introduce more complex criteria for choosing where to respawn the player in future |
|
|
|
* For now: if the square one back (x =- 1) from the pit is walkable and unoccupied, then put them there |
|
|
|
* Otherwise, try the next square back, etc, until we find an available one |
|
|
|
*/ |
|
|
|
|
|
|
|
Block currentBlock = null; |
|
|
|
//We start from the position of our pit, at ground level
|
|
|
|
Vector3 currentPos = new Vector3(this.transform.position.x, this.transform.position.y, this.transform.position.z); |
|
|
|
|
|
|
|
Debug.Log("Commencing respawn"); |
|
|
|
|
|
|
|
//Hardcoding the number of iterations for now for simplicity, should change this later
|
|
|
|
for (int i = 0; i < 100; i++) |
|
|
|
{ |
|
|
|
//First we check one back
|
|
|
|
currentPos.x -= 1; |
|
|
|
Debug.Log("currentPos = " + currentPos.x + ", " + currentPos.y + ", " + currentPos.z); |
|
|
|
if (Block.isBlockAtPosition(currentPos, 1, ~Ignore, out currentBlock)) //Does a block exist here?
|
|
|
|
{ |
|
|
|
Debug.Log("Block exists"); |
|
|
|
if (currentBlock.isWalkable(~Ignore)) //If so, can we walk on it?
|
|
|
|
{ |
|
|
|
Debug.Log("Block is walkable"); |
|
|
|
//Don't yet have a check for whether it's occupied
|
|
|
|
break; //If it is, we stop here
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//If the block one back isn't an option, we check to the left and right
|
|
|
|
currentPos.z += 1; |
|
|
|
Debug.Log("currentPos = " + currentPos.x + ", " + currentPos.y + ", " + currentPos.z); |
|
|
|
if (Block.isBlockAtPosition(currentPos, 1, ~Ignore, out currentBlock)) //Does a block exist here?
|
|
|
|
{ |
|
|
|
Debug.Log("Block exists"); |
|
|
|
if (currentBlock.isWalkable(~Ignore)) //If so, can we walk on it?
|
|
|
|
{ |
|
|
|
Debug.Log("Block is walkable"); |
|
|
|
//Don't yet have a check for whether it's occupied
|
|
|
|
break; //If it is, we stop here
|
|
|
|
} |
|
|
|
} |
|
|
|
currentPos.z -= 2; |
|
|
|
Debug.Log("currentPos = " + currentPos.x + ", " + currentPos.y + ", " + currentPos.z); |
|
|
|
if (Block.isBlockAtPosition(currentPos, 1, ~Ignore, out currentBlock)) //Does a block exist here?
|
|
|
|
{ |
|
|
|
Debug.Log("Block exists"); |
|
|
|
if (currentBlock.isWalkable(~Ignore)) //If so, can we walk on it?
|
|
|
|
{ |
|
|
|
Debug.Log("Block is walkable"); |
|
|
|
//Don't yet have a check for whether it's occupied
|
|
|
|
break; //If it is, we stop here
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//If we've gotten this far and haven't found an available spot, we move back a row and try again
|
|
|
|
currentPos.z += 1; |
|
|
|
} |
|
|
|
|
|
|
|
//Having found our target block, we move the character there
|
|
|
|
if (currentBlock != null) |
|
|
|
{ |
|
|
|
this.transform.position = currentBlock.VisualPosition; |
|
|
|
this.inPit = false; |
|
|
|
this._currentBlock = currentBlock; |
|
|
|
Debug.Log("Moved " + this.name + " to " |
|
|
|
+ this.transform.position.x + ", " |
|
|
|
+ this.transform.position.y + ", " |
|
|
|
+ this.transform.position.z + ", " |
|
|
|
+ " inPit = " + inPit); |
|
|
|
} |
|
|
|
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) |
|
|
|
{ |
|
|
|
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);
|
|
|
|
} |
|
|
|
public void RotateHalf(Direction direction, float speed) |
|
|
|
{ |
|
|
|
StartCoroutine(rotateHalfCoroutine(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
|
|
|
|
#endregion Depricated
|
|
|
|
|
|
|
|
} |