aboutsummaryrefslogtreecommitdiffstats
path: root/Assets/Scripts/CharacterController2D.cs
diff options
context:
space:
mode:
authorToby Vincent <tobyv13@gmail.com>2022-04-08 17:24:16 -0500
committerToby Vincent <tobyv13@gmail.com>2022-04-08 17:24:16 -0500
commitfb2703b646d22bd4502fab6f0ca58cb922d1ed2c (patch)
tree37a9584cd0d194082749161fef417cc4c4e965fe /Assets/Scripts/CharacterController2D.cs
parenta16d177920a16d4364e0b1ceff8dc7639ba6ca17 (diff)
wip: no regerts
fix jump; race condition(ish) in jump/fall/land events (?) impl trigger animations on events refactor control, (follow) camera, anim handlers into interfaces impl controller pattern for controls (FSM using lambdas + interfaces) come up with the rest of the todos
Diffstat (limited to 'Assets/Scripts/CharacterController2D.cs')
-rw-r--r--Assets/Scripts/CharacterController2D.cs154
1 files changed, 154 insertions, 0 deletions
diff --git a/Assets/Scripts/CharacterController2D.cs b/Assets/Scripts/CharacterController2D.cs
new file mode 100644
index 0000000..bf62498
--- /dev/null
+++ b/Assets/Scripts/CharacterController2D.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections;
+using UnityEngine;
+using UnityEngine.Events;
+
+[RequireComponent(typeof(Rigidbody2D))]
+[RequireComponent(typeof(CapsuleCollider2D))]
+
+public class CharacterController2D : MonoBehaviour
+{
+ public enum Direction
+ {
+ left = -1,
+ right = 1
+ }
+
+ [SerializeField] Camera mainCamera;
+ [SerializeField] float acceleration = 40f;
+ [SerializeField][Range(0, .3f)] float smoothing = .05f;
+ [SerializeField] float gravityScale = 1.5f;
+ [SerializeField] float jumpForce = 50f;
+ [SerializeField] int maxJumpCount = 1;
+ [SerializeField] bool airControl = true;
+
+ internal UnityEvent OnIdleEvent;
+ internal UnityEvent OnFlip;
+ internal UnityEvent OnJump;
+ internal UnityEvent OnLand;
+ internal UnityEvent OnFall;
+
+ public Direction direction = Direction.right;
+ public Vector2 velocity = Vector2.zero;
+ public int jumpCount = 0;
+ public bool isGrounded = false;
+ public Vector3 cameraPos;
+ public Rigidbody2D _rigidBody;
+ public CapsuleCollider2D _collider;
+ public Transform _transform;
+
+ void Awake()
+ {
+ _rigidBody = GetComponent<Rigidbody2D>();
+ _collider = GetComponent<CapsuleCollider2D>();
+ OnIdleEvent ??= new UnityEvent();
+ OnFlip ??= new UnityEvent();
+ OnJump ??= new UnityEvent();
+ OnFall ??= new UnityEvent();
+ OnLand ??= new UnityEvent();
+ }
+
+ // Use this for initialization
+ void Start()
+ {
+ _transform = transform;
+ _rigidBody.freezeRotation = true;
+ _rigidBody.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
+ _rigidBody.gravityScale = gravityScale;
+ direction = (Direction)(_transform.localScale.x / Mathf.Abs(_transform.localScale.x));
+
+ jumpCount = maxJumpCount;
+
+ if (mainCamera)
+ cameraPos = mainCamera.transform.position;
+
+ OnFlip.AddListener(HandleFlip);
+ OnJump.AddListener(HandleJump);
+ OnFall.AddListener(HandleFall);
+ OnLand.AddListener(HandleLand);
+ }
+
+ void Update()
+ {
+ if (isGrounded || airControl)
+ HandleHorzInput(Input.GetAxisRaw("Horizontal"));
+
+ // Changing this to `canJump` or `jumpCount > 0` would allow for things like double jumping.
+ if (jumpCount > 0 && Input.GetButtonDown("Jump"))
+ OnJump.Invoke();
+
+
+ if (mainCamera)
+ {
+ var targetPos = new Vector3(_transform.position.x, cameraPos.y, cameraPos.z);
+ mainCamera.transform.position = Vector3.Lerp(mainCamera.transform.position, targetPos, 0.25f);
+ }
+ }
+
+ void FixedUpdate()
+ {
+ CheckCollision();
+ }
+
+ public void Move(float magnitude)
+ {
+ Vector3 targetVelocity = new Vector2(magnitude, _rigidBody.velocity.y);
+ _rigidBody.velocity = Vector2.SmoothDamp(_rigidBody.velocity, targetVelocity, ref velocity, smoothing);
+ }
+
+ void CheckCollision()
+ {
+ var evnt = isGrounded ? OnFall : OnLand;
+
+ float colliderRadius = _collider.size.x * 0.4f * Mathf.Abs(transform.localScale.x);
+ Vector3 groundCheckPos = new Vector3(_collider.bounds.size.x * 0.5f, colliderRadius * 0.9f, 0) + _collider.bounds.min;
+ Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckPos, colliderRadius);
+
+ if (Array.Exists(colliders, c => c != _collider))
+ {
+ Debug.Log(Array.Find(colliders, c => c != _collider));
+ evnt.Invoke();
+ }
+ }
+
+ void HandleHorzInput(float horzInput)
+ {
+ Move(horzInput * acceleration);
+
+ if (horzInput * (int)direction < 0)
+ OnFlip.Invoke();
+ }
+
+
+ void HandleFlip()
+ {
+ Debug.Log("Flipping");
+ Vector3 theScale = transform.localScale;
+ theScale.x *= -1;
+ transform.localScale = theScale;
+
+ direction = direction == Direction.left ? Direction.right : Direction.left;
+ }
+
+ void HandleJump()
+ {
+ Debug.Log("Jumping");
+ jumpCount--;
+ _rigidBody.AddForce(Vector2.up * jumpForce);
+ OnFall.Invoke();
+ }
+
+
+ void HandleFall()
+ {
+ Debug.Log("Falling");
+ isGrounded = false;
+ }
+
+ void HandleLand()
+ {
+ Debug.Log("Landing");
+ isGrounded = true;
+ jumpCount = maxJumpCount;
+ }
+}