예제 #1
0
        private static void DrawMessages(SpriteBatch spriteBatch, float deltaTime)
        {
            if (messages.Count == 0)
            {
                return;
            }

            Vector2 currPos = new Vector2(GameMain.GraphicsWidth / 2.0f, GameMain.GraphicsHeight * 0.7f);

            int i = 1;

            foreach (GUIMessage msg in messages)
            {
                float alpha = 1.0f;

                if (msg.LifeTime < 1.0f)
                {
                    alpha -= 1.0f - msg.LifeTime;
                }

                if (msg.Centered)
                {
                    msg.Pos    = MathUtils.SmoothStep(msg.Pos, currPos, deltaTime * 20.0f);
                    currPos.Y += 30.0f;
                }

                Font.DrawString(spriteBatch, msg.Text,
                                new Vector2((int)msg.Pos.X - 1, (int)msg.Pos.Y - 1),
                                Color.Black * alpha * 0.5f, 0.0f,
                                msg.Origin, 1.0f, SpriteEffects.None, 0.0f);

                Font.DrawString(spriteBatch, msg.Text,
                                new Vector2((int)msg.Pos.X, (int)msg.Pos.Y),
                                msg.Color * alpha, 0.0f,
                                msg.Origin, 1.0f, SpriteEffects.None, 0.0f);


                messages[0].LifeTime -= deltaTime / i;

                i++;
            }

            if (messages[0].LifeTime <= 0.0f)
            {
                messages.Remove(messages[0]);
            }
        }
