using System;
using UnityEngine;
using Framework.Input.States;
namespace Framework.Actors.Platformer {
/// 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();
}
}
PlatformerInputState inputState = InputManager.GetState();
handleHorizontalMovement(inputState);
// Begin dashing if the player hits the dash key and it's enabled
if(inputState.Dash.WasTriggered) {
if(Abilities.CanAirDash) {
SwitchToDashMove();
}
}
// 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() {
PlatformerActorPresenter 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(PlatformerInputState 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, targetSpeed;
{
if(Abilities.CanSprint && inputState.Sprint.IsActive) {
fastestSpeed = Abilities.RunningSpeed;
} else {
fastestSpeed = Abilities.WalkingSpeed;
}
targetSpeed = fastestSpeed * inputState.Horizontal;
}
float acceleration = fastestSpeed / Abilities.SecondsToFullSpeed;
acceleration *= Abilities.AirControlFactor; // Adjust for air control!
AccelerateToVelocity(targetSpeed, acceleration);
// Turn the actor towards the direction the player is directing
if(inputState.Horizontal < -0.1f) {
ActorController.FacingDirection = -1.0f;
} else if(inputState.Horizontal > 0.1f) {
ActorController.FacingDirection = +1.0f;
}
}
/// Highest negative vertical velocity the actor encountered
private float mostRecentVerticalVelocity;
}
} // namespace Framework.Actors.Platformer