Exemplo n.º 1
0
        public override MovementCalculator CreateMovementCalculator(AvatarController avatar)
        {
            float angularVelocity               = 0;
            var   acceleration                  = Vector2.zero;
            float boostGatheringDuration        = 0;
            float boostExecutionDuration        = 0;
            float maximumBoostExecutionDuration = 0;

            return(deltaTime => {
                float currentAngle = avatar.physics.rotationAngle;

                var targetDirection = avatar.intentions.intendedFlight == Vector2.zero
                    ? avatar.physics.rotatedForward
                    : avatar.intentions.intendedFlight;

                float targetAngle = Vector2.SignedAngle(avatar.physics.forward, targetDirection);

                if (directionsNormalized)
                {
                    targetAngle = AngleUtil.RoundAngle(targetAngle, directionRange);
                }

                var currentVelocity = avatar.physics.velocity;

                (Vector2, float, int) boost()
                {
                    avatar.physics.drag = boostDrag;

                    boostExecutionDuration++;
                    if (boostExecutionDuration >= maximumBoostExecutionDuration)
                    {
                        boostExecutionDuration = 0;
                        avatar.broom.isBoosting = false;
                        angularVelocity = 0;
                        return glide();
                    }

                    float angle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angularVelocity, boostRotationDuration, maximumRotationSpeed, deltaTime);
                    var rotation = Quaternion.Euler(0, 0, angle);
                    var targetVelocity = (Vector2)(rotation * Vector2.right * currentVelocity.magnitude);

                    var velocity = targetVelocity;

                    return (velocity, angle, avatar.physics.facing);
                }

                (Vector2, float, int) glide()
                {
                    float angle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angularVelocity, rotationDuration, maximumRotationSpeed, deltaTime);
                    var rotation = Quaternion.Euler(0, 0, angle);

                    var velocityRotation = AngleUtil.DirectionalRotation(currentVelocity);

                    float alignment = AngleUtil.Alignment(rotation, velocityRotation);

                    float alignDuration = GetAlignDuration(alignment);
                    var targetVelocity = rotation * Vector2.right * currentVelocity.magnitude;

                    avatar.physics.drag = GetDrag(alignment);

                    avatar.broom.isAligned = alignment > requiredAlignment;
                    avatar.broom.isDiving = currentVelocity.y < requiredYSpeed;
                    bool intendsBoost = targetAngle <= 180;

                    if (intendsBoost)
                    {
                        if (avatar.broom.canBoost)
                        {
                            avatar.broom.canBoost = false;
                            avatar.broom.isBoosting = true;
                            maximumBoostExecutionDuration = Mathf.Abs(currentVelocity.y) * boostExecutionDurationMultiplier;
                            onBoost.Invoke(avatar.gameObject);
                            currentVelocity += currentVelocity.normalized * boostExecutionSpeed;
                            angularVelocity = 0;
                            return boost();
                        }
                    }
                    else
                    {
                        if (avatar.broom.isAligned && avatar.broom.isDiving)
                        {
                            if (!avatar.broom.canBoost && boostGatheringDuration < minimumBoostGatheringDuration)
                            {
                                boostGatheringDuration += deltaTime;
                                if (boostGatheringDuration >= minimumBoostGatheringDuration)
                                {
                                    boostGatheringDuration = 0;
                                    avatar.broom.canBoost = true;
                                }
                            }
                        }
                    }

                    var velocity = Vector2.SmoothDamp(currentVelocity, targetVelocity, ref acceleration, alignDuration, maximumGlideAcceleration, deltaTime);
                    velocity += GetAcceleration(alignment) * Time.deltaTime * (Vector2)(rotation * Vector3.right);
                    velocity += avatar.physics.gravityStep;

                    return (velocity, angle, avatar.physics.facing);
                }

                return avatar.broom.isBoosting
                    ? boost()
                    : glide();
            });
        }
Exemplo n.º 2
0
 public void TestRoundAngle(float angle, int directions, float roundedAngle)
 {
     Assert.AreEqual(roundedAngle, AngleUtil.RoundAngle(angle, directions));
 }