예제 #2
0
        void UpdateWalkAnim(float deltaTime)
        {
            if (CurrentGroundedParams == null)
            {
                return;
            }
            movement = MathUtils.SmoothStep(movement, TargetMovement, 0.2f);

            Collider.LinearVelocity = new Vector2(
                movement.X,
                Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);

            //limbs are disabled when simple physics is enabled, no need to move them
            if (SimplePhysicsEnabled)
            {
                return;
            }

            float mainLimbHeight = ColliderHeightFromFloor;

            Vector2 colliderBottom = GetColliderBottom();

            float movementAngle = 0.0f;
            float mainLimbAngle = (MainLimb.type == LimbType.Torso ? TorsoAngle ?? 0 : HeadAngle ?? 0) * Dir;

            while (MainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
            {
                movementAngle += MathHelper.TwoPi;
            }
            while (MainLimb.Rotation - (movementAngle + mainLimbAngle) < -MathHelper.Pi)
            {
                movementAngle -= MathHelper.TwoPi;
            }

            Limb torso = GetLimb(LimbType.Torso);

            if (torso != null)
            {
                if (TorsoAngle.HasValue)
                {
                    SmoothRotateWithoutWrapping(torso, movementAngle + TorsoAngle.Value * Dir, MainLimb, TorsoTorque);
                }
                if (TorsoPosition.HasValue)
                {
                    Vector2 pos = colliderBottom + Vector2.UnitY * TorsoPosition.Value;

                    if (torso != MainLimb)
                    {
                        pos.X = torso.SimPosition.X;
                    }
                    else
                    {
                        mainLimbHeight = TorsoPosition.Value;
                    }

                    torso.MoveToPos(pos, TorsoMoveForce);
                    torso.PullJointEnabled      = true;
                    torso.PullJointWorldAnchorB = pos;
                }
            }

            Limb head = GetLimb(LimbType.Head);

            if (head != null)
            {
                if (HeadAngle.HasValue)
                {
                    SmoothRotateWithoutWrapping(head, movementAngle + HeadAngle.Value * Dir, MainLimb, HeadTorque);
                }
                if (HeadPosition.HasValue)
                {
                    Vector2 pos = colliderBottom + Vector2.UnitY * HeadPosition.Value;

                    if (head != MainLimb)
                    {
                        pos.X = head.SimPosition.X;
                    }
                    else
                    {
                        mainLimbHeight = HeadPosition.Value;
                    }

                    head.MoveToPos(pos, HeadMoveForce);
                    head.PullJointEnabled      = true;
                    head.PullJointWorldAnchorB = pos;
                }
            }

            if (TailAngle.HasValue)
            {
                var tail = GetLimb(LimbType.Tail);
                if (tail != null)
                {
                    SmoothRotateWithoutWrapping(tail, movementAngle + TailAngle.Value * Dir, MainLimb, TailTorque);
                }
            }

            WalkPos -= MainLimb.LinearVelocity.X * (CurrentAnimationParams.CycleSpeed / RagdollParams.JointScale / 100.0f);

            Vector2 transformedStepSize = Vector2.Zero;

            if (Math.Abs(TargetMovement.X) > 0.01f)
            {
                transformedStepSize = new Vector2(
                    (float)Math.Cos(WalkPos) * StepSize.Value.X * 3.0f,
                    (float)Math.Sin(WalkPos) * StepSize.Value.Y * 2.0f);
            }

            foreach (Limb limb in Limbs)
            {
                switch (limb.type)
                {
                case LimbType.LeftFoot:
                case LimbType.RightFoot:
                    Vector2 footPos = new Vector2(limb.SimPosition.X, colliderBottom.Y);

                    if (limb.RefJointIndex > -1)
                    {
                        if (LimbJoints.Length <= limb.RefJointIndex)
                        {
                            DebugConsole.ThrowError($"Reference joint index {limb.RefJointIndex} is out of array. This is probably due to a missing joint. If you just deleted a joint, don't do that without first removing the reference joint indices from the limbs. If this is not the case, please ensure that you have defined the index to the right joint.");
                        }
                        else
                        {
                            footPos.X = LimbJoints[limb.RefJointIndex].WorldAnchorA.X;
                        }
                    }
                    footPos.X += limb.StepOffset.X * Dir;
                    footPos.Y += limb.StepOffset.Y;

                    if (limb.type == LimbType.LeftFoot)
                    {
                        limb.DebugRefPos    = footPos + Vector2.UnitX * movement.X * 0.1f;
                        limb.DebugTargetPos = footPos + new Vector2(
                            transformedStepSize.X + movement.X * 0.1f,
                            (transformedStepSize.Y > 0.0f) ? transformedStepSize.Y : 0.0f);
                        limb.MoveToPos(limb.DebugTargetPos, FootMoveForce);
                    }
                    else if (limb.type == LimbType.RightFoot)
                    {
                        limb.DebugRefPos    = footPos + Vector2.UnitX * movement.X * 0.1f;
                        limb.DebugTargetPos = footPos + new Vector2(
                            -transformedStepSize.X + movement.X * 0.1f,
                            (-transformedStepSize.Y > 0.0f) ? -transformedStepSize.Y : 0.0f);
                        limb.MoveToPos(limb.DebugTargetPos, FootMoveForce);
                    }

                    if (CurrentGroundedParams.FootAnglesInRadians.ContainsKey(limb.limbParams.ID))
                    {
                        SmoothRotateWithoutWrapping(limb,
                                                    movementAngle + CurrentGroundedParams.FootAnglesInRadians[limb.limbParams.ID] * Dir,
                                                    MainLimb, FootTorque);
                    }
                    break;

                case LimbType.LeftLeg:
                case LimbType.RightLeg:
                    if (Math.Abs(CurrentGroundedParams.LegTorque) > 0.001f)
                    {
                        limb.body.ApplyTorque(limb.Mass * CurrentGroundedParams.LegTorque * Dir);
                    }
                    break;
                }
            }
        }
예제 #3
0
        void UpdateWalkAnim(float deltaTime)
        {
            movement = MathUtils.SmoothStep(movement, TargetMovement, 0.2f);

            Collider.LinearVelocity = new Vector2(
                movement.X,
                Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);

            //limbs are disabled when simple physics is enabled, no need to move them
            if (SimplePhysicsEnabled)
            {
                return;
            }

            Vector2 colliderBottom = GetColliderBottom();

            float movementAngle = 0.0f;
            var   mainLimb      = MainLimb;
            float mainLimbAngle = (mainLimb.type == LimbType.Torso ? TorsoAngle ?? 0 : HeadAngle ?? 0) * Dir;

            while (mainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
            {
                movementAngle += MathHelper.TwoPi;
            }
            while (mainLimb.Rotation - (movementAngle + mainLimbAngle) < -MathHelper.Pi)
            {
                movementAngle -= MathHelper.TwoPi;
            }

            float stepLift = TargetMovement.X == 0.0f ? 0 :
                             (float)Math.Sin(WalkPos * CurrentGroundedParams.StepLiftFrequency + MathHelper.Pi * CurrentGroundedParams.StepLiftOffset) * (CurrentGroundedParams.StepLiftAmount / 100);

            float limpAmount = character.GetLegPenalty();

            if (limpAmount > 0)
            {
                float walkPosX = (float)Math.Cos(WalkPos);
                //make the footpos oscillate when limping
                limpAmount = Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * Math.Min(Math.Abs(TargetMovement.X), 0.3f) * Dir;
            }

            Limb torso = GetLimb(LimbType.Torso);

            if (torso != null)
            {
                if (TorsoAngle.HasValue)
                {
                    SmoothRotateWithoutWrapping(torso, movementAngle + TorsoAngle.Value * Dir, mainLimb, TorsoTorque);
                }
                if (TorsoPosition.HasValue)
                {
                    Vector2 pos = colliderBottom + new Vector2(limpAmount, TorsoPosition.Value + stepLift);

                    if (torso != mainLimb)
                    {
                        pos.X = torso.SimPosition.X;
                    }

                    torso.MoveToPos(pos, TorsoMoveForce);
                    torso.PullJointEnabled      = true;
                    torso.PullJointWorldAnchorB = pos;
                }
            }

            Limb head = GetLimb(LimbType.Head);

            if (head != null)
            {
                if (HeadAngle.HasValue)
                {
                    SmoothRotateWithoutWrapping(head, movementAngle + HeadAngle.Value * Dir, mainLimb, HeadTorque);
                }
                if (HeadPosition.HasValue)
                {
                    Vector2 pos = colliderBottom + new Vector2(limpAmount, HeadPosition.Value + stepLift * CurrentGroundedParams.StepLiftHeadMultiplier);

                    if (head != mainLimb)
                    {
                        pos.X = head.SimPosition.X;
                    }

                    head.MoveToPos(pos, HeadMoveForce);
                    head.PullJointEnabled      = true;
                    head.PullJointWorldAnchorB = pos;
                }
            }

            if (TailAngle.HasValue)
            {
                var tail = GetLimb(LimbType.Tail);
                if (tail != null)
                {
                    SmoothRotateWithoutWrapping(tail, movementAngle + TailAngle.Value * Dir, mainLimb, TailTorque);
                }
            }

            float prevWalkPos = WalkPos;

            WalkPos -= mainLimb.LinearVelocity.X * (CurrentAnimationParams.CycleSpeed / RagdollParams.JointScale / 100.0f);

            Vector2 transformedStepSize = Vector2.Zero;

            if (Math.Abs(TargetMovement.X) > 0.01f)
            {
                transformedStepSize = new Vector2(
                    (float)Math.Cos(WalkPos) * StepSize.Value.X * 3.0f,
                    (float)Math.Sin(WalkPos) * StepSize.Value.Y * 2.0f);
            }

            foreach (Limb limb in Limbs)
            {
                if (limb.IsSevered)
                {
                    continue;
                }
                if (Math.Abs(limb.Params.ConstantTorque) > 0)
                {
                    limb.body.SmoothRotate(movementAngle + MathHelper.ToRadians(limb.Params.ConstantAngle) * Dir, limb.Params.ConstantTorque, wrapAngle: true);
                }
                switch (limb.type)
                {
                case LimbType.LeftFoot:
                case LimbType.RightFoot:
                    Vector2 footPos = new Vector2(limb.SimPosition.X, colliderBottom.Y);

                    if (limb.RefJointIndex > -1)
                    {
                        if (LimbJoints.Length <= limb.RefJointIndex)
                        {
                            DebugConsole.ThrowError($"Reference joint index {limb.RefJointIndex} is out of array. This is probably due to a missing joint. If you just deleted a joint, don't do that without first removing the reference joint indices from the limbs. If this is not the case, please ensure that you have defined the index to the right joint.");
                        }
                        else
                        {
                            footPos.X = LimbJoints[limb.RefJointIndex].WorldAnchorA.X;
                        }
                    }
                    footPos.X += limb.StepOffset.X * Dir;
                    footPos.Y += limb.StepOffset.Y;

                    bool playFootstepSound = false;
                    if (limb.type == LimbType.LeftFoot)
                    {
                        if (Math.Sign(Math.Sin(prevWalkPos)) > 0 && Math.Sign(transformedStepSize.Y) < 0)
                        {
                            playFootstepSound = true;
                        }

                        limb.DebugRefPos    = footPos + Vector2.UnitX * movement.X * 0.1f;
                        limb.DebugTargetPos = footPos + new Vector2(
                            transformedStepSize.X + movement.X * 0.1f,
                            (transformedStepSize.Y > 0.0f) ? transformedStepSize.Y : 0.0f);
                        limb.MoveToPos(limb.DebugTargetPos, FootMoveForce);
                    }
                    else if (limb.type == LimbType.RightFoot)
                    {
                        if (Math.Sign(Math.Sin(prevWalkPos)) < 0 && Math.Sign(transformedStepSize.Y) > 0)
                        {
                            playFootstepSound = true;
                        }

                        limb.DebugRefPos    = footPos + Vector2.UnitX * movement.X * 0.1f;
                        limb.DebugTargetPos = footPos + new Vector2(
                            -transformedStepSize.X + movement.X * 0.1f,
                            (-transformedStepSize.Y > 0.0f) ? -transformedStepSize.Y : 0.0f);
                        limb.MoveToPos(limb.DebugTargetPos, FootMoveForce);
                    }

                    if (playFootstepSound)
                    {
#if CLIENT
                        PlayImpactSound(limb);
#endif
                    }

                    if (CurrentGroundedParams.FootAnglesInRadians.ContainsKey(limb.Params.ID))
                    {
                        SmoothRotateWithoutWrapping(limb,
                                                    movementAngle + CurrentGroundedParams.FootAnglesInRadians[limb.Params.ID] * Dir,
                                                    mainLimb, FootTorque);
                    }
                    break;

                case LimbType.LeftLeg:
                case LimbType.RightLeg:
                    if (Math.Abs(CurrentGroundedParams.LegTorque) > 0)
                    {
                        limb.body.ApplyTorque(limb.Mass * CurrentGroundedParams.LegTorque * Dir);
                    }
                    break;
                }
            }
        }
예제 #4
0
        void UpdateWalkAnim(float deltaTime)
        {
            movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, 0.2f);

            Collider.LinearVelocity = new Vector2(
                movement.X,
                Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);

            //limbs are disabled when simple physics is enabled, no need to move them
            if (SimplePhysicsEnabled)
            {
                return;
            }

            float mainLimbHeight, mainLimbAngle;

            if (MainLimb.type == LimbType.Torso)
            {
                mainLimbHeight = TorsoPosition;
                mainLimbAngle  = torsoAngle;
            }
            else
            {
                mainLimbHeight = HeadPosition;
                mainLimbAngle  = headAngle;
            }

            MainLimb.body.SmoothRotate(mainLimbAngle * Dir, 50.0f);

            MainLimb.MoveToPos(GetColliderBottom() + Vector2.UnitY * mainLimbHeight, 10.0f);

            MainLimb.PullJointEnabled      = true;
            MainLimb.PullJointWorldAnchorB = GetColliderBottom() + Vector2.UnitY * mainLimbHeight;

            walkPos -= MainLimb.LinearVelocity.X * 0.05f;

            Vector2 transformedStepSize = new Vector2(
                (float)Math.Cos(walkPos) * stepSize.X * 3.0f,
                (float)Math.Sin(walkPos) * stepSize.Y * 2.0f);

            foreach (Limb limb in Limbs)
            {
                switch (limb.type)
                {
                case LimbType.LeftFoot:
                case LimbType.RightFoot:
                    Vector2 footPos = new Vector2(limb.SimPosition.X, MainLimb.SimPosition.Y - mainLimbHeight);

                    if (limb.RefJointIndex > -1)
                    {
                        RevoluteJoint refJoint = LimbJoints[limb.RefJointIndex];
                        footPos.X = refJoint.WorldAnchorA.X;
                    }
                    footPos.X += limb.StepOffset.X * Dir;
                    footPos.Y += limb.StepOffset.Y;

                    if (limb.type == LimbType.LeftFoot)
                    {
                        limb.MoveToPos(footPos + new Vector2(
                                           transformedStepSize.X + movement.X * 0.1f,
                                           (transformedStepSize.Y > 0.0f) ? transformedStepSize.Y : 0.0f),
                                       8.0f);
                    }
                    else if (limb.type == LimbType.RightFoot)
                    {
                        limb.MoveToPos(footPos + new Vector2(
                                           -transformedStepSize.X + movement.X * 0.1f,
                                           (-transformedStepSize.Y > 0.0f) ? -transformedStepSize.Y : 0.0f),
                                       8.0f);
                    }

                    if (footRotation != null)
                    {
                        limb.body.SmoothRotate((float)footRotation * Dir, 50.0f);
                    }

                    break;

                case LimbType.LeftLeg:
                case LimbType.RightLeg:
                    if (legTorque != 0.0f)
                    {
                        limb.body.ApplyTorque(limb.Mass * legTorque * Dir);
                    }
                    break;
                }
            }
        }
예제 #5
0
        void UpdateClimbing()
        {
            if (character.SelectedConstruction == null || character.SelectedConstruction.GetComponent <Ladder>() == null)
            {
                Anim = Animation.None;
                return;
            }

            onGround        = false;
            IgnorePlatforms = true;

            Vector2 tempTargetMovement = TargetMovement;

            tempTargetMovement.Y = Math.Min(tempTargetMovement.Y, 1.0f);

            movement = MathUtils.SmoothStep(movement, tempTargetMovement, 0.3f);

            Limb leftFoot  = GetLimb(LimbType.LeftFoot);
            Limb rightFoot = GetLimb(LimbType.RightFoot);
            Limb head      = GetLimb(LimbType.Head);
            Limb torso     = GetLimb(LimbType.Torso);

            Limb waist = GetLimb(LimbType.Waist);

            Limb leftHand  = GetLimb(LimbType.LeftHand);
            Limb rightHand = GetLimb(LimbType.RightHand);

            Vector2 ladderSimPos = ConvertUnits.ToSimUnits(
                character.SelectedConstruction.Rect.X + character.SelectedConstruction.Rect.Width / 2.0f,
                character.SelectedConstruction.Rect.Y);

            float stepHeight = ConvertUnits.ToSimUnits(30.0f);

            if (currentHull == null && character.SelectedConstruction.Submarine != null)
            {
                ladderSimPos += character.SelectedConstruction.Submarine.SimPosition;
            }
            else if (currentHull.Submarine != null && currentHull.Submarine != character.SelectedConstruction.Submarine)
            {
                ladderSimPos += character.SelectedConstruction.Submarine.SimPosition - currentHull.Submarine.SimPosition;
            }

            MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.9f - colliderHeightFromFloor), 10.5f);
            MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.7f - colliderHeightFromFloor), 10.5f);
            MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, Collider.SimPosition.Y + 0.6f - colliderHeightFromFloor), 10.5f);

            Collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, Collider.SimPosition.Y), 10.5f);

            bool slide = targetMovement.Y < -1.1f;

            Vector2 handPos = new Vector2(
                ladderSimPos.X,
                Collider.SimPosition.Y + 0.8f + movement.Y * 0.1f - ladderSimPos.Y);

            handPos.Y = Math.Min(-0.2f, handPos.Y) - colliderHeightFromFloor;

            MoveLimb(leftHand,
                     new Vector2(handPos.X,
                                 (slide ? handPos.Y : MathUtils.Round(handPos.Y - stepHeight, stepHeight * 2.0f) + stepHeight) + ladderSimPos.Y),
                     5.2f);

            MoveLimb(rightHand,
                     new Vector2(handPos.X,
                                 (slide ? handPos.Y : MathUtils.Round(handPos.Y, stepHeight * 2.0f)) + ladderSimPos.Y),
                     5.2f);

            leftHand.body.ApplyTorque(Dir * 2.0f);
            rightHand.body.ApplyTorque(Dir * 2.0f);

            Vector2 footPos = new Vector2(
                handPos.X - Dir * 0.05f,
                Collider.SimPosition.Y + 0.9f - colliderHeightFromFloor - stepHeight * 2.7f - ladderSimPos.Y - 0.7f);

            //if (movement.Y < 0) footPos.Y += 0.05f;

            MoveLimb(leftFoot,
                     new Vector2(footPos.X,
                                 (slide ? footPos.Y : MathUtils.Round(footPos.Y + stepHeight, stepHeight * 2.0f) - stepHeight) + ladderSimPos.Y),
                     15.5f, true);

            MoveLimb(rightFoot,
                     new Vector2(footPos.X,
                                 (slide ? footPos.Y : MathUtils.Round(footPos.Y, stepHeight * 2.0f)) + ladderSimPos.Y),
                     15.5f, true);

            //apply torque to the legs to make the knees bend
            Limb leftLeg  = GetLimb(LimbType.LeftLeg);
            Limb rightLeg = GetLimb(LimbType.RightLeg);

            leftLeg.body.ApplyTorque(Dir * -8.0f);
            rightLeg.body.ApplyTorque(Dir * -8.0f);

            float movementFactor = (handPos.Y / stepHeight) * (float)Math.PI;

            movementFactor = 0.8f + (float)Math.Abs(Math.Sin(movementFactor));

            Vector2 subSpeed = currentHull != null || character.SelectedConstruction.Submarine == null
                ? Vector2.Zero : character.SelectedConstruction.Submarine.Velocity;

            Vector2 climbForce = new Vector2(0.0f, movement.Y + 0.3f) * movementFactor;

            //if (climbForce.Y > 0.5f) climbForce.Y = Math.Max(climbForce.Y, 1.3f);

            //apply forces to the collider to move the Character up/down
            Collider.ApplyForce((climbForce * 20.0f + subSpeed * 50.0f) * Collider.Mass);
            head.body.SmoothRotate(0.0f);

            if (!character.SelectedConstruction.Prefab.Triggers.Any())
            {
                character.SelectedConstruction = null;
                return;
            }

            Rectangle trigger = character.SelectedConstruction.Prefab.Triggers.FirstOrDefault();

            trigger = character.SelectedConstruction.TransformTrigger(trigger);

            bool notClimbing = false;

            if (character.IsRemotePlayer && GameMain.Server == null)
            {
                notClimbing = character.IsKeyDown(InputType.Left) || character.IsKeyDown(InputType.Right);
            }
            else
            {
                notClimbing = Math.Abs(targetMovement.X) > 0.05f ||
                              (TargetMovement.Y < 0.0f && ConvertUnits.ToSimUnits(trigger.Height) + handPos.Y < HeadPosition) ||
                              (TargetMovement.Y > 0.0f && handPos.Y > 0.1f);
            }

            if (notClimbing)
            {
                Anim = Animation.None;
                character.SelectedConstruction = null;
                IgnorePlatforms = false;
            }
        }
