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