Colliders can "climb" over small obstacles

This commit is contained in:
Regalis
2016-11-02 16:11:04 +02:00
parent 3cc807605e
commit 95937694f4
2 changed files with 53 additions and 73 deletions
@@ -298,16 +298,21 @@ namespace Barotrauma
if (onGround && (!character.IsRemotePlayer || GameMain.Server != null)) if (onGround && (!character.IsRemotePlayer || GameMain.Server != null))
{ {
collider.LinearVelocity = new Vector2( collider.LinearVelocity = new Vector2(
movement.X, movement.X,
collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); 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); getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f);
torso.pullJoint.Enabled = true; torso.pullJoint.Enabled = true;
head.pullJoint.Enabled = true; head.pullJoint.Enabled = true;
waist.pullJoint.Enabled = true; waist.pullJoint.Enabled = true;
collider.FarseerBody.Friction = 0.05f;
collider.FarseerBody.Restitution = 0.05f;
if (stairs != null) if (stairs != null)
{ {
torso.pullJoint.WorldAnchorB = new Vector2( torso.pullJoint.WorldAnchorB = new Vector2(
@@ -454,8 +459,6 @@ namespace Barotrauma
leftArm.body.SmoothRotate(0.0f, 20.0f); leftArm.body.SmoothRotate(0.0f, 20.0f);
} }
} }
} }
void UpdateStandingSimple() void UpdateStandingSimple()
@@ -466,20 +469,51 @@ namespace Barotrauma
{ {
movement = Vector2.Normalize(movement); movement = Vector2.Normalize(movement);
} }
}
return; private void ClimbOverObstacles()
//RefLimb.pullJoint.Enabled = true; {
//RefLimb.pullJoint.WorldAnchorB = if (collider.FarseerBody.ContactList == null || Math.Abs(movement.X) < 0.01f) return;
// RefLimb.SimPosition + movement * 0.15f;
//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<Vector2> contactPos;
ce.Contact.GetWorldManifold(out contactNormal, out contactPos);
//foreach (Limb l in Limbs) //only climb if moving towards the obstacle
//{ if (Math.Sign(contactPos[0].X - collider.SimPosition.X) == Math.Sign(movement.X) &&
// if (l == RefLimb) continue; (handle == null || contactPos[0].Y > ((Vector2)handle).Y))
// l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); {
//} handle = contactPos[0];
//new Vector2(movement.X, floorY + HeadPosition), 0.5f); }
}
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() void UpdateSwimming()
@@ -820,63 +854,7 @@ namespace Barotrauma
var head = GetLimb(LimbType.Head); var head = GetLimb(LimbType.Head);
head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos); head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos);
head.pullJoint.Enabled = true; 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) public override void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand)
{ {
if (target == null) return; if (target == null) return;
@@ -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); Vector2 rayEnd = rayStart - new Vector2(0.0f, TorsoPosition);
var lowestLimb = FindLowestLimb(); var lowestLimb = FindLowestLimb();