예제 #6
0
        void UpdateSwimming()
        {
            IgnorePlatforms = true;

            Vector2 footPos, handPos;

            float surfaceLimiter = 1.0f;

            Limb head  = GetLimb(LimbType.Head);
            Limb torso = GetLimb(LimbType.Torso);

            if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f))
            {
                surfaceLimiter = (ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 0.4f) - surfaceY);
                surfaceLimiter = Math.Max(1.0f, surfaceLimiter);
                if (surfaceLimiter > 50.0f)
                {
                    return;
                }
            }

            Limb leftHand  = GetLimb(LimbType.LeftHand);
            Limb rightHand = GetLimb(LimbType.RightHand);

            Limb leftFoot  = GetLimb(LimbType.LeftFoot);
            Limb rightFoot = GetLimb(LimbType.RightFoot);

            float rotation = MathHelper.WrapAngle(Collider.Rotation);

            rotation = MathHelper.ToDegrees(rotation);
            if (rotation < 0.0f)
            {
                rotation += 360;
            }

            if (!character.IsRemotePlayer && !aiming && Anim != Animation.UsingConstruction)
            {
                if (rotation > 20 && rotation < 170)
                {
                    TargetDir = Direction.Left;
                }
                else if (rotation > 190 && rotation < 340)
                {
                    TargetDir = Direction.Right;
                }
            }

            float targetSpeed = TargetMovement.Length();

            if (targetSpeed > 0.1f)
            {
                if (!aiming)
                {
                    float newRotation = MathUtils.VectorToAngle(TargetMovement) - MathHelper.PiOver2;
                    Collider.SmoothRotate(newRotation, 5.0f);
                    //torso.body.SmoothRotate(newRotation);
                }
            }
            else
            {
                if (aiming)
                {
                    Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
                    Vector2 diff     = (mousePos - torso.SimPosition) * Dir;

                    TargetMovement = new Vector2(0.0f, -0.1f);

                    float newRotation = MathUtils.VectorToAngle(diff);
                    Collider.SmoothRotate(newRotation, 5.0f);
                }
            }

            torso.body.SmoothRotate(Collider.Rotation);
            torso.body.MoveToPos(Collider.SimPosition + new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * 0.4f, 5.0f);

            if (TargetMovement == Vector2.Zero)
            {
                return;
            }

            movement = MathUtils.SmoothStep(movement, TargetMovement, 0.3f);

            //dont try to move upwards if head is already out of water
            if (surfaceLimiter > 1.0f && TargetMovement.Y > 0.0f)
            {
                if (TargetMovement.X == 0.0f)
                {
                    //pull head above water
                    head.body.SmoothRotate(0.0f, 5.0f);

                    walkPos += 0.05f;
                }
                else
                {
                    TargetMovement = new Vector2(
                        (float)Math.Sqrt(targetSpeed * targetSpeed - TargetMovement.Y * TargetMovement.Y)
                        * Math.Sign(TargetMovement.X),
                        Math.Max(TargetMovement.Y, TargetMovement.Y * 0.2f));

                    //turn head above the water
                    head.body.ApplyTorque(Dir);
                }

                movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f;
            }

            if (!character.IsRemotePlayer || GameMain.Server != null)
            {
                Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement * swimSpeed, movementLerp);
            }

            walkPos += movement.Length() * 0.2f;
            footPos  = Collider.SimPosition - new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * 0.4f;

            for (int i = -1; i < 2; i += 2)
            {
                var thigh = i == -1 ? GetLimb(LimbType.LeftThigh) : GetLimb(LimbType.RightThigh);
                var leg   = i == -1 ? GetLimb(LimbType.LeftLeg) : GetLimb(LimbType.RightLeg);

                float thighDiff = Math.Abs(MathUtils.GetShortestAngle(torso.Rotation, thigh.Rotation));
                if (thighDiff > MathHelper.PiOver2)
                {
                    //thigh bent too close to the torso -> force the leg to extend
                    float thighTorque = thighDiff * thigh.Mass * Math.Sign(torso.Rotation - thigh.Rotation) * 10.0f;
                    thigh.body.ApplyTorque(thighTorque);
                    leg.body.ApplyTorque(thighTorque);
                }
                else
                {
                    thigh.body.SmoothRotate(torso.Rotation + (float)Math.Sin(walkPos) * i * 0.3f, 2.0f);
                }
            }

            Vector2 transformedFootPos = new Vector2((float)Math.Sin(walkPos) * 0.5f, 0.0f);

            transformedFootPos = Vector2.Transform(
                transformedFootPos,
                Matrix.CreateRotationZ(Collider.Rotation));

            MoveLimb(rightFoot, footPos - transformedFootPos, 1.0f);
            MoveLimb(leftFoot, footPos + transformedFootPos, 1.0f);

            handPos = (torso.SimPosition + head.SimPosition) / 2.0f;

            //at the surface, not moving sideways -> hands just float around
            if (!headInWater && TargetMovement.X == 0.0f && TargetMovement.Y > 0)
            {
                handPos.X = handPos.X + Dir * 0.6f;

                float wobbleAmount = 0.1f;

                if (!rightHand.Disabled)
                {
                    MoveLimb(rightHand, new Vector2(
                                 handPos.X + (float)Math.Sin(walkPos / 1.5f) * wobbleAmount,
                                 handPos.Y + (float)Math.Sin(walkPos / 3.5f) * wobbleAmount - 0.25f), 1.5f);
                }

                if (!leftHand.Disabled)
                {
                    MoveLimb(leftHand, new Vector2(
                                 handPos.X + (float)Math.Sin(walkPos / 2.0f) * wobbleAmount,
                                 handPos.Y + (float)Math.Sin(walkPos / 3.0f) * wobbleAmount - 0.25f), 1.5f);
                }

                return;
            }

            handPos += head.LinearVelocity * 0.1f;

            float handCyclePos = walkPos / 2.0f * -Dir;
            float handPosX     = (float)Math.Cos(handCyclePos) * 0.4f;
            float handPosY     = (float)Math.Sin(handCyclePos) * 1.0f;

            handPosY = MathHelper.Clamp(handPosY, -0.8f, 0.8f);

            Matrix rotationMatrix = Matrix.CreateRotationZ(torso.Rotation);

            if (!rightHand.Disabled)
            {
                Vector2 rightHandPos = new Vector2(-handPosX, -handPosY);
                rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, rightHandPos.X) : Math.Min(-0.3f, rightHandPos.X);
                rightHandPos   = Vector2.Transform(rightHandPos, rotationMatrix);

                HandIK(rightHand, handPos + rightHandPos, 0.5f);
            }

            if (!leftHand.Disabled)
            {
                Vector2 leftHandPos = new Vector2(handPosX, handPosY);
                leftHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, leftHandPos.X) : Math.Min(-0.3f, leftHandPos.X);
                leftHandPos   = Vector2.Transform(leftHandPos, rotationMatrix);

                HandIK(leftHand, handPos + leftHandPos, 0.5f);
            }
        }
