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; } }