Exemplo n.º 1
0
        public override MovementCalculator CreateMovementCalculator(AvatarController avatar)
        {
            float angularVelocity = 0;

            return(deltaTime => {
                var velocityOrientation = new AvatarOrientation(avatar.physics.velocityAngle);

                var currentOrientation = new AvatarOrientation(avatar.physics.rotationAngle);

                var velocity = avatar.physics.velocity;

                var direction = avatar.intentions.intendedFlight == Vector2.zero
                    ? avatar.physics.rotatedForward
                    : avatar.intentions.intendedFlight.normalized;
                float angle = Vector2.SignedAngle(avatar.physics.forward, direction);
                if (!avatar.canFlyLooping)
                {
                    //angle = Mathf.Clamp(angle, -90, 90);
                }
                var oldRotation = currentOrientation.rotation;
                currentOrientation.angle = Mathf.SmoothDampAngle(currentOrientation.angle, angle, ref angularVelocity, rotationDuration, maxRotationSpeed, deltaTime);

                // Gliding
                float alignment = AngleUtil.Alignment(velocityOrientation.rotation, currentOrientation.rotation);
                bool isAligned = alignment >= alignmentDeadZone;

                if (isAligned && Mathf.Abs(angularVelocity) > angularDeadZone)
                {
                    velocity = velocity.magnitude * (currentOrientation.rotation * avatar.physics.forward).SwizzleXY();
                    avatar.broom.isBoosting = true;
                }
                else
                {
                    avatar.broom.isBoosting = false;
                }

                // Drag
                avatar.physics.drag = GetDrag(alignment);
                velocity += avatar.physics.dragStep;

                // Gravity
                velocity += avatar.physics.gravityStep;

                // Thrust
                if (isAligned)
                {
                    float thrustAcceleration = GetThrust(alignment);
                    var thrustDirection = (currentOrientation.rotation * avatar.physics.forward).SwizzleXY();
                    velocity += thrustAcceleration * deltaTime * thrustDirection;
                }

                // Visuals
                avatar.broom.isAligned = isAligned;

                return (velocity, currentOrientation.angle, avatar.physics.facing);
            });
        }
Exemplo n.º 2
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.º 3
0
 public void TestAlignment(float angleA, float angleB, float alignment)
 {
     Assert.AreEqual(alignment, AngleUtil.Alignment(Quaternion.Euler(0, 0, angleA), Quaternion.Euler(0, 0, angleB)), 0.001f);
 }