예제 #7
0
        void UpdateStanding()
        {
            Vector2 handPos;

            //if you're allergic to magic numbers, stop reading now

            Limb leftFoot  = GetLimb(LimbType.LeftFoot);
            Limb rightFoot = GetLimb(LimbType.RightFoot);
            Limb head      = GetLimb(LimbType.Head);
            Limb torso     = GetLimb(LimbType.Torso);

            Limb waist = GetLimb(LimbType.Waist);

            Limb leftHand  = GetLimb(LimbType.LeftHand);
            Limb rightHand = GetLimb(LimbType.RightHand);

            Limb leftLeg  = GetLimb(LimbType.LeftLeg);
            Limb rightLeg = GetLimb(LimbType.RightLeg);

            float getUpSpeed     = 0.3f;
            float walkCycleSpeed = movement.X * walkAnimSpeed;

            if (stairs != null)
            {
                TargetMovement = new Vector2(MathHelper.Clamp(TargetMovement.X, -1.5f, 1.5f), TargetMovement.Y);

                /*if ((TargetMovement.X > 0.0f && stairs.StairDirection == Direction.Right) ||
                 *  TargetMovement.X < 0.0f && stairs.StairDirection == Direction.Left)
                 * {
                 *  TargetMovement *= 1.7f;
                 *  //walkCycleSpeed *= 1.0f;
                 * }*/
            }

            Vector2 colliderPos = GetColliderBottom();

            if (Math.Abs(TargetMovement.X) > 1.0f)
            {
                float slowdownAmount = 0.0f;
                if (currentHull != null)
                {
                    //full slowdown (1.5f) when water is up to the torso
                    surfaceY       = ConvertUnits.ToSimUnits(currentHull.Surface);
                    slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / torsoPosition, 0.0f, 1.0f) * 1.5f;
                }

                float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 1.0f);
                TargetMovement = Vector2.Normalize(TargetMovement) * maxSpeed;
            }

            float walkPosX        = (float)Math.Cos(walkPos);
            float walkPosY        = (float)Math.Sin(walkPos);
            float runningModifier = (float)Math.Max(Math.Min(Math.Abs(TargetMovement.X), 3.0f) / 1.5f, 1.0);

            Vector2 stepSize = new Vector2(
                this.stepSize.X * walkPosX * runningModifier,
                this.stepSize.Y * walkPosY * runningModifier * runningModifier);

            if (Crouching)
            {
                stepSize *= 0.5f;
            }

            float footMid = colliderPos.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f;

            movement = overrideTargetMovement == Vector2.Zero ?
                       MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp) :
                       overrideTargetMovement;

            if (Math.Abs(movement.X) < 0.005f)
            {
                movement.X = 0.0f;
            }

            movement.Y = 0.0f;

            for (int i = 0; i < 2; i++)
            {
                Limb leg = GetLimb((i == 0) ? LimbType.LeftThigh : LimbType.RightThigh);// : leftLeg;

                float shortestAngle = leg.Rotation - torso.Rotation;

                if (Math.Abs(shortestAngle) < 2.5f)
                {
                    continue;
                }

                if (Math.Abs(shortestAngle) > 5.0f)
                {
                    TargetDir = TargetDir == Direction.Right ? Direction.Left : Direction.Right;
                }
                else
                {
                    leg.body.ApplyTorque(shortestAngle * 10.0f);

                    leg = GetLimb((i == 0) ? LimbType.LeftLeg : LimbType.RightLeg);
                    leg.body.ApplyTorque(-shortestAngle * 10.0f);
                }
            }

            if (onGround && (!character.IsRemotePlayer || GameMain.Server != null))
            {
                //move slower if collider isn't upright
                float rotationFactor = (float)Math.Abs(Math.Cos(Collider.Rotation));

                Collider.LinearVelocity = new Vector2(
                    movement.X * rotationFactor,
                    Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);
            }

            getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f);

            torso.pullJoint.Enabled = true;
            head.pullJoint.Enabled  = true;
            waist.pullJoint.Enabled = true;

            float floorPos = GetFloorY(colliderPos + new Vector2(Math.Sign(movement.X) * 0.5f, 1.0f));
            bool  onSlope  = floorPos > GetColliderBottom().Y + 0.05f;

            if (stairs != null || onSlope)
            {
                torso.pullJoint.WorldAnchorB = new Vector2(
                    MathHelper.SmoothStep(torso.SimPosition.X, footMid + movement.X * 0.25f, getUpSpeed * 0.8f),
                    MathHelper.SmoothStep(torso.SimPosition.Y, colliderPos.Y + TorsoPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f));


                head.pullJoint.WorldAnchorB = new Vector2(
                    MathHelper.SmoothStep(head.SimPosition.X, footMid + movement.X * (Crouching ? 0.6f : 0.25f), getUpSpeed * 0.8f),
                    MathHelper.SmoothStep(head.SimPosition.Y, colliderPos.Y + HeadPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f));

                waist.pullJoint.WorldAnchorB = waist.SimPosition;// +movement * 0.3f;
            }
            else
            {
                if (!onGround)
                {
                    movement = Vector2.Zero;
                }

                torso.pullJoint.WorldAnchorB =
                    MathUtils.SmoothStep(torso.SimPosition,
                                         new Vector2(footMid + movement.X * 0.2f, colliderPos.Y + TorsoPosition), getUpSpeed);

                head.pullJoint.WorldAnchorB =
                    MathUtils.SmoothStep(head.SimPosition,
                                         new Vector2(footMid + movement.X * (Crouching && Math.Sign(movement.X) == Math.Sign(Dir) ? 0.6f : 0.2f), colliderPos.Y + HeadPosition), getUpSpeed * 1.2f);

                waist.pullJoint.WorldAnchorB = waist.SimPosition + movement * 0.06f;
            }

            if (!onGround)
            {
                Vector2 move = torso.pullJoint.WorldAnchorB - torso.SimPosition;

                foreach (Limb limb in Limbs)
                {
                    MoveLimb(limb, limb.SimPosition + move, 15.0f, true);
                }

                return;
            }

            //moving horizontally
            if (TargetMovement.X != 0.0f)
            {
                //progress the walking animation
                walkPos -= (walkCycleSpeed / runningModifier) * 0.8f;

                for (int i = -1; i < 2; i += 2)
                {
                    Limb foot = i == -1 ? leftFoot : rightFoot;
                    Limb leg  = i == -1 ? leftLeg : rightLeg;

                    Vector2 footPos = stepSize * -i;
                    if (stepSize.Y < 0.0f)
                    {
                        stepSize.Y = -0.15f;
                    }

                    if (onSlope && stairs == null)
                    {
                        footPos.Y *= 2.0f;
                    }
                    footPos.Y = Math.Min(waist.SimPosition.Y - colliderPos.Y - 0.4f, footPos.Y);

                    MoveLimb(foot, footPos + colliderPos, 15.0f, true);
                    foot.body.SmoothRotate(leg.body.Rotation + MathHelper.PiOver2 * Dir * 1.6f, 20.0f * runningModifier);
                }

                if (runningModifier > 1.0f)
                {
                    if (walkPosY > 0.0f)
                    {
                        GetLimb(LimbType.LeftThigh).body.ApplyTorque(-walkPosY * Dir * Math.Abs(movement.X) * thighTorque);
                    }
                    else
                    {
                        GetLimb(LimbType.RightThigh).body.ApplyTorque(walkPosY * Dir * Math.Abs(movement.X) * thighTorque);
                    }
                }

                if (legTorque > 0.0f)
                {
                    if (Math.Sign(walkPosX) != Math.Sign(movement.X))
                    {
                        GetLimb(LimbType.LeftLeg).body.ApplyTorque(-walkPosY * Dir * Math.Abs(movement.X) * legTorque / runningModifier);
                    }
                    else
                    {
                        GetLimb(LimbType.RightLeg).body.ApplyTorque(walkPosY * Dir * Math.Abs(movement.X) * legTorque / runningModifier);
                    }
                }

                //calculate the positions of hands
                handPos   = torso.SimPosition;
                handPos.X = -walkPosX * 0.4f;

                float lowerY = -1.0f + (runningModifier - 1.0f) * 0.8f;

                handPos.Y = lowerY + (float)(Math.Abs(Math.Sin(walkPos - Math.PI * 1.5f) * 0.15 * runningModifier));

                Vector2 posAddition = new Vector2(-movement.X * 0.015f * runningModifier, 0.0f);

                if (!rightHand.Disabled)
                {
                    HandIK(rightHand, torso.SimPosition + posAddition +
                           new Vector2(
                               -handPos.X,
                               (Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY), 0.7f * runningModifier);
                }

                if (!leftHand.Disabled)
                {
                    HandIK(leftHand, torso.SimPosition + posAddition +
                           new Vector2(
                               handPos.X,
                               (Math.Sign(walkPosX) == Math.Sign(-Dir)) ? handPos.Y : lowerY), 0.7f * runningModifier);
                }
            }
            else
            {
                //float movementFactor = (movement.X / 4.0f) * movement.X * Math.Sign(movement.X);

                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 footPos = colliderPos;

                    if (Crouching)
                    {
                        footPos = new Vector2(
                            waist.SimPosition.X + Math.Sign(stepSize.X * i) * Dir * 0.3f,
                            colliderPos.Y - 0.1f);
                    }
                    else
                    {
                        footPos = new Vector2(GetCenterOfMass().X + stepSize.X * i * 0.2f, colliderPos.Y - 0.1f);
                    }

                    if (stairs == null)
                    {
                        footPos.Y = Math.Max(Math.Min(floorPos, footPos.Y + 0.5f), footPos.Y);
                    }

                    var foot = i == -1 ? rightFoot : leftFoot;

                    MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X) * 100.0f, true);
                }

                leftFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f);
                rightFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f);

                if (!rightHand.Disabled)
                {
                    rightHand.body.SmoothRotate(0.0f, 5.0f);

                    var rightArm = GetLimb(LimbType.RightArm);
                    rightArm.body.SmoothRotate(0.0f, 20.0f);
                }

                if (!leftHand.Disabled)
                {
                    leftHand.body.SmoothRotate(0.0f, 5.0f);

                    var leftArm = GetLimb(LimbType.LeftArm);
                    leftArm.body.SmoothRotate(0.0f, 20.0f);
                }
            }
        }