diff --git a/Assets/Prefabs/Trick.prefab b/Assets/Prefabs/Trick.prefab index abf6bb5..abc688a 100644 --- a/Assets/Prefabs/Trick.prefab +++ b/Assets/Prefabs/Trick.prefab @@ -189,8 +189,6 @@ MonoBehaviour: avoidPlayerRadius: 0 avoidTrickRadius: 0 treatSeekWeight: 1 - avoidPlayerWeight: 0 - avoidTrickWeight: 0 wanderWeight: 0.4 maxTricks: 50 jumpImpulse: 6 diff --git a/Assets/Scripts/PlayerPickupController.cs b/Assets/Scripts/PlayerPickupController.cs index 6f50eb8..6a869ed 100644 --- a/Assets/Scripts/PlayerPickupController.cs +++ b/Assets/Scripts/PlayerPickupController.cs @@ -12,15 +12,24 @@ public class PlayerPickupController : MonoBehaviour [SerializeField] private string controlSchemeName = ""; [SerializeField] private int gamepadIndex = -1; private bool deviceFilterEnabled; + [SerializeField] private float minThrowSpeed = 6f; + [SerializeField] private float maxThrowSpeed = 20f; + [SerializeField] private float throwChargeTime = 0.75f; + [SerializeField] private float throwUpwardForce = 0f; + [SerializeField] private float throwTriggerThreshold = 0.6f; [Header("Setup")] public Transform holdPoint; // Empty GameObject above head public float pickupRange = 2.0f; private GameObject heldObject; + private PlayerPlatformerController platformerController; + private bool isChargingThrow; + private float throwChargeStartTime; private void OnEnable() { + platformerController = GetComponent(); if (inputActions == null) { Debug.LogError("PlayerPickupController missing InputActionAsset reference.", this); @@ -61,6 +70,7 @@ public class PlayerPickupController : MonoBehaviour } InputSystem.onDeviceChange -= HandleDeviceChange; + platformerController = null; } private void OnInteractPerformed(InputAction.CallbackContext context) @@ -69,13 +79,46 @@ public class PlayerPickupController : MonoBehaviour if(heldObject != null) { Debug.Log("Dropping held object"); - DropObject(); + DropObject(false); return; } TryPickUp(); } + private void Update() + { + if (heldObject == null) + { + return; + } + + if (!heldObject.TryGetComponent(out _)) + { + return; + } + + var gamepad = GetGamepad(); + if (gamepad == null) + { + return; + } + + var triggerValue = gamepad.rightTrigger.ReadValue(); + if (triggerValue >= throwTriggerThreshold) + { + if (!isChargingThrow) + { + isChargingThrow = true; + throwChargeStartTime = Time.time; + } + } + else if (isChargingThrow) + { + DropObject(true); + } + } + void TryPickUp() { // Find all colliders within range @@ -129,17 +172,22 @@ public class PlayerPickupController : MonoBehaviour } } - void DropObject() + void DropObject(bool applyThrow) { // Re-enable physics if (heldObject.TryGetComponent(out Rigidbody2D rb)) { rb.bodyType = RigidbodyType2D.Dynamic; rb.gravityScale = 1; + rb.linearVelocity = Vector2.zero; } if (heldObject.TryGetComponent(out var trick)) { trick.SetCarried(false); + if (applyThrow) + { + trick.OnThrown(); + } } if (heldObject.TryGetComponent(out var playerController)) { @@ -149,12 +197,52 @@ public class PlayerPickupController : MonoBehaviour heldPickup.enabled = true; } } + if (applyThrow && heldObject.TryGetComponent(out Rigidbody2D throwBody)) + { + var direction = 1f; + if (platformerController != null && Mathf.Abs(platformerController.LastMoveX) > 0.01f) + { + direction = Mathf.Sign(platformerController.LastMoveX); + } + var charge01 = 1f; + if (isChargingThrow) + { + var heldTime = Time.time - throwChargeStartTime; + charge01 = Mathf.Clamp01(heldTime / Mathf.Max(0.01f, throwChargeTime)); + } + var throwSpeed = Mathf.Lerp(minThrowSpeed, maxThrowSpeed, charge01); + throwBody.linearVelocity = new Vector2(direction * throwSpeed, 0f); + throwBody.angularVelocity = 0f; + } Collider2D col = heldObject.GetComponent(); if (col != null) col.enabled = true; // Unparent heldObject.transform.SetParent(null); heldObject = null; + isChargingThrow = false; + } + + private Gamepad GetGamepad() + { + if (runtimeActions == null) + { + return null; + } + + var devices = runtimeActions.devices; + if (devices != null) + { + foreach (var device in devices) + { + if (device is Gamepad gamepad) + { + return gamepad; + } + } + } + + return Gamepad.current; } private bool ShouldFilterDevices() diff --git a/Assets/Scripts/PlayerPlatformerController.cs b/Assets/Scripts/PlayerPlatformerController.cs index 2562486..97d4962 100644 --- a/Assets/Scripts/PlayerPlatformerController.cs +++ b/Assets/Scripts/PlayerPlatformerController.cs @@ -22,6 +22,7 @@ public class PlayerPlatformerController : MonoBehaviour private InputActionAsset runtimeActions; private InputAction moveAction; private InputAction jumpAction; + public float LastMoveX { get; private set; } private bool deviceFilterEnabled; private void Awake() @@ -86,6 +87,10 @@ public class PlayerPlatformerController : MonoBehaviour } var input = moveAction.ReadValue(); + if (Mathf.Abs(input.x) > 0.01f) + { + LastMoveX = input.x; + } var velocity = body.linearVelocity; velocity.x = input.x * moveSpeed; body.linearVelocity = velocity; diff --git a/Assets/Scripts/TrickController.cs b/Assets/Scripts/TrickController.cs index 080a470..f1775d2 100644 --- a/Assets/Scripts/TrickController.cs +++ b/Assets/Scripts/TrickController.cs @@ -22,8 +22,6 @@ public class TrickController : MonoBehaviour [SerializeField] private TrickController trickPrefab; [SerializeField] private float avoidPlayerRadius = 1.2f; [SerializeField] private float treatSeekWeight = 1f; - [SerializeField] private float avoidPlayerWeight = 0.25f; - [SerializeField] private float avoidTrickWeight = 0.2f; [SerializeField] private float wanderWeight = 0.4f; [SerializeField] private int maxTricks = 50; [SerializeField] private float jumpImpulse = 6f; @@ -34,6 +32,7 @@ public class TrickController : MonoBehaviour [SerializeField] private float despawnMinX = -12f; [SerializeField] private float despawnMaxX = 12f; [SerializeField] private float despawnMinY = -10f; + [SerializeField] private float throwControlLockTime = 0.35f; private Rigidbody2D body; private Transform target; @@ -44,6 +43,7 @@ public class TrickController : MonoBehaviour private float nextConsumeTime; private float desiredXVelocity; private float nextJumpTime; + private float movementLockUntil; private void Awake() { @@ -121,6 +121,11 @@ public class TrickController : MonoBehaviour return; } + if (Time.time < movementLockUntil) + { + return; + } + if (!IsGrounded()) { var airborne = body.linearVelocity; @@ -379,4 +384,9 @@ public class TrickController : MonoBehaviour } } } + + public void OnThrown() + { + movementLockUntil = Time.time + throwControlLockTime; + } }