diff --git a/Assets/Resources/SpaceRaceInput.inputactions b/Assets/Resources/SpaceRaceInput.inputactions index bf7896a..97f81bd 100755 --- a/Assets/Resources/SpaceRaceInput.inputactions +++ b/Assets/Resources/SpaceRaceInput.inputactions @@ -354,7 +354,7 @@ "name": "", "id": "448824b6-c8b3-47ec-b7f7-0123f90cf5f6", "path": "/1", - "interactions": "", + "interactions": "Press", "processors": "", "groups": "", "action": "powerUnit1", @@ -365,7 +365,7 @@ "name": "", "id": "18e2e44e-8735-45ce-aad2-b75c212fc4dc", "path": "/2", - "interactions": "", + "interactions": "Press", "processors": "", "groups": "", "action": "powerUnit2", @@ -376,7 +376,7 @@ "name": "", "id": "46351ee7-55d7-428d-9778-6ffd51bc663c", "path": "/3", - "interactions": "", + "interactions": "Press", "processors": "", "groups": "", "action": "powerUnit3", @@ -387,7 +387,7 @@ "name": "", "id": "e36dc262-5e19-467b-9153-98f8795b3752", "path": "/4", - "interactions": "", + "interactions": "Press", "processors": "", "groups": "", "action": "powerUnit4", diff --git a/Assets/Scenes/sr_star_fraenkel_zermelo/sr_star_fraenkel_zermelo.unity b/Assets/Scenes/sr_star_fraenkel_zermelo/sr_star_fraenkel_zermelo.unity index 1bd8d3e..71e0cb4 100644 --- a/Assets/Scenes/sr_star_fraenkel_zermelo/sr_star_fraenkel_zermelo.unity +++ b/Assets/Scenes/sr_star_fraenkel_zermelo/sr_star_fraenkel_zermelo.unity @@ -232,6 +232,46 @@ PrefabInstance: propertyPath: m_IsActive value: 1 objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_NotificationBehavior + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.size + value: 11 + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[7].m_ActionId + value: 7871c83b-4bda-4ee4-8128-ed5cd975ff95 + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[8].m_ActionId + value: e82aecf6-6941-44ee-b67e-fc4e55837abe + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[9].m_ActionId + value: 09c2221d-dc0e-46d0-9bdf-8e66b25b0e83 + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[10].m_ActionId + value: 49bf2fe6-f03b-4dec-9dd9-e571a9ae3e90 + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[7].m_ActionName + value: ship/powerUnit1[/Keyboard/1] + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[8].m_ActionName + value: ship/powerUnit2[/Keyboard/2] + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[9].m_ActionName + value: ship/powerUnit3[/Keyboard/3] + objectReference: {fileID: 0} + - target: {fileID: 5993260185458565267, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} + propertyPath: m_ActionEvents.Array.data[10].m_ActionName + value: ship/powerUnit4[/Keyboard/4] + objectReference: {fileID: 0} - target: {fileID: 8925193253056788144, guid: 217f9c8f922f2d41cac52c3699bde478, type: 3} propertyPath: m_Name value: Ship diff --git a/Assets/Src/PowerUnit.cs b/Assets/Src/PowerUnit.cs index 6b89d23..f14f8b3 100644 --- a/Assets/Src/PowerUnit.cs +++ b/Assets/Src/PowerUnit.cs @@ -1,45 +1,118 @@ using System; using UnityEngine; +public enum Output { + Acceleration, + Deceleration, + Strafing, + Shield, +} + public class PowerUnit { static float baseOutput = 25.0f; + static float initialAcceleration = 2f * baseOutput; + static float initialDeceleration = 4f * baseOutput; + static float initialStrafing = 1f * baseOutput; - float acceleration = 2f * baseOutput; - float deceleration = 4f * baseOutput; - float strafing = 1f * baseOutput; - float stablisation = 75f; + float acceleration = initialAcceleration; + float deceleration = initialDeceleration; + float strafing = initialStrafing; - float shieldsCurrent = 5000f; - float shieldsMax = 5000f; - float shieldsRegen = 10f; // * 100 ticks per second = 5s fully recharge + static float initialShieldMax = 5000f; + float shieldCurrent = initialShieldMax; + float shieldMax = initialShieldMax; + float shieldRegen = 10f; // * 100 ticks per second = 5s fully recharge + + int boostMax = 2; + int boostCharges = 0; + + static float stablisation = 75f; public float Acceleration => acceleration; public float Deceleration => deceleration; public float Strafing => strafing; - public float Shields => shieldsCurrent; - public float ShieldsMax => shieldsMax; + public float Shield => shieldCurrent; + public float ShieldMax => shieldMax; public float Stabilisation => stablisation; - public string ShieldsPct => $"{((shieldsCurrent / shieldsMax) * 100f):0}"; + public string ShieldPct => $"{((shieldCurrent / shieldMax) * 100f):0}"; + public string BoostsAvailable => $"{boostCharges}"; public void Init() { - shieldsCurrent = shieldsMax; - shieldsRegen = (shieldsMax / 5f) * Time.fixedDeltaTime; + boostCharges = 0; + shieldCurrent = initialShieldMax; + acceleration = initialAcceleration; + deceleration = initialDeceleration; + strafing = initialStrafing; } - public void Reassign(float accel, float decel, float strafe) { - acceleration = baseOutput * accel; - deceleration = baseOutput * decel; - strafing = baseOutput * strafe; + // Regeneration of boosts is tracked by the ShipControls + // it has to handle tracking the coroutines etc + public void BoostRegenerate() { + boostCharges = Math.Min(boostCharges + 1, boostMax); + Debug.Log($"Boosts available {boostCharges}"); } - // returns whether shields depleted - public bool ShieldsReduce(float amt) { - shieldsCurrent = shieldsCurrent - amt; - return shieldsCurrent < 0f; + public bool BoostUse(Output output) { + if (boostCharges < 1) + return false; + + float newOutput = output switch { + Output.Acceleration => BoostUseAcceleration(), + Output.Deceleration => BoostUseDeceleration(), + Output.Strafing => BoostUseStrafing(), + Output.Shield => BoostUseShields(), + _ => 0f, + }; + + // Boosts are immediately used and tracked here + boostCharges--; + + Debug.Log($"Set {output} to {newOutput}"); + + return true; } - public void ShieldsRegenerate() { - shieldsCurrent = Math.Min(shieldsCurrent + shieldsRegen, shieldsMax); + float BoostUseAcceleration() => acceleration += baseOutput; + float BoostUseDeceleration() => deceleration += baseOutput; + float BoostUseStrafing() => strafing += baseOutput; + float BoostUseShields() { + float shieldFrac = shieldMax / shieldCurrent; + shieldMax = 7000f; + shieldCurrent = shieldMax * shieldFrac; + ShieldRegenRecalculate(); + return shieldMax; } + + public void BoostEnd(Output output) { + float newOutput = output switch { + Output.Acceleration => BoostEndAcceleration(), + Output.Deceleration => BoostEndDeceleration(), + Output.Strafing => BoostEndStrafing(), + Output.Shield => BoostEndShields(), + _ => 0f, + }; + + Debug.Log($"Set {output} to {newOutput}"); + } + + float BoostEndAcceleration() => acceleration -= baseOutput; + float BoostEndDeceleration() => deceleration -= baseOutput; + float BoostEndStrafing() => strafing -= baseOutput; + float BoostEndShields() { + float shieldFrac = shieldMax / shieldCurrent; + shieldMax = 5000f; + shieldCurrent = shieldMax * shieldFrac; + ShieldRegenRecalculate(); + return shieldMax; + } + + // returns whether shield depleted + public bool ShieldReduce(float amt) { + shieldCurrent = shieldCurrent - amt; + return shieldCurrent < 0f; + } + + public void ShieldRegenerate() => shieldCurrent = Math.Min(shieldCurrent + shieldRegen, shieldMax); + void ShieldRegenRecalculate() => shieldRegen = (shieldMax / 5f) * Time.fixedDeltaTime; } \ No newline at end of file diff --git a/Assets/Src/ShipControls.cs b/Assets/Src/ShipControls.cs index d7d5c0f..cb2c441 100755 --- a/Assets/Src/ShipControls.cs +++ b/Assets/Src/ShipControls.cs @@ -1,16 +1,15 @@ using System; +using System.Collections; +using System.Collections.Generic; + using UnityEngine; using UnityEngine.InputSystem; -public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { +public class ShipControls : MonoBehaviour { public Camera aim; public Timing timing; - public PowerUnit powerUnit = new(); SpaceRaceInput input; - InputAction lookAction; - InputAction accelerateAction; - InputAction decelerateAction; Rigidbody rigidBody; @@ -22,12 +21,16 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { Vector3 thrust; Vector3 strafe; - // Camera Controls float camPitch; float camYaw; float clampAngle = 90.0f; + public PowerUnit powerUnit = new(); + List boostLifecycles = new(); + int boostDurationSeconds = 2; + int boostCooldownSeconds = 5; + void Start() { Cursor.lockState = CursorLockMode.Locked; rigidBody = GetComponent(); @@ -47,23 +50,10 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { camYaw = initialAim.eulerAngles.y; forceMode = ForceMode.Acceleration; - if (input == null) { - input = new SpaceRaceInput(); - input.ship.SetCallbacks(this); - } - input.ship.Enable(); - - lookAction = input.FindAction("look"); - accelerateAction = input.FindAction("accelerate"); - decelerateAction = input.FindAction("decelerate"); - + SetupActions(); Respawn(); } - void OnDestroy() { - input.ship.RemoveCallbacks(this); - } - // to minimise input lag we poll for the thrust vector every frame and set it // same with the camera, we always look around void Update() { @@ -76,9 +66,8 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { // needs to be done here in fixedUpdate because otherwise the input is checked on every frame // so they will have already hit the button before this tick and they actually start moving // aka ripoff - bool shouldStartTimer = !timing.timerEnabled && (thrust != Vector3.zero || strafe != Vector3.zero); - if (shouldStartTimer) - timing.StartTimer(); + bool shouldBegin = !timing.timerEnabled && (thrust != Vector3.zero || strafe != Vector3.zero); + if (shouldBegin) Begin(); // the ship being propelled forward // this is in world space because of the xform from the camera pos @@ -98,7 +87,7 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { if (Quaternion.Angle(aim.transform.rotation, rigidBody.rotation) > 1f) rigidBody.rotation = Quaternion.RotateTowards(transform.rotation, aim.transform.rotation, step); - powerUnit.ShieldsRegenerate(); + powerUnit.ShieldRegenerate(); } void UpdateCamera() { @@ -110,25 +99,20 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { // delta *= 0.1f; // Account for sensitivity setting on old Mouse X and Y axes. // def needs to be configurable - Vector2 lookDelta = lookAction.ReadValue(); + Vector2 lookDelta = input.ship.look.ReadValue(); camYaw += lookDelta.x; camPitch -= lookDelta.y; camPitch = Mathf.Clamp(camPitch, -clampAngle, clampAngle); aim.transform.eulerAngles = new Vector3(camPitch, camYaw, 0.0f); } - public void OnStrafe(InputAction.CallbackContext ctx) { - Vector2 str = ctx.ReadValue(); - strafe = new Vector3(str.x, str.y, 0f) * powerUnit.Strafing; - } - // if you are decelerating you can't accelerate as well // otherwise you can flip the ship around and // decelerate + accelerate against the velocity vector // aka cheating? Vector3 getThrust() { - float accelerateInput = accelerateAction.ReadValue(); - float decelerateInput = decelerateAction.ReadValue(); + float accelerateInput = input.ship.accelerate.ReadValue(); + float decelerateInput = input.ship.decelerate.ReadValue(); // decelerates the ship against the direction it is moving if (decelerateInput > 0f) { @@ -144,14 +128,6 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { return Vector3.zero; } - public void OnQuit(InputAction.CallbackContext ctx) { - Application.Quit(); - } - - public void OnRespawn(InputAction.CallbackContext ctx) { - Respawn(); - } - public void Respawn() { // IMPORTANT // stop the timer before we move the ship or anything @@ -170,9 +146,99 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { camPitch = initialAim.eulerAngles.x; camYaw = initialAim.eulerAngles.y; + foreach (var cd in boostLifecycles) { + StopCoroutine(cd); + } + powerUnit.Init(); } + // stuff we have to do right as they come off the line + void Begin() { + timing.StartTimer(); + + // start with 0 cooldowns and regen them + var cd = BoostCdLifecycle(); + boostLifecycles.Add(cd); + StartCoroutine(cd); + } + + public float Speed() { + return rigidBody.velocity.magnitude; + } + + public void Damage(float amt, string src) { + Debug.Log($"Damage {amt} from {src}"); + + bool destroyed = powerUnit.ShieldReduce(amt); + if (destroyed) { + Debug.Log($"Ddddestroyed by {src}"); + Respawn(); + } + } + + void BoostUse(Output output) { + bool used = powerUnit.BoostUse(output); + if (!used) return; + + var boost = BoostLifecycle(output); + boostLifecycles.Add(boost); + StartCoroutine(boost); + } + + void BoostEnd(Output output) { + powerUnit.BoostEnd(output); + var cd = BoostCdLifecycle(); + boostLifecycles.Add(cd); + StartCoroutine(cd); + } + + IEnumerator BoostLifecycle(Output output) { + yield return new WaitForSeconds(boostDurationSeconds); + BoostEnd(output); + } + + IEnumerator BoostCdLifecycle() { + yield return new WaitForSeconds(boostCooldownSeconds); + powerUnit.BoostRegenerate(); + } + + // I prefer doing it this way than registering the callbacks etc + // the control of the actions is more granular + // plus the callbacks don't have to be public, bonus + void SetupActions() { + if (input == null) + input = new SpaceRaceInput(); + + input.ship.Enable(); + + // we have to update strafe the whole time it's being pressed + // including setting it back to zero when released + input.ship.strafe.started += OnStrafe; + input.ship.strafe.performed += OnStrafe; + input.ship.strafe.canceled += OnStrafe; + + // these we only care about the initial press + input.ship.respawn.started += OnRespawn; + input.ship.quit.started += OnQuit; + input.ship.powerUnit1.started += OnPowerUnit1; + input.ship.powerUnit2.started += OnPowerUnit2; + input.ship.powerUnit3.started += OnPowerUnit3; + input.ship.powerUnit4.started += OnPowerUnit4; + } + + void OnStrafe(InputAction.CallbackContext ctx) { + Vector2 str = ctx.ReadValue(); + strafe = new Vector3(str.x, str.y, 0f) * powerUnit.Strafing; + } + + void OnQuit(InputAction.CallbackContext ctx) => Application.Quit(); + void OnRespawn(InputAction.CallbackContext ctx) => Respawn(); + void OnPowerUnit1 (InputAction.CallbackContext ctx) => BoostUse(Output.Acceleration); + void OnPowerUnit2 (InputAction.CallbackContext ctx) => BoostUse(Output.Deceleration); + void OnPowerUnit3 (InputAction.CallbackContext ctx) => BoostUse(Output.Strafing); + void OnPowerUnit4 (InputAction.CallbackContext ctx) => BoostUse(Output.Shield); + void OnDrawGizmosSelected() { if (Application.isPlaying == false) return; @@ -196,30 +262,4 @@ public class ShipControls : MonoBehaviour, SpaceRaceInput.IShipActions { Gizmos.color = Color.cyan; Gizmos.DrawRay(transform.position, thrust); } - - public float Speed() { - return rigidBody.velocity.magnitude; - } - - public void Damage(float amt, string src) { - Debug.Log($"Damage {amt} from {src}"); - - bool destroyed = powerUnit.ShieldsReduce(amt); - if (destroyed) { - Debug.Log($"Ddddestroyed by {src}"); - Respawn(); - } - } - - // We don't use these because we poll instead - // the callbacks are only invoked when the value changes - // aka if you hold accelerate it doesn't do what you expect - public void OnAccelerate(InputAction.CallbackContext ctx) { } - public void OnDecelerate(InputAction.CallbackContext ctx) { } - public void OnLook(InputAction.CallbackContext ctx) { } - - public void OnPowerUnit1 (InputAction.CallbackContext ctx) => powerUnit.Reassign(2f, 4f, 1f); - public void OnPowerUnit2 (InputAction.CallbackContext ctx) => powerUnit.Reassign(2f, 4f, 3f); - public void OnPowerUnit4 (InputAction.CallbackContext ctx) => powerUnit.Reassign(2f, 5f, 0f); - public void OnPowerUnit3 (InputAction.CallbackContext ctx) => powerUnit.Reassign(1f, 3f, 3f); } \ No newline at end of file diff --git a/Assets/Src/ShipInput.cs b/Assets/Src/ShipInput.cs index ef13851..9debde9 100755 --- a/Assets/Src/ShipInput.cs +++ b/Assets/Src/ShipInput.cs @@ -376,7 +376,7 @@ public partial class @SpaceRaceInput: IInputActionCollection2, IDisposable ""name"": """", ""id"": ""448824b6-c8b3-47ec-b7f7-0123f90cf5f6"", ""path"": ""/1"", - ""interactions"": """", + ""interactions"": ""Press"", ""processors"": """", ""groups"": """", ""action"": ""powerUnit1"", @@ -387,7 +387,7 @@ public partial class @SpaceRaceInput: IInputActionCollection2, IDisposable ""name"": """", ""id"": ""18e2e44e-8735-45ce-aad2-b75c212fc4dc"", ""path"": ""/2"", - ""interactions"": """", + ""interactions"": ""Press"", ""processors"": """", ""groups"": """", ""action"": ""powerUnit2"", @@ -398,7 +398,7 @@ public partial class @SpaceRaceInput: IInputActionCollection2, IDisposable ""name"": """", ""id"": ""46351ee7-55d7-428d-9778-6ffd51bc663c"", ""path"": ""/3"", - ""interactions"": """", + ""interactions"": ""Press"", ""processors"": """", ""groups"": """", ""action"": ""powerUnit3"", @@ -409,7 +409,7 @@ public partial class @SpaceRaceInput: IInputActionCollection2, IDisposable ""name"": """", ""id"": ""e36dc262-5e19-467b-9153-98f8795b3752"", ""path"": ""/4"", - ""interactions"": """", + ""interactions"": ""Press"", ""processors"": """", ""groups"": """", ""action"": ""powerUnit4"", diff --git a/Assets/Src/UI/Controls.uxml b/Assets/Src/UI/Controls.uxml index 35456fa..bf1b04a 100644 --- a/Assets/Src/UI/Controls.uxml +++ b/Assets/Src/UI/Controls.uxml @@ -11,6 +11,10 @@ + + + + diff --git a/Assets/Src/UI/ControlsUI.cs b/Assets/Src/UI/ControlsUI.cs index 04b63c4..b1d2b74 100644 --- a/Assets/Src/UI/ControlsUI.cs +++ b/Assets/Src/UI/ControlsUI.cs @@ -12,6 +12,7 @@ public class ControlsUI : MonoBehaviour { UIDocument uiDocument; Label speed; Label shields; + Label boosts; Label puAccel; Label puDecel; Label puStrafe; @@ -27,6 +28,7 @@ public class ControlsUI : MonoBehaviour { shields = uiDocument.rootVisualElement.Q