diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarActorMovementController.hpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarActorMovementController.hpp')
-rw-r--r-- | source/game/StarActorMovementController.hpp | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/source/game/StarActorMovementController.hpp b/source/game/StarActorMovementController.hpp new file mode 100644 index 0000000..11731eb --- /dev/null +++ b/source/game/StarActorMovementController.hpp @@ -0,0 +1,363 @@ +#ifndef STAR_ACTOR_MOVEMENT_CONTROLLER_HPP +#define STAR_ACTOR_MOVEMENT_CONTROLLER_HPP + +#include "StarMovementController.hpp" +#include "StarPlatformerAStarTypes.hpp" +#include "StarAnchorableEntity.hpp" +#include "StarGameTimers.hpp" + +namespace Star { + +STAR_EXCEPTION(ActorMovementControllerException, MovementControllerException); + +STAR_CLASS(ActorMovementController); +STAR_CLASS(PathController); + +struct ActorJumpProfile { + ActorJumpProfile(); + ActorJumpProfile(Json const& config); + + Json toJson() const; + + ActorJumpProfile merge(ActorJumpProfile const& rhs) const; + + Maybe<float> jumpSpeed; + Maybe<float> jumpControlForce; + Maybe<float> jumpInitialPercentage; + + // If this is greater than 0.0, jump hold time is limited by this factor. + Maybe<float> jumpHoldTime; + // If this is greater than 0.0, then the total jump time for *all jumps in a + // multi jump set* is limited by this factor. + Maybe<float> jumpTotalHoldTime; + + Maybe<bool> multiJump; + Maybe<float> reJumpDelay; + Maybe<bool> autoJump; + Maybe<bool> collisionCancelled; +}; + +DataStream& operator>>(DataStream& ds, ActorJumpProfile& movementParameters); +DataStream& operator<<(DataStream& ds, ActorJumpProfile const& movementParameters); + +// A not-quite superset of MovementParameters, with some fields from +// MovementParameters ignored because they make no sense, and other fields +// expanded out to different cases based on Actor specific things. +struct ActorMovementParameters { + // Load sensible defaults from a config file. + static ActorMovementParameters sensibleDefaults(); + + // Construct parameters from config with only those specified in the config + // set, if any. + explicit ActorMovementParameters(Json const& config = Json()); + + Json toJson() const; + + // Merge the given set of movement parameters on top of this one, with any + // set parameters in rhs overwriting the ones in this set. + ActorMovementParameters merge(ActorMovementParameters const& rhs) const; + + Maybe<float> mass; + Maybe<float> gravityMultiplier; + Maybe<float> liquidBuoyancy; + Maybe<float> airBuoyancy; + Maybe<float> bounceFactor; + Maybe<bool> stopOnFirstBounce; + Maybe<bool> enableSurfaceSlopeCorrection; + Maybe<float> slopeSlidingFactor; + Maybe<float> maxMovementPerStep; + Maybe<float> maximumCorrection; + Maybe<float> speedLimit; + + Maybe<PolyF> standingPoly; + Maybe<PolyF> crouchingPoly; + + Maybe<bool> stickyCollision; + Maybe<float> stickyForce; + + Maybe<float> walkSpeed; + Maybe<float> runSpeed; + Maybe<float> flySpeed; + + Maybe<float> airFriction; + Maybe<float> liquidFriction; + + Maybe<float> minimumLiquidPercentage; + Maybe<float> liquidImpedance; + + Maybe<float> normalGroundFriction; + Maybe<float> ambulatingGroundFriction; + + Maybe<float> groundForce; + Maybe<float> airForce; + Maybe<float> liquidForce; + + ActorJumpProfile airJumpProfile; + ActorJumpProfile liquidJumpProfile; + + Maybe<float> fallStatusSpeedMin; + Maybe<int> fallThroughSustainFrames; + Maybe<float> maximumPlatformCorrection; + Maybe<float> maximumPlatformCorrectionVelocityFactor; + + Maybe<StringSet> physicsEffectCategories; + + Maybe<float> groundMovementMinimumSustain; + Maybe<float> groundMovementMaximumSustain; + Maybe<float> groundMovementCheckDistance; + + Maybe<bool> collisionEnabled; + Maybe<bool> frictionEnabled; + Maybe<bool> gravityEnabled; + + Maybe<float> pathExploreRate; +}; + +DataStream& operator>>(DataStream& ds, ActorMovementParameters& movementParameters); +DataStream& operator<<(DataStream& ds, ActorMovementParameters const& movementParameters); + +// A set of normalized values that act as "modifiers" or "bonuses" to movement, +// and can be combined sensibly. A modifier of 0.0 represents a 0% change, a +// modifier of 0.2 represents a 20% increase, and a modifier of -0.2 represents +// a 20% decrease. Also includes some flags that disable functionality +// combined with logical OR. +struct ActorMovementModifiers { + explicit ActorMovementModifiers(Json const& config = Json()); + + Json toJson() const; + + // Combines each modifier value through addition. + ActorMovementModifiers combine(ActorMovementModifiers const& rhs) const; + + float groundMovementModifier; + float liquidMovementModifier; + float speedModifier; + float airJumpModifier; + float liquidJumpModifier; + + bool runningSuppressed; + bool jumpingSuppressed; + // Suppresses left, right, down, crouch, jump, and fly controls + bool movementSuppressed; + bool facingSuppressed; +}; + +DataStream& operator>>(DataStream& ds, ActorMovementModifiers& movementModifiers); +DataStream& operator<<(DataStream& ds, ActorMovementModifiers const& movementModifiers); + +class ActorMovementController : public MovementController { +public: + // Constructs an ActorMovementController with parameters loaded from sensible + // defaults, and the given parameters (if any) applied on top of them. + explicit ActorMovementController(ActorMovementParameters const& parameters = ActorMovementParameters()); + + // Currently active parameters. + ActorMovementParameters const& baseParameters() const; + + // Apply any set parameters from the given set on top of the current set. + void updateBaseParameters(ActorMovementParameters const& parameters); + + // Reset the parameters from the sensible defaults, and apply the given + // parameters (if any) on top of them. + void resetBaseParameters(ActorMovementParameters const& parameters = ActorMovementParameters()); + + // Currently active modifiers. + ActorMovementModifiers const& baseModifiers() const; + + // Combine the given modifiers with the already active modifiers. + void updateBaseModifiers(ActorMovementModifiers const& modifiers); + + // Reset all modifiers to the given values + void resetBaseModifiers(ActorMovementModifiers const& modifiers = ActorMovementModifiers()); + + // Stores and loads position, velocity, rotation, movingDirection, + // facingDirection, and crouching + Json storeState() const; + void loadState(Json const& state); + + // Optionaly anchor this ActorMovementController to the given + // AnchorableEntity. position, rotation, and facing direction will be set + // based on the entity anchor alone every tick, and on slaved + // ActorMovementControllers it will be updated based on the actual slave-side + // AnchorableEntity state. + void setAnchorState(EntityAnchorState anchorState); + void resetAnchorState(); + Maybe<EntityAnchorState> anchorState() const; + EntityAnchorConstPtr entityAnchor() const; + + // ActorMovementController position and rotation honor the entity anchor, if + // an anchor is set. + Vec2F position() const; + float xPosition() const; + float yPosition() const; + float rotation() const; + PolyF collisionBody() const; + RectF localBoundBox() const; + RectF collisionBoundBox() const; + + bool walking() const; + bool running() const; + Direction movingDirection() const; + Direction facingDirection() const; + bool crouching() const; + bool flying() const; + bool falling() const; + bool canJump() const; + bool jumping() const; + // Slightly different than onGround, in that this is sustained for a few + // extra frames of movement before it becomes false. + bool groundMovement() const; + bool liquidMovement() const; + bool pathfinding() const; + + // Basic direct physics controls that can be called multiple times per + // update and will be combined. + void controlRotation(float rotationRate); + void controlAcceleration(Vec2F const& acceleration); + void controlForce(Vec2F const& force); + void controlApproachVelocity(Vec2F const& targetVelocity, float maxControlForce); + void controlApproachVelocityAlongAngle(float angle, float targetVelocity, float maxControlForce, bool positiveOnly = false); + void controlApproachXVelocity(float targetXVelocity, float maxControlForce); + void controlApproachYVelocity(float targetYVelocity, float maxControlForce); + + // Apply ActorMovementParameters / ActorMovementModifiers only as long as + // the controls are active. Can be called multiple times per update and + // will be combined. + void controlParameters(ActorMovementParameters const& parameters); + void controlModifiers(ActorMovementModifiers const& modifiers); + + // Higher level movement controls that use forces defined in the + // ActorMovementParameters. Calling more than once per update will override + // previous calls. + void controlMove(Direction direction, bool run = true); + void controlFace(Direction direction); + void controlDown(); + void controlCrouch(); + void controlJump(bool jumpEvenIfUnable = false); + void controlFly(Vec2F const& velocity); + + Maybe<pair<Vec2F, bool>> pathMove(Vec2F const& pathPosition, bool run = false, Maybe<PlatformerAStar::Parameters> const& parameters = {}); + Maybe<pair<Vec2F, bool>> controlPathMove(Vec2F const& pathPosition, bool run = false, Maybe<PlatformerAStar::Parameters> const& parameters = {}); + + // Clears all control data. + void clearControls(); + + // Integrates the ActorMovementController one WorldTimestep and applies all + // the control data and clears it for the next step. + void tickMaster(); + + void tickSlave(); + +private: + struct ApproachVelocityCommand { + Vec2F targetVelocity; + float maxControlForce; + }; + + struct ApproachVelocityAlongAngleCommand { + float alongAngle; + float targetVelocity; + float maxControlForce; + bool positiveOnly; + }; + + void applyMCParameters(ActorMovementParameters const& parameters); + void doSetAnchorState(Maybe<EntityAnchorState> anchorState); + + ActorMovementParameters m_baseParameters; + ActorMovementModifiers m_baseModifiers; + + // State data + + NetElementBool m_walking; + NetElementBool m_running; + NetElementEnum<Direction> m_movingDirection; + NetElementEnum<Direction> m_facingDirection; + NetElementBool m_crouching; + NetElementBool m_flying; + NetElementBool m_falling; + NetElementBool m_canJump; + NetElementBool m_jumping; + NetElementBool m_groundMovement; + NetElementBool m_liquidMovement; + NetElementData<Maybe<EntityAnchorState>> m_anchorState; + EntityAnchorConstPtr m_entityAnchor; + + // Command data + + float m_controlRotationRate; + Vec2F m_controlAcceleration; + Vec2F m_controlForce; + List<ApproachVelocityCommand> m_controlApproachVelocities; + List<ApproachVelocityAlongAngleCommand> m_controlApproachVelocityAlongAngles; + + Maybe<Direction> m_controlMove; + Maybe<Direction> m_controlFace; + bool m_controlRun; + bool m_controlCrouch; + bool m_controlDown; + bool m_controlJump; + bool m_controlJumpAnyway; + + Maybe<Vec2F> m_controlFly; + + Maybe<pair<Vec2F, bool>> m_controlPathMove; + Maybe<pair<Vec2F, bool>> m_pathMoveResult; + PathControllerPtr m_pathController; + + ActorMovementParameters m_controlParameters; + ActorMovementModifiers m_controlModifiers; + + // Internal state data + + int m_fallThroughSustain; + bool m_lastControlJump; + bool m_lastControlDown; + + GameTimer m_reJumpTimer; + Maybe<GameTimer> m_jumpHoldTimer; + GameTimer m_groundMovementSustainTimer; + + // Target horizontal velocity for walking / running + float m_targetHorizontalAmbulatingVelocity; +}; + +class PathController { +public: + PathController(World* world); + + PlatformerAStar::Parameters const& parameters(); + void setParameters(PlatformerAStar::Parameters const& parameters); + void reset(); + bool pathfinding() const; + Maybe<Vec2F> targetPosition() const; + Maybe<Direction> facing() const; + Maybe<PlatformerAStar::Action> curAction() const; + + // return true for reaching goal, false for failing to find path, nothing for running + Maybe<bool> findPath(ActorMovementController& movementController, Vec2F const& targetPosition); + Maybe<bool> move(ActorMovementController& movementController, ActorMovementParameters const& parameters, ActorMovementModifiers const& modifiers, bool run, float dt); +private: + bool validateEdge(ActorMovementController& movementController, PlatformerAStar::Edge const& edge); + bool movingCollision(ActorMovementController& movementController, PolyF const& collisionPoly); + +private: + bool onGround(ActorMovementController const& movementController, Vec2F const& position, CollisionSet const& collisionSet) const; + + World* m_world; + PlatformerAStar::Parameters m_parameters; + + Maybe<Vec2F> m_startPosition; + Maybe<Vec2F> m_targetPosition; + PlatformerAStar::PathFinderPtr m_pathFinder; + + Maybe<Direction> m_controlFace; + + size_t m_edgeIndex; + float m_edgeTimer; + Maybe<PlatformerAStar::Path> m_path; +}; + +} + +#endif |