예제 #1
0
        public IState Execute(PlayerController p)
        {
            p.Move();
            p.ApplyGravity();
            p.DetermineFacing();
            p.SpriteManager.AlignWith(p.Surface.SurfaceNormal);

            if (p.Surface.Airborne)
            {
                return(new FallState());
            }

            if (p.Surface.Unstable)
            {
                // TODO: Make this an event or observable perhaps?
                // So it isnt running every frame.
                var animation = p.SpriteManager.GetAnimationState();
                if (animation.IsName("Run"))
                {
                    p.SpriteManager.SetAnimation("RunDifficult");
                    p.SpriteManager.Speed = 1f;
                }

                var v = p.GetSurfaceProjectedVelocity();
                var i = p.Input.MovementHorizontal;

                // We slip and fall if...
                // We are on a slope above the slope angle threshold.
                // We aren't inputting any movement.
                // We are moving backward (relative to our input).
                var aboveSlopeThreshold = p.Surface.SurfaceAngle > p.Surface.SlopeAngleThreshold;
                var noInput             = i.magnitude <= 0.01f;
                var movingBackwards     = Vector2.Dot(v.normalized, i.normalized) < 0f;

                if (aboveSlopeThreshold)
                {
                    if (noInput || movingBackwards)
                    {
                        return(new FallSlideState());
                    }
                }
            }
            else
            {
                var v = p.GetSurfaceProjectedVelocity();
                var i = p.GetSurfaceAlignedXInput();
                var movingIntentionally = i.sqrMagnitude > 0.01f && v.sqrMagnitude > 0.01f;
                var animation           = p.SpriteManager.GetAnimationState();

                /// Select an animation based on what we are doing:

                // TODO: Make this an event or observable perhaps?
                // So it isnt running every frame.
                if (animation.IsName("RunDifficult"))
                {
                    p.SpriteManager.SetAnimation("Run");
                }

                p.SpriteManager.Animator.SetBool("MovingIntentionally", movingIntentionally);
                p.SpriteManager.Animator.SetBool("Pushing", p.TowardWall(i));

                // Scale animation with relative speed.
                if (animation.IsName("Run"))
                {
                    var aligned = Vector2.Dot(v.normalized, i) > 0;
                    var speed   = aligned ? v.magnitude : 0f;
                    p.SpriteManager.Speed = Mathf.Clamp01(speed);
                }
                else
                {
                    p.SpriteManager.Speed = 1f;
                }
            }

            foreach (var input in p.Input)
            {
                if (input.Action == InputActions.JumpDown)
                {
                    return(new JumpState());
                }

                if (input.Action == InputActions.AttackDown)
                {
                    return(new AttackState());
                }

                p.Input.Release(input);
            }

            return(null);
        }
예제 #2
0
        public IState Execute(PlayerController p)
        {
            p.ApplyGravity();
            p.DetermineFacing();

            if (accelerationCurve != null)
            {
                var accel = p.Physics.Acceleration * accelerationCurve.Evaluate(Time.time - atTime);
                p.Move(p.Physics.Speed, accel);
            }
            else
            {
                p.Move();
            }

            // Wall Jumping / Attacking
            foreach (var input in p.Input)
            {
                if (input.Action == InputActions.AttackDown)
                {
                    return(new AttackState());
                }

                if (input.Action == InputActions.JumpDown)
                {
                    if (p.SweepForWall(Vector2.right))
                    {
                        return(PlayerController.WallJump(p, Vector2.left));
                    }
                    if (p.SweepForWall(Vector2.left))
                    {
                        return(PlayerController.WallJump(p, Vector2.right));
                    }

                    // Coyote Time
                    if (p.StateMachine.PreviousState is RunState && !Utility.Elapsed(startTime, p.CoyoteTime))
                    {
                        return(new JumpState());
                    }
                }

                p.Input.Release(input);
            }

            if (p.Surface.Grounded)
            {
                var moving = p.GetSurfaceProjectedVelocity().sqrMagnitude > 0.01f;
                p.SpriteManager.SetAnimation(moving ? "LandMoving" : "LandStationary");
                return(new RunState());
            }

            if (p.Surface.ContactingWall)
            {
                // Wallslide.
                var i = p.GetSurfaceAlignedXInput();
                if (!p.AwayFromWall(i) && p.SweepForWall(-p.Surface.WallNormal))
                {
                    return(new WallSlideState());
                }
            }

            if (p.Surface.Unstable)
            {
                return(new FallSlideState());
            }

            return(null);
        }