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); } }
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); } } }