using System; using UnityEngine; using Framework.Input.States; namespace Framework.Actors.Shooter { /// Lets the player control a character in the air public class AirMove : PlayerMove { /// Whether the air move was activated by the player jumping up /// /// If this is set at the time the move starts, the actor will receive an upward /// impulse that is incrementally applied until either the velocity required for /// the jump height is reached or the player releases the jump button. /// public bool WasActivatedByJumping = false; /// Called when the actor has started the move public override void OnStarted() { base.OnStarted(); EnableGravity(true); ++ActorController.ConsecutiveJumpCount; this.mostRecentVerticalVelocity = 0.0f; } /// Called once per physics frame /// /// Updates the world position of the actor /// public override void FixedUpdate() { base.FixedUpdate(); // If this is the first jump frame, don't check grounding (the actor is // still grounded and just jumping off) if(this.WasActivatedByJumping) { GiveVerticalJumpImpulse(Abilities.JumpHeight); this.WasActivatedByJumping = false; } else { // Update the grounded state (the actor's physics component will have // moved it before or after this code ran, so the isGrounded state is now stale) bool isGrounded = RecheckGrounding(); if(isGrounded) { float ownVelocity = GetVerticalVelocity(); Vector3 groundVelocity = ActorController.GroundChecker.GetMostRecentGroundVelocity(); isGrounded &= (ownVelocity <= groundVelocity.y); } // If the actor has impacted the ground, return to the ground move if(isGrounded) { SwitchToGroundMove(this.mostRecentVerticalVelocity); ActorController.ActiveMove.FixedUpdate(); return; } else { this.mostRecentVerticalVelocity = GetVerticalVelocity(); } } ShooterInputState inputState = InputManager.GetState(); handleHorizontalMovement(inputState); // If the player pressed the jump key, we'll be airborne with upward velocity if(inputState.Jump.WasTriggered) { if(ActorController.ConsecutiveJumpCount < Abilities.JumpCount) { SwitchToAirMove(jumped: true); return; } } } /// /// Switches the presenter to the animation state appropriate for this move /// protected override void SetPresenterState() { ShooterActorPresenter presenter = ActorPresenter; if(presenter != null) { presenter.SetAirState(); } } /// Movement logic to move the actor to the left and right /// Inputs the player has made this frame private void handleHorizontalMovement(ShooterInputState inputState) { // Determine the speed at which the player wants to move and the highest // possible speed the actor could achieve (used to calculate acceleration) float fastestSpeed, runnningSpeed, strafingSpeed; { if(Abilities.CanSprint && inputState.Sprint.IsActive) { fastestSpeed = Abilities.RunningSpeed; } else { fastestSpeed = Abilities.WalkingSpeed; } runnningSpeed = fastestSpeed * inputState.Running; strafingSpeed = Abilities.WalkingSpeed * inputState.Strafing; } float acceleration = fastestSpeed / Abilities.SecondsToFullSpeed; acceleration *= Abilities.AirControlFactor; // Adjust for air control! AccelerateToVelocity(runnningSpeed, strafingSpeed, acceleration); // TODO: Add rotation times aircontrol } /// Highest negative vertical velocity the actor encountered private float mostRecentVerticalVelocity; } } // namespace Framework.Actors.Shooter