using System;
using System.Collections;
using System.Collections.Generic;
using PlayerInput;
using UnityEngine;
using UnityEngine.SceneManagement;
[SelectionBase]
public class PlayerController : MonoBehaviour {
public float Speed = 5;
public float Gravity = 7;
public enum State
{
Walking,
Raking,
MakingPile
}
private State state = State.Walking;
private int leafLayer = 0;
private CharacterController charC;
private AnimationHandler anim;
// Use this for initialization
void Start () {
charC = GetComponent<CharacterController>();
anim = GetComponent<AnimationHandler>();
rakeTimer = new SimpleTimer();
rakeBackTween = new SimpleTween();
oldPos = transform.position;
leafLayer = LayerMask.GetMask("leaf");
}
private float velY = 0;
public float RunCycleTime = 0.8f;
public float RunFrameTime = 0.3f;
public float RunFrameSpeedBoost = 1.4f;
private float runCycle = 0.0f;
public float PushRadius = 0.6f;
public float PushForce = 300.0f;
public float PushPower = 2.0f;
private float rakeTime = 0.0f;
public float TimeToPushRake = 0.3f;
private SimpleTimer rakeTimer;
private Vector3 rakeDir = new Vector2();
private Vector3 oldPos = new Vector3();
private Vector3 playerDir = new Vector3();
public int[] LeafsForPile;
private AnimationHandler.Direction rakeAnimDir = AnimationHandler.Direction.UpRight;
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.F5))
{
Scene scene = SceneManager.GetActiveScene();
SceneManager.LoadScene(scene.name);
}
Vector3 dir = new Vector3();
if (input != null)
{
if (charC.isGrounded && state == State.Walking)
{
dir.x = input.Axis(InputSource<PlayerController>.InputAxis.MoveX);
dir.z = input.Axis(InputSource<PlayerController>.InputAxis.MoveY);
if (dir.magnitude > 0.3f)
{
dir.Normalize();
playerDir.x = dir.x;
playerDir.z = dir.z;
float speed = Speed;
if (runCycle < RunFrameTime)
{
speed *= RunFrameSpeedBoost;
}
dir *= speed;
float angle = Mathf.Atan2(dir.z, dir.x);
if (angle < 0) angle += Mathf.PI * 2;
if (angle < Mathf.PI / 2.0f) anim.SetDir(AnimationHandler.Direction.UpRight);
if (angle < Mathf.PI && angle >= Mathf.PI / 2.0f) anim.SetDir(AnimationHandler.Direction.UpLeft);
if (angle < Mathf.PI * 3.0f / 2.0f && angle >= Mathf.PI) anim.SetDir(AnimationHandler.Direction.DownLeft);
if (angle >= Mathf.PI * 3.0f / 2.0f) anim.SetDir(AnimationHandler.Direction.DownRight);
//Debug.Log("ANGLE: " + angle);
runCycle += Time.deltaTime;
while (runCycle >= RunCycleTime)
{
runCycle -= RunCycleTime;
}
int frame = ((int)Mathf.Floor(runCycle / RunCycleTime * 4.0f) + 1) % 4; //< RunFrameTime ? 1 : 0;
anim.SetFrame(frame);
}
else
{
dir.x = 0;
dir.z = 0;
anim.SetFrame(0);
runCycle = 0.0f;
}
}
}
if (state == State.Walking)
{
dir.y = velY;
velY -= Gravity * Time.deltaTime;
gameObject.layer = LayerMask.NameToLayer("player_controller_no_collide");
charC.Move(dir * Time.deltaTime);
gameObject.layer = LayerMask.NameToLayer("player_controller");
if (charC.isGrounded)
{
velY = 0;
}
Vector3 moved = transform.position - oldPos;
if (moved.magnitude > 0.7f * Time.deltaTime)
{
foreach (Collider c in Physics.OverlapSphere(transform.position, PushRadius, leafLayer))
{
LeafPhysics leaf = c.GetComponentInParent<LeafPhysics>();
if (leaf != null)
{
Vector3 toLeaf = leaf.transform.position - transform.position;
float dist = toLeaf.magnitude;
float power = Mathf.Pow(1.0f - dist / PushRadius, PushPower) * Time.deltaTime * PushForce;
//toLeaf.Normalize();
toLeaf.y += UnityEngine.Random.Range(0.4f, 1.0f);
leaf.Body.AddForce(toLeaf * (9.0f + UnityEngine.Random.Range(0, 9.0f)) * power * Time.deltaTime * 60);
}
}
}
Vector3 localRakeDir = new Vector3(input.Axis(InputSource<PlayerController>.InputAxis.RakeX), 0, input.Axis(InputSource<PlayerController>.InputAxis.RakeY));
if (localRakeDir.magnitude < 0.2f)
{
rakeTime = 0;
}
else
{
if (rakeTime >= 0)
{
rakeTime += Time.deltaTime;
}
}
if (rakeTime >= 0 && localRakeDir.magnitude > 0.7f && rakeTime < TimeToPushRake)
{
playerDir = -localRakeDir;
rakeDir = localRakeDir;
state = State.Raking;
float angle = Mathf.Atan2(-rakeDir.z, -rakeDir.x);
if (angle < 0) angle += Mathf.PI * 2;
rakeAnimDir = AnimationHandler.Direction.UpRight;
if (angle < Mathf.PI / 2.0f) rakeAnimDir = AnimationHandler.Direction.UpRight;
if (angle < Mathf.PI && angle >= Mathf.PI / 2.0f) rakeAnimDir = AnimationHandler.Direction.UpLeft;
if (angle < Mathf.PI * 3.0f / 2.0f && angle >= Mathf.PI) rakeAnimDir = AnimationHandler.Direction.DownLeft;
if (angle >= Mathf.PI * 3.0f / 2.0f) rakeAnimDir = AnimationHandler.Direction.DownRight;
rakeTime = -1;
anim.SetState("Rake", rakeAnimDir, 0);
rakeTimer.Start(0.15f, Rake);
}
if (state == State.Walking && input.ButtonPressedThisFrame(InputSource<PlayerController>.InputButton.MakePile))
{
rakeDir = playerDir;
state = State.MakingPile;
float angle = Mathf.Atan2(rakeDir.z, rakeDir.x);
if (angle < 0) angle += Mathf.PI * 2;
rakeAnimDir = AnimationHandler.Direction.UpRight;
if (angle < Mathf.PI / 2.0f) rakeAnimDir = AnimationHandler.Direction.UpRight;
if (angle < Mathf.PI && angle >= Mathf.PI / 2.0f) rakeAnimDir = AnimationHandler.Direction.UpLeft;
if (angle < Mathf.PI * 3.0f / 2.0f && angle >= Mathf.PI) rakeAnimDir = AnimationHandler.Direction.DownLeft;
if (angle >= Mathf.PI * 3.0f / 2.0f) rakeAnimDir = AnimationHandler.Direction.DownRight;
rakeTime = -1;
anim.SetState("Rake", rakeAnimDir, 0);
rakeTimer.Start(0.175f, () =>
{
anim.SetState("Rake", rakeAnimDir, 1);
rakeTimer.Start(0.175f, MakePile);
});
}
}
oldPos = transform.position;
}
public float RakeBackDist = 0.8f;
public float RakeBackTime = 0.2f;
private SimpleTween rakeBackTween;
private Vector3 rakeBackStart = new Vector3();
private Vector3 rakeBackEnd = new Vector3();
public float RakeReachDist = 0.6f;
public float RakeReachRadius = 0.6f;
public float RakeFlyForce = 100;
private void Rake()
{
anim.SetState("Rake", rakeAnimDir, 1);
Vector3 rakeMove = rakeDir * RakeBackDist;
rakeBackStart = transform.position;
charC.Move(rakeMove);
rakeBackEnd = transform.position;
transform.position = rakeBackStart;
rakeBackTween.Init(UpdateRakeBack, SimpleTween.QuadEaseInOut, 0, 1, RakeBackTime);
rakeBackTween.OnFinish = FinishedRake;
List<LeafPhysics> leafs = new List<LeafPhysics>();
int layer = LayerMask.GetMask("leaf");
foreach (Collider col in Physics.OverlapSphere(rakeBackStart - rakeDir * RakeReachDist, RakeReachRadius, layer))
{
LeafPhysics leaf = col.GetComponentInParent<LeafPhysics>();
if (leaf != null)
{
leafs.Add(leaf);
}
}
foreach (LeafPhysics leaf in leafs)
{
float rand = UnityEngine.Random.Range(0, 1.0f);
Vector3 startPos = leaf.transform.position;
Vector3 toLeaf = startPos - transform.position;
float dist = Vector3.Dot(toLeaf, -rakeDir);
dist += UnityEngine.Random.Range(-0.1f, 0.1f);
Vector3 pull = rakeDir * dist;
if (rand < 0.65f)
{
// pull the leaf back, and then destroy
leaf.Body.isKinematic = true;
pull.x += UnityEngine.Random.Range(-0.05f, 0.05f);
pull.z += UnityEngine.Random.Range(-0.05f, 0.05f);
pull = pull * 0.5f + toLeaf.normalized * -0.5f * dist;
float pullTime = RakeBackTime + UnityEngine.Random.Range(-0.04f, 0.04f);
SimpleTween tween = new SimpleTween(v =>
{
if (leaf != null)
{
leaf.transform.position = startPos + pull * v;
}
}, SimpleTween.TweenType.EaseLinear, 0, 1, pullTime);
tween.OnFinish = () =>
{
if (leaf != null)
{
leaf.Body.isKinematic = false;
}
//GameObject.Destroy(leaf.gameObject);
};
}
else if (rand < 0.83f)
{
pull.Normalize();
pull = Quaternion.Euler(UnityEngine.Random.Range(-30.0f, 30.0f), UnityEngine.Random.Range(-30.0f, 30.0f), UnityEngine.Random.Range(-30.0f, 30.0f)) * pull;
pull.y += 0.3f;
leaf.Body.AddForce(pull * RakeFlyForce, ForceMode.Impulse);
}
else
{
}
}
}
public Pile PilePrefab;
public float PileSearchRadius = 0.7f;
private List<LeafPhysics> potentialPile = new List<LeafPhysics>();
private void MakePile()
{
anim.SetState("Stand", anim.Dir, 0);
potentialPile.Clear();
foreach (Collider c in Physics.OverlapSphere(transform.position + rakeDir * RakeReachDist, PileSearchRadius, leafLayer))
{
LeafPhysics leaf = c.GetComponentInParent<LeafPhysics>();
if (leaf != null)
{
potentialPile.Add(leaf);
}
}
int numLeaves = potentialPile.Count;
bool madePile = false;
for (int i = LeafsForPile.Length - 1; i >= 0; i--)
{
if (numLeaves >= LeafsForPile[i])
{
if (UnityEngine.Random.Range(0, 1.0f) < 0.15f)
{
i--;
if (i < 0) break;
numLeaves = LeafsForPile[i] - 1;
}
float pileScale = (float)i / (LeafsForPile.Length - 1) + 0.4f;
Pile pile = Instantiate<Pile>(PilePrefab);
pile.NumLeaves = numLeaves;
pile.InitialPop = pileScale;
pile.transform.position = transform.position + rakeDir * RakeReachDist + new Vector3(UnityEngine.Random.Range(-0.1f, 0.1f), 0, UnityEngine.Random.Range(-0.1f, 0.1f));
madePile = true;
break;
}
}
if (madePile)
{
foreach (LeafPhysics leaf in potentialPile)
{
if (UnityEngine.Random.Range(0, 1f) < 0.8f)
{
leaf.FadeOut(0.3f);
}
}
}
else
{
foreach (LeafPhysics leaf in potentialPile)
{
leaf.Body.AddForce(new Vector3(UnityEngine.Random.Range(-2, 2), 0, UnityEngine.Random.Range(-2, 2)), ForceMode.Impulse);
}
}
FinishedRake();
}
private void FinishedRake()
{
state = State.Walking;
anim.SetState("Stand", anim.Dir, 0);
}
private void UpdateRakeBack(float val)
{
Vector3 pos = transform.position;
pos.x = rakeBackStart.x * (1 - val) + rakeBackEnd.x * val;
pos.z = rakeBackStart.z * (1 - val) + rakeBackEnd.z * val;
transform.position = pos;
}
private InputSource<PlayerController> input = null;
private InputManager.PlayerInfo playerInfo;
public void SetInput(InputSource<PlayerController> newPlayerInput, InputManager.PlayerInfo playerInfo)
{
this.input = newPlayerInput;
this.playerInfo = playerInfo;
}
}