106 lines
4.1 KiB
TypeScript
106 lines
4.1 KiB
TypeScript
// Movement/State/BFL_MovementStateMachine.ts
|
|
|
|
import { E_MovementState } from '#root/Movement/Core/E_MovementState.ts';
|
|
import type { S_MovementContext } from '#root/Movement/State/S_MovementContext.ts';
|
|
import { E_SurfaceType } from '#root/Movement/Surface/E_SurfaceType.ts';
|
|
|
|
/**
|
|
* Movement State Machine
|
|
*
|
|
* Pure functional FSM for determining movement state
|
|
* Takes movement context and returns appropriate state
|
|
* No side effects - completely deterministic
|
|
*
|
|
* @category Movement State
|
|
* @pure All methods are pure functions
|
|
*/
|
|
class BFL_MovementStateMachineClass {
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
// STATE DETERMINATION
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Determine movement state based on current Context
|
|
* Main entry point for state machine logic
|
|
*
|
|
* @param Context - Current movement context
|
|
* @returns Appropriate movement state
|
|
*
|
|
* @example
|
|
* const state = MovementStateMachine.DetermineState({
|
|
* IsGrounded: true,
|
|
* SurfaceType: E_SurfaceType.Walkable,
|
|
* InputMagnitude: 0.8,
|
|
* CurrentSpeed: 500,
|
|
* VerticalVelocity: 0,
|
|
* IsBlocked: false
|
|
* });
|
|
* // Returns: E_MovementState.Walking
|
|
*
|
|
* @pure true
|
|
* @category State Determination
|
|
*/
|
|
public DetermineState(Context: S_MovementContext): E_MovementState {
|
|
// Priority 1: Check if grounded
|
|
if (Context.IsGrounded) {
|
|
// Priority 2: Check surface type
|
|
if (Context.SurfaceType === E_SurfaceType.SteepSlope) {
|
|
return E_MovementState.Sliding;
|
|
} else if (
|
|
Context.SurfaceType === E_SurfaceType.Wall ||
|
|
Context.SurfaceType === E_SurfaceType.Ceiling ||
|
|
// Priority 3: Check if blocked by collision
|
|
Context.IsBlocked
|
|
) {
|
|
return E_MovementState.Blocked;
|
|
} else {
|
|
// Priority 4: Determine ground state based on input
|
|
return this.DetermineGroundedState(Context);
|
|
}
|
|
} else {
|
|
return this.DetermineAirborneState(Context);
|
|
}
|
|
}
|
|
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
// STATE HELPERS
|
|
// ════════════════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Determine state when character is airborne
|
|
* Distinguishes between jumping, falling, etc.
|
|
*
|
|
* @param Context - Current movement context
|
|
* @returns Airborne-specific state
|
|
*
|
|
* @pure true
|
|
* @category State Helpers
|
|
*/
|
|
private DetermineAirborneState(Context: S_MovementContext): E_MovementState {
|
|
// Could extend this to differentiate Jump vs Fall
|
|
// For now, just return Airborne
|
|
return E_MovementState.Airborne;
|
|
}
|
|
|
|
/**
|
|
* Determine state when character is on ground
|
|
* Distinguishes between idle, walking, running, etc.
|
|
*
|
|
* @param Context - Current movement context
|
|
* @returns Grounded-specific state
|
|
*
|
|
* @pure true
|
|
* @category State Helpers
|
|
*/
|
|
private DetermineGroundedState(Context: S_MovementContext): E_MovementState {
|
|
// Check if player is providing input
|
|
if (Context.InputMagnitude > 0.01 && Context.CurrentSpeed > 1.0) {
|
|
return E_MovementState.Walking;
|
|
} else {
|
|
return E_MovementState.Idle;
|
|
}
|
|
}
|
|
}
|
|
|
|
export const BFL_MovementStateMachine = new BFL_MovementStateMachineClass();
|