From 95937694f4dde4dfd3884cd3ccef26ec54d3daf3 Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 2 Nov 2016 16:11:04 +0200 Subject: [PATCH] Colliders can "climb" over small obstacles --- .../Animation/HumanoidAnimController.cs | 120 +++++++----------- .../Source/Characters/Animation/Ragdoll.cs | 6 +- 2 files changed, 53 insertions(+), 73 deletions(-) diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 46a8ae740..eba834401 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -298,16 +298,21 @@ namespace Barotrauma if (onGround && (!character.IsRemotePlayer || GameMain.Server != null)) { collider.LinearVelocity = new Vector2( - movement.X, - collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); + movement.X, + collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); } + ClimbOverObstacles(); + getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f); torso.pullJoint.Enabled = true; head.pullJoint.Enabled = true; waist.pullJoint.Enabled = true; + collider.FarseerBody.Friction = 0.05f; + collider.FarseerBody.Restitution = 0.05f; + if (stairs != null) { torso.pullJoint.WorldAnchorB = new Vector2( @@ -454,8 +459,6 @@ namespace Barotrauma leftArm.body.SmoothRotate(0.0f, 20.0f); } } - - } void UpdateStandingSimple() @@ -466,20 +469,51 @@ namespace Barotrauma { movement = Vector2.Normalize(movement); } + } - return; - //RefLimb.pullJoint.Enabled = true; - //RefLimb.pullJoint.WorldAnchorB = - // RefLimb.SimPosition + movement * 0.15f; + private void ClimbOverObstacles() + { + if (collider.FarseerBody.ContactList == null || Math.Abs(movement.X) < 0.01f) return; - //RefLimb.body.SmoothRotate(0.0f); + //check if the collider is touching a suitable obstacle to climb over + Vector2? handle = null; + FarseerPhysics.Dynamics.Contacts.ContactEdge ce = collider.FarseerBody.ContactList; + while (ce != null && ce.Contact != null) + { + if (ce.Contact.Enabled && ce.Contact.IsTouching && ce.Contact.FixtureA.CollisionCategories.HasFlag(Physics.CollisionWall)) + { + Vector2 contactNormal; + FarseerPhysics.Common.FixedArray2 contactPos; + ce.Contact.GetWorldManifold(out contactNormal, out contactPos); - //foreach (Limb l in Limbs) - //{ - // if (l == RefLimb) continue; - // l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); - //} - //new Vector2(movement.X, floorY + HeadPosition), 0.5f); + //only climb if moving towards the obstacle + if (Math.Sign(contactPos[0].X - collider.SimPosition.X) == Math.Sign(movement.X) && + (handle == null || contactPos[0].Y > ((Vector2)handle).Y)) + { + handle = contactPos[0]; + } + } + + ce = ce.Next; + } + + if (handle == null) return; + + float colliderBottomY = GetColliderBottom().Y; + + //the contact point should be higher than the bottom of the collider + if (((Vector2)handle).Y < colliderBottomY + 0.01f) return; + + //find the height of the floor below the torso + //(if moving towards towards an obstacle that's low enough to climb over, the torso should be above it) + float obstacleY = GetFloorY(GetLimb(LimbType.Torso)); + + if (obstacleY > colliderBottomY) + { + //higher vertical velocity for taller obstacles + collider.LinearVelocity += Vector2.UnitY * (((Vector2)handle).Y - colliderBottomY + 0.01f) * 10; + onGround = true; + } } void UpdateSwimming() @@ -820,63 +854,7 @@ namespace Barotrauma var head = GetLimb(LimbType.Head); head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos); head.pullJoint.Enabled = true; - - - //RefLimb.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X - Math.Sign(headDiff.X) * 0.5f, targetHead.SimPosition.Y + 0.4f + yPos); - //head.pullJoint.Enabled = true; - - - - //DragCharacter(character.SelectedCharacter, LimbType.Torso, LimbType.Head); } - - //float punchTimer; - //bool punching; - - //public void Punch() - //{ - // if (punchTimer < 0.01f) punching = true; - - // Limb rightHand = GetLimb(LimbType.RightHand); - // Limb head = GetLimb(LimbType.Head); - - // Vector2 diff = Vector2.Normalize(Character.CursorPosition - RefLimb.Position); - - // rightHand.body.ApplyLinearImpulse(diff * 20.0f); - // head.body.ApplyLinearImpulse(diff * 5.0f); - // head.body.ApplyTorque(Dir*100.0f); - //} - - //public void Block(float deltaTime) - //{ - // Limb head = GetLimb(LimbType.Head); - // Limb torso = GetLimb(LimbType.Torso); - // Limb leftHand = GetLimb(LimbType.LeftHand); - // Limb leftFoot = GetLimb(LimbType.LeftFoot); - // Limb rightHand = GetLimb(LimbType.RightHand); - - // Vector2 pos = head.SimPosition; - - // rightHand.Disabled = true; - // leftHand.Disabled = true; - - // HandIK(leftHand, pos + new Vector2(0.25f*Dir, 0.0f)); - - // if (punching) - // { - // punchTimer += deltaTime*10.0f; - // if (punchTimer>2.0f) - // { - // punching = false; - // } - // } - // else - // { - // punchTimer = MathHelper.Lerp(punchTimer, 0.0f, 0.3f); - // HandIK(rightHand, pos + new Vector2((0.3f + punchTimer) * Dir, 0.1f)); - // } - //} - public override void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand) { if (target == null) return; diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 0a934195d..6489cb001 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -934,9 +934,11 @@ namespace Barotrauma } - private float GetFloorY() + protected float GetFloorY(Limb refLimb = null) { - Vector2 rayStart = collider.SimPosition; + PhysicsBody refBody = refLimb == null ? collider : refLimb.body; + + Vector2 rayStart = refBody.SimPosition; Vector2 rayEnd = rayStart - new Vector2(0.0f, TorsoPosition); var lowestLimb = FindLowestLimb();