Controlling humanoid movement with one capsule-shaped physics body that other limbs (attempt to) follow

Broken and WIP
This commit is contained in:
Regalis
2016-10-13 23:19:48 +03:00
parent e12fe29f80
commit 62c88be214
9 changed files with 306 additions and 195 deletions
@@ -76,6 +76,10 @@
<sound file ="Content/step.ogg"/> <sound file ="Content/step.ogg"/>
</limb> </limb>
<limb id = "13" height="100" radius="15" mass = "6" type="Controller" attackpriority="2" impacttolerance="5000.0">
<sprite texture="Content/Characters/Human/[GENDER]head[HEADID].png" sourcerect="1,1,1,1" depth="0.0" origin="0.5,0.5"/>
</limb>
<!-- head to body --> <!-- head to body -->
<joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45"/> <joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45"/>
<joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/> <joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/>
@@ -154,9 +154,9 @@ namespace Barotrauma
{ {
x = 0.0f; x = 0.0f;
} }
else if (character.AnimController.LowestLimb != null && hull != null) else if (hull != null)
{ {
if (character.AnimController.LowestLimb.Position.Y < hull.Rect.Y - hull.Rect.Height + 10.0f) x = 0.0f; if (character.AnimController.GetColliderBottom().Y < hull.Rect.Y - hull.Rect.Height + 10.0f) x = 0.0f;
} }
character.AnimController.IgnorePlatforms = false; character.AnimController.IgnorePlatforms = false;
@@ -1,6 +1,7 @@
using System.Xml.Linq; using System.Xml.Linq;
using FarseerPhysics; using FarseerPhysics;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System.Collections.Generic;
namespace Barotrauma namespace Barotrauma
{ {
@@ -9,8 +10,6 @@ namespace Barotrauma
public enum Animation { None, Climbing, UsingConstruction, Struggle, CPR }; public enum Animation { None, Climbing, UsingConstruction, Struggle, CPR };
public Animation Anim; public Animation Anim;
public Direction TargetDir;
protected Character character; protected Character character;
protected float walkSpeed, swimSpeed; protected float walkSpeed, swimSpeed;
@@ -25,6 +24,8 @@ namespace Barotrauma
protected readonly Vector2 stepSize; protected readonly Vector2 stepSize;
protected readonly float legTorque; protected readonly float legTorque;
public float StunTimer public float StunTimer
{ {
get { return stunTimer; } get { return stunTimer; }
@@ -52,6 +53,8 @@ namespace Barotrauma
//impactTolerance = ToolBox.GetAttributeFloat(element, "impacttolerance", 10.0f); //impactTolerance = ToolBox.GetAttributeFloat(element, "impacttolerance", 10.0f);
legTorque = ToolBox.GetAttributeFloat(element, "legtorque", 0.0f); legTorque = ToolBox.GetAttributeFloat(element, "legtorque", 0.0f);
} }
public virtual void UpdateAnim(float deltaTime) { } public virtual void UpdateAnim(float deltaTime) { }
@@ -59,5 +62,7 @@ namespace Barotrauma
public virtual void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle) { } public virtual void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle) { }
public virtual void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand) { } public virtual void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand) { }
} }
} }
@@ -293,19 +293,21 @@ namespace Barotrauma
Structure structure = fixture.Body.UserData as Structure; Structure structure = fixture.Body.UserData as Structure;
if (stairs == null && structure != null) if (stairs == null && structure != null)
{ {
if (LowestLimb.SimPosition.Y < structure.SimPosition.Y) //TODO: fix
{ //if (LowestLimb.SimPosition.Y < structure.SimPosition.Y)
return -1; //{
} // return -1;
else //}
{ //else
stairs = structure; //{
} // stairs = structure;
//}
} }
break; break;
case Physics.CollisionPlatform: case Physics.CollisionPlatform:
Structure platform = fixture.Body.UserData as Structure; Structure platform = fixture.Body.UserData as Structure;
if (IgnorePlatforms || LowestLimb.Position.Y < platform.Rect.Y) return -1; //TODO: fix
//if (IgnorePlatforms || LowestLimb.Position.Y < platform.Rect.Y) return -1;
break; break;
case Physics.CollisionWall: case Physics.CollisionWall:
break; break;
@@ -44,10 +44,10 @@ namespace Barotrauma
{ {
get get
{ {
return Crouching ? base.TorsoAngle+0.5f : base.TorsoAngle; return Crouching ? base.TorsoAngle + 0.5f : base.TorsoAngle;
} }
} }
public HumanoidAnimController(Character character, XElement element) public HumanoidAnimController(Character character, XElement element)
: base(character, element) : base(character, element)
{ {
@@ -64,80 +64,135 @@ namespace Barotrauma
if (character.IsDead) return; if (character.IsDead) return;
if (Frozen) return; if (Frozen) return;
Vector2 colliderPos = GetLimb(LimbType.Torso).SimPosition; if (collider == null) return;
Vector2 colliderPos = GetColliderBottom();
//if (inWater) stairs = null; //if (inWater) stairs = null;
if (onFloorTimer <= 0.0f && !SimplePhysicsEnabled) //if (onFloorTimer <= 0.0f && !SimplePhysicsEnabled)
//{
// Vector2 rayStart = colliderPos; // at the bottom of the player sprite
// Vector2 rayEnd = rayStart - new Vector2(0.0f, TorsoPosition);
// if (stairs != null) rayEnd.Y -= 0.5f;
// //do a raytrace straight down from the torso to figure
// //out whether the ragdoll is standing on ground
// float closestFraction = 1;
// Structure closestStructure = null;
// GameMain.World.RayCast((fixture, point, normal, fraction) =>
// {
// switch (fixture.CollisionCategories)
// {
// case Physics.CollisionStairs:
// if (inWater && TargetMovement.Y < 0.5f) return -1;
// Structure structure = fixture.Body.UserData as Structure;
// if (stairs == null && structure != null)
// {
// if (LowestLimb.SimPosition.Y < structure.SimPosition.Y)
// {
// return -1;
// }
// else
// {
// stairs = structure;
// }
// }
// break;
// case Physics.CollisionPlatform:
// Structure platform = fixture.Body.UserData as Structure;
// if (IgnorePlatforms || LowestLimb.Position.Y < platform.Rect.Y) return -1;
// break;
// case Physics.CollisionWall:
// break;
// default:
// return -1;
// }
// onGround = true;
// if (fraction < closestFraction)
// {
// closestFraction = fraction;
// Structure structure = fixture.Body.UserData as Structure;
// if (structure != null) closestStructure = structure;
// }
// onFloorTimer = 0.05f;
// return closestFraction;
// }
// , rayStart, rayEnd);
// if (closestStructure != null && closestStructure.StairDirection != Direction.None)
// {
// stairs = closestStructure;
// }
// else
// {
// stairs = null;
// }
// if (closestFraction == 1) //raycast didn't hit anything
// {
// floorY = (currentHull == null) ? -1000.0f : ConvertUnits.ToSimUnits(currentHull.Rect.Y - currentHull.Rect.Height);
// }
// else
// {
// floorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction;
// }
//}
bool onStairs = stairs != null;
stairs = null;
var contacts = collider.body.FarseerBody.ContactList;
while (contacts != null && contacts.Contact != null)
{ {
Vector2 rayStart = colliderPos; // at the bottom of the player sprite if (contacts.Contact.Enabled && contacts.Contact.IsTouching)
Vector2 rayEnd = rayStart - new Vector2(0.0f, TorsoPosition);
if (stairs != null) rayEnd.Y -= 0.5f;
//do a raytrace straight down from the torso to figure
//out whether the ragdoll is standing on ground
float closestFraction = 1;
Structure closestStructure = null;
GameMain.World.RayCast((fixture, point, normal, fraction) =>
{ {
switch (fixture.CollisionCategories) Vector2 normal;
FarseerPhysics.Common.FixedArray2<Vector2> points;
contacts.Contact.GetWorldManifold(out normal, out points);
switch (contacts.Contact.FixtureA.CollisionCategories)
{ {
case Physics.CollisionStairs: case Physics.CollisionStairs:
if (inWater && TargetMovement.Y < 0.5f) return -1; Structure structure = contacts.Contact.FixtureA.Body.UserData as Structure;
Structure structure = fixture.Body.UserData as Structure; if (structure != null && onStairs)
if (stairs == null && structure != null)
{ {
if (LowestLimb.SimPosition.Y < structure.SimPosition.Y) stairs = structure;
{
return -1;
}
else
{
stairs = structure;
}
} }
break; break;
case Physics.CollisionPlatform:
Structure platform = fixture.Body.UserData as Structure;
if (IgnorePlatforms || LowestLimb.Position.Y < platform.Rect.Y) return -1;
break;
case Physics.CollisionWall:
break;
default:
return -1;
} }
// case Physics.CollisionPlatform:
// Structure platform = contacts.Contact.FixtureA.Body.UserData as Structure;
// if (IgnorePlatforms || colliderBottom.Y < ConvertUnits.ToSimUnits(platform.Rect.Y - 15))
// {
// contacts = contacts.Next;
// continue;
// }
// break;
// case Physics.CollisionWall:
// break;
// default:
// contacts = contacts.Next;
// continue;
//}
onGround = true;
if (fraction < closestFraction) if (points[0].Y < collider.SimPosition.Y)
{ {
closestFraction = fraction;
Structure structure = fixture.Body.UserData as Structure; floorY = Math.Max(floorY, points[0].Y);
if (structure != null) closestStructure = structure;
onGround = true;
onFloorTimer = 0.1f;
} }
onFloorTimer = 0.05f;
return closestFraction;
}
, rayStart, rayEnd);
if (closestStructure != null && closestStructure.StairDirection != Direction.None)
{
stairs = closestStructure;
}
else
{
stairs = null;
} }
if (closestFraction == 1) //raycast didn't hit anything contacts = contacts.Next;
{
floorY = (currentHull == null) ? -1000.0f : ConvertUnits.ToSimUnits(currentHull.Rect.Y - currentHull.Rect.Height);
}
else
{
floorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction;
}
}
}
//the ragdoll "stays on ground" for 50 millisecs after separation //the ragdoll "stays on ground" for 50 millisecs after separation
if (onFloorTimer <= 0.0f) if (onFloorTimer <= 0.0f)
@@ -152,7 +207,7 @@ namespace Barotrauma
{ {
onFloorTimer -= deltaTime; onFloorTimer -= deltaTime;
} }
//stun (= disable the animations) if the ragdoll receives a large enough impact //stun (= disable the animations) if the ragdoll receives a large enough impact
if (strongestImpact > 0.0f) if (strongestImpact > 0.0f)
{ {
@@ -160,9 +215,10 @@ namespace Barotrauma
} }
strongestImpact = 0.0f; strongestImpact = 0.0f;
if (stunTimer > 0) if (stunTimer > 0)
{ {
collider.Disabled = true;
stunTimer -= deltaTime; stunTimer -= deltaTime;
return; return;
} }
@@ -179,11 +235,11 @@ namespace Barotrauma
Vector2 midPos = waist.SimPosition; Vector2 midPos = waist.SimPosition;
Matrix torsoTransform = Matrix.CreateRotationZ(waist.Rotation); Matrix torsoTransform = Matrix.CreateRotationZ(waist.Rotation);
midPos += Vector2.Transform(new Vector2(-0.3f*Dir,-0.2f), torsoTransform); midPos += Vector2.Transform(new Vector2(-0.3f * Dir, -0.2f), torsoTransform);
if (rightHand.pullJoint.Enabled) midPos = (midPos + rightHand.pullJoint.WorldAnchorB) / 2.0f; if (rightHand.pullJoint.Enabled) midPos = (midPos + rightHand.pullJoint.WorldAnchorB) / 2.0f;
@@ -199,16 +255,17 @@ namespace Barotrauma
else else
{ {
if (Anim != Animation.UsingConstruction) ResetPullJoints(); if (Anim != Animation.UsingConstruction) ResetPullJoints();
} }
if (SimplePhysicsEnabled) if (SimplePhysicsEnabled)
{ {
UpdateStandingSimple(); UpdateStandingSimple();
return; return;
} }
inWater = false;
switch (Anim) switch (Anim)
{ {
@@ -224,12 +281,12 @@ namespace Barotrauma
default: default:
if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter); if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter);
//0.5 second delay for switching between swimming and walking //0.5 second delay for switching between swimming and walking
//prevents rapid switches between swimming/walking if the water level is fluctuating around the minimum swimming depth //prevents rapid switches between swimming/walking if the water level is fluctuating around the minimum swimming depth
if (inWater) if (inWater)
{ {
inWaterTimer = Math.Max(inWaterTimer+deltaTime, 0.5f); inWaterTimer = Math.Max(inWaterTimer + deltaTime, 0.5f);
if (inWaterTimer >= 1.0f) swimming = true; if (inWaterTimer >= 1.0f) swimming = true;
} }
else else
@@ -268,19 +325,19 @@ namespace Barotrauma
//if you're allergic to magic numbers, stop reading now //if you're allergic to magic numbers, stop reading now
Limb leftFoot = GetLimb(LimbType.LeftFoot); Limb leftFoot = GetLimb(LimbType.LeftFoot);
Limb rightFoot = GetLimb(LimbType.RightFoot); Limb rightFoot = GetLimb(LimbType.RightFoot);
Limb head = GetLimb(LimbType.Head); Limb head = GetLimb(LimbType.Head);
Limb torso = GetLimb(LimbType.Torso); Limb torso = GetLimb(LimbType.Torso);
Limb waist = GetLimb(LimbType.Waist); Limb waist = GetLimb(LimbType.Waist);
Limb leftHand = GetLimb(LimbType.LeftHand); Limb leftHand = GetLimb(LimbType.LeftHand);
Limb rightHand = GetLimb(LimbType.RightHand); Limb rightHand = GetLimb(LimbType.RightHand);
Limb leftLeg = GetLimb(LimbType.LeftLeg);
Limb rightLeg = GetLimb(LimbType.RightLeg);
Limb leftLeg = GetLimb(LimbType.LeftLeg);
Limb rightLeg = GetLimb(LimbType.RightLeg);
float getUpSpeed = 0.3f; float getUpSpeed = 0.3f;
float walkCycleSpeed = head.LinearVelocity.X * walkAnimSpeed; float walkCycleSpeed = head.LinearVelocity.X * walkAnimSpeed;
if (stairs != null) if (stairs != null)
@@ -297,10 +354,10 @@ namespace Barotrauma
{ {
TargetMovement /= 1.0f; TargetMovement /= 1.0f;
walkCycleSpeed *= 1.5f; walkCycleSpeed *= 1.5f;
} }
} }
Vector2 colliderPos = new Vector2(torso.SimPosition.X, floorY); Vector2 colliderPos = GetColliderBottom();
if (Math.Abs(TargetMovement.X) > 1.0f) if (Math.Abs(TargetMovement.X) > 1.0f)
{ {
@@ -313,24 +370,24 @@ namespace Barotrauma
float slowdownFactor = (float)limbsInWater / (float)Limbs.Count(); float slowdownFactor = (float)limbsInWater / (float)Limbs.Count();
float maxSpeed = Math.Max(TargetMovement.Length() - slowdownFactor, 1.0f); float maxSpeed = Math.Max(TargetMovement.Length() - slowdownFactor, 1.0f);
// if (character.SelectedCharacter!=null) maxSpeed = Math.Min(maxSpeed, 1.0f); // if (character.SelectedCharacter!=null) maxSpeed = Math.Min(maxSpeed, 1.0f);
TargetMovement = Vector2.Normalize(TargetMovement) * maxSpeed; TargetMovement = Vector2.Normalize(TargetMovement) * maxSpeed;
} }
float walkPosX = (float)Math.Cos(walkPos); float walkPosX = (float)Math.Cos(walkPos);
float walkPosY = (float)Math.Sin(walkPos); float walkPosY = (float)Math.Sin(walkPos);
float runningModifier = (float)Math.Max(Math.Min(Math.Abs(TargetMovement.X),3.0f) / 1.5f, 1.0); float runningModifier = (float)Math.Max(Math.Min(Math.Abs(TargetMovement.X), 3.0f) / 1.5f, 1.0);
Vector2 stepSize = new Vector2( Vector2 stepSize = new Vector2(
this.stepSize.X * walkPosX * runningModifier, this.stepSize.X * walkPosX * runningModifier,
this.stepSize.Y * walkPosY * runningModifier * runningModifier); this.stepSize.Y * walkPosY * runningModifier * runningModifier);
if (Crouching) stepSize *= 0.5f; if (Crouching) stepSize *= 0.5f;
float footMid = waist.SimPosition.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f; float footMid = colliderPos.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f;
movement = MathUtils.SmoothStep(movement, TargetMovement*walkSpeed, movementLerp); movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp);
movement.Y = 0.0f; movement.Y = 0.0f;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
@@ -355,9 +412,9 @@ namespace Barotrauma
} }
} }
if (LowestLimb == null) return; //if (LowestLimb == null) return;
if (!onGround || (LowestLimb.SimPosition.Y - floorY > 0.5f && stairs == null)) return; if (onGround) collider.body.LinearVelocity = new Vector2(movement.X * 1.5f, collider.LinearVelocity.Y);
//float? ceilingY = null; //float? ceilingY = null;
//if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null) //if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null)
@@ -366,7 +423,7 @@ namespace Barotrauma
// if (ceilingY - floorY < HeadPosition) Crouching = true; // if (ceilingY - floorY < HeadPosition) Crouching = true;
//} //}
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;
@@ -375,8 +432,6 @@ namespace Barotrauma
if (stairs != null) if (stairs != null)
{ {
if (LowestLimb.SimPosition.Y < stairs.SimPosition.Y) IgnorePlatforms = true;
torso.pullJoint.WorldAnchorB = new Vector2( torso.pullJoint.WorldAnchorB = new Vector2(
MathHelper.SmoothStep(torso.SimPosition.X, footMid + movement.X * 0.35f, getUpSpeed * 0.8f), MathHelper.SmoothStep(torso.SimPosition.X, footMid + movement.X * 0.35f, getUpSpeed * 0.8f),
MathHelper.SmoothStep(torso.SimPosition.Y, colliderPos.Y + TorsoPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f)); MathHelper.SmoothStep(torso.SimPosition.Y, colliderPos.Y + TorsoPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f));
@@ -390,17 +445,31 @@ namespace Barotrauma
} }
else else
{ {
if (!onGround) movement = Vector2.Zero;
torso.pullJoint.WorldAnchorB = torso.pullJoint.WorldAnchorB =
MathUtils.SmoothStep(torso.SimPosition, MathUtils.SmoothStep(torso.SimPosition,
new Vector2(footMid + movement.X * 0.3f, colliderPos.Y + TorsoPosition), getUpSpeed); new Vector2(footMid + movement.X * 0.3f, colliderPos.Y + TorsoPosition), getUpSpeed);
head.pullJoint.WorldAnchorB = head.pullJoint.WorldAnchorB =
MathUtils.SmoothStep(head.SimPosition, MathUtils.SmoothStep(head.SimPosition,
new Vector2(footMid + movement.X * (Crouching && Math.Sign(movement.X)==Math.Sign(Dir) ? 1.0f : 0.3f), colliderPos.Y + HeadPosition), getUpSpeed*1.2f); new Vector2(footMid + movement.X * (Crouching && Math.Sign(movement.X) == Math.Sign(Dir) ? 1.0f : 0.3f), colliderPos.Y + HeadPosition), getUpSpeed * 1.2f);
waist.pullJoint.WorldAnchorB = waist.SimPosition + movement * 0.1f; waist.pullJoint.WorldAnchorB = waist.SimPosition + movement * 0.1f;
} }
if (!onGround)
{
Vector2 move = torso.pullJoint.WorldAnchorB - torso.SimPosition;
foreach (Limb limb in Limbs)
{
if (limb == collider) continue;
MoveLimb(limb, limb.SimPosition+move, 15.0f, true);
}
return;
}
//moving horizontally //moving horizontally
if (TargetMovement.X != 0.0f) if (TargetMovement.X != 0.0f)
@@ -462,7 +531,7 @@ namespace Barotrauma
HandIK(rightHand, torso.SimPosition + posAddition + HandIK(rightHand, torso.SimPosition + posAddition +
new Vector2( new Vector2(
-handPos.X, -handPos.X,
(Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY), 0.7f*runningModifier); (Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY), 0.7f * runningModifier);
} }
if (!leftHand.Disabled) if (!leftHand.Disabled)
@@ -507,7 +576,7 @@ namespace Barotrauma
var leftArm = GetLimb(LimbType.LeftArm); var leftArm = GetLimb(LimbType.LeftArm);
leftArm.body.SmoothRotate(0.0f, 20.0f); leftArm.body.SmoothRotate(0.0f, 20.0f);
} }
} }
} }
@@ -521,17 +590,18 @@ namespace Barotrauma
movement = Vector2.Normalize(movement); movement = Vector2.Normalize(movement);
} }
RefLimb.pullJoint.Enabled = true; return;
RefLimb.pullJoint.WorldAnchorB = //RefLimb.pullJoint.Enabled = true;
RefLimb.SimPosition + movement * 0.15f; //RefLimb.pullJoint.WorldAnchorB =
// RefLimb.SimPosition + movement * 0.15f;
RefLimb.body.SmoothRotate(0.0f); //RefLimb.body.SmoothRotate(0.0f);
foreach (Limb l in Limbs) //foreach (Limb l in Limbs)
{ //{
if (l == RefLimb) continue; // if (l == RefLimb) continue;
l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); // l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation);
} //}
//new Vector2(movement.X, floorY + HeadPosition), 0.5f); //new Vector2(movement.X, floorY + HeadPosition), 0.5f);
} }
@@ -596,7 +666,7 @@ namespace Barotrauma
if (TargetMovement == Vector2.Zero) return; if (TargetMovement == Vector2.Zero) return;
movement = MathUtils.SmoothStep(movement, TargetMovement*swimSpeed, 0.3f); movement = MathUtils.SmoothStep(movement, TargetMovement * swimSpeed, 0.3f);
//dont try to move upwards if head is already out of water //dont try to move upwards if head is already out of water
if (surfaceLimiter > 1.0f && TargetMovement.Y > 0.0f) if (surfaceLimiter > 1.0f && TargetMovement.Y > 0.0f)
@@ -747,7 +817,7 @@ namespace Barotrauma
float stepHeight = ConvertUnits.ToSimUnits(30.0f); float stepHeight = ConvertUnits.ToSimUnits(30.0f);
if (currentHull==null && character.SelectedConstruction.Submarine!=null) if (currentHull == null && character.SelectedConstruction.Submarine != null)
{ {
ladderSimPos += character.SelectedConstruction.Submarine.SimPosition; ladderSimPos += character.SelectedConstruction.Submarine.SimPosition;
} }
@@ -759,7 +829,7 @@ namespace Barotrauma
MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, head.SimPosition.Y + 0.05f), 10.5f); MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, head.SimPosition.Y + 0.05f), 10.5f);
MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, torso.SimPosition.Y), 10.5f); MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, torso.SimPosition.Y), 10.5f);
MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, waist.SimPosition.Y), 10.5f); MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, waist.SimPosition.Y), 10.5f);
Vector2 handPos = new Vector2( Vector2 handPos = new Vector2(
ladderSimPos.X, ladderSimPos.X,
@@ -807,12 +877,12 @@ namespace Barotrauma
float movementFactor = (handPos.Y / stepHeight) * (float)Math.PI; float movementFactor = (handPos.Y / stepHeight) * (float)Math.PI;
movementFactor = 0.8f + (float)Math.Abs(Math.Sin(movementFactor)); movementFactor = 0.8f + (float)Math.Abs(Math.Sin(movementFactor));
Vector2 subSpeed = currentHull != null || character.SelectedConstruction.Submarine == null Vector2 subSpeed = currentHull != null || character.SelectedConstruction.Submarine == null
? Vector2.Zero : character.SelectedConstruction.Submarine.Velocity; ? Vector2.Zero : character.SelectedConstruction.Submarine.Velocity;
Vector2 climbForce = new Vector2(0.0f, movement.Y + (inWater ? -0.05f : 0.6f)) * movementFactor; Vector2 climbForce = new Vector2(0.0f, movement.Y + (inWater ? -0.05f : 0.6f)) * movementFactor;
if (climbForce.Y > 0.5f) climbForce.Y = Math.Max(climbForce.Y, 1.3f); if (climbForce.Y > 0.5f) climbForce.Y = Math.Max(climbForce.Y, 1.3f);
torso.body.ApplyForce((climbForce * 40.0f + subSpeed*50.0f) * torso.Mass); torso.body.ApplyForce((climbForce * 40.0f + subSpeed * 50.0f) * torso.Mass);
head.body.SmoothRotate(0.0f); head.body.SmoothRotate(0.0f);
if (!character.SelectedConstruction.Prefab.Triggers.Any()) if (!character.SelectedConstruction.Prefab.Triggers.Any())
@@ -862,15 +932,15 @@ namespace Barotrauma
targetMovement = new Vector2(diff.X, 0.0f); targetMovement = new Vector2(diff.X, 0.0f);
TargetDir = headDiff.X > 0.0f ? Direction.Right : Direction.Left; TargetDir = headDiff.X > 0.0f ? Direction.Right : Direction.Left;
UpdateStanding(); UpdateStanding();
Vector2 handPos = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso).SimPosition + Vector2.UnitY*0.2f; Vector2 handPos = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso).SimPosition + Vector2.UnitY * 0.2f;
Grab(handPos, handPos); Grab(handPos, handPos);
float yPos = (float)Math.Sin(cprAnimState) * 0.1f; float yPos = (float)Math.Sin(cprAnimState) * 0.1f;
cprAnimState += deltaTime*8.0f; cprAnimState += deltaTime * 8.0f;
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);
@@ -880,7 +950,7 @@ namespace Barotrauma
//RefLimb.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X - Math.Sign(headDiff.X) * 0.5f, targetHead.SimPosition.Y + 0.4f + yPos); //RefLimb.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X - Math.Sign(headDiff.X) * 0.5f, targetHead.SimPosition.Y + 0.4f + yPos);
//head.pullJoint.Enabled = true; //head.pullJoint.Enabled = true;
//DragCharacter(character.SelectedCharacter, LimbType.Torso, LimbType.Head); //DragCharacter(character.SelectedCharacter, LimbType.Torso, LimbType.Head);
} }
@@ -942,15 +1012,15 @@ namespace Barotrauma
//only grab with one hand when swimming //only grab with one hand when swimming
leftHand.Disabled = true; leftHand.Disabled = true;
if (!inWater) rightHand.Disabled = true; if (!inWater) rightHand.Disabled = true;
for (int i = 0; i < 2; i++ )
{
LimbType type = i == 0 ? leftHandTarget: rightHandTarget;
Limb targetLimb = target.AnimController.GetLimb(type);
Limb pullLimb = GetLimb(i == 0 ? LimbType.LeftHand: LimbType.RightHand);
if (i==1 && inWater) for (int i = 0; i < 2; i++)
{
LimbType type = i == 0 ? leftHandTarget : rightHandTarget;
Limb targetLimb = target.AnimController.GetLimb(type);
Limb pullLimb = GetLimb(i == 0 ? LimbType.LeftHand : LimbType.RightHand);
if (i == 1 && inWater)
{ {
targetLimb.pullJoint.Enabled = false; targetLimb.pullJoint.Enabled = false;
} }
@@ -977,7 +1047,7 @@ namespace Barotrauma
} }
else if (target is AICharacter) else if (target is AICharacter)
{ {
target.AnimController.TargetMovement = Vector2.Lerp(target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX*Dir) - target.SimPosition, 0.5f); target.AnimController.TargetMovement = Vector2.Lerp(target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition, 0.5f);
} }
} }
@@ -990,7 +1060,7 @@ namespace Barotrauma
pullLimb.Disabled = true; pullLimb.Disabled = true;
pullLimb.pullJoint.Enabled = true; pullLimb.pullJoint.Enabled = true;
pullLimb.pullJoint.WorldAnchorB = (i==0) ? rightHandPos : leftHandPos; pullLimb.pullJoint.WorldAnchorB = (i == 0) ? rightHandPos : leftHandPos;
pullLimb.pullJoint.MaxForce = 500.0f; pullLimb.pullJoint.MaxForce = 500.0f;
} }
@@ -1085,7 +1155,7 @@ namespace Barotrauma
item.body.ResetDynamics(); item.body.ResetDynamics();
Vector2 currItemPos = (character.SelectedItems[0]==item) ? Vector2 currItemPos = (character.SelectedItems[0] == item) ?
rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] : rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] :
leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1]; leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
item.SetTransform(currItemPos, itemAngle); item.SetTransform(currItemPos, itemAngle);
@@ -1136,7 +1206,7 @@ namespace Barotrauma
Vector2 targetMovement = character.GetTargetMovement(); Vector2 targetMovement = character.GetTargetMovement();
Vector2 currPosition = prevPosition + targetMovement * timePassed/500.0f; Vector2 currPosition = prevPosition + targetMovement * timePassed / 500.0f;
return currPosition; return currPosition;
} }
@@ -1200,7 +1270,7 @@ namespace Barotrauma
Vector2 position = limb.SimPosition; Vector2 position = limb.SimPosition;
if ((limb.pullJoint==null || !limb.pullJoint.Enabled) && mirror) if ((limb.pullJoint == null || !limb.pullJoint.Enabled) && mirror)
{ {
difference = limb.body.SimPosition - torso.SimPosition; difference = limb.body.SimPosition - torso.SimPosition;
difference = Vector2.Transform(difference, torsoTransform); difference = Vector2.Transform(difference, torsoTransform);
@@ -1219,6 +1289,6 @@ namespace Barotrauma
limb.body.SetTransform(limb.body.SimPosition, angle); limb.body.SetTransform(limb.body.SimPosition, angle);
} }
} }
} }
} }
@@ -57,18 +57,15 @@ namespace Barotrauma
public bool onGround; public bool onGround;
private bool ignorePlatforms; private bool ignorePlatforms;
private Limb refLimb; protected Limb refLimb;
protected Structure stairs; protected Structure stairs;
protected Direction dir; protected Direction dir;
//private byte ID; public Direction TargetDir;
public Limb LowestLimb protected Limb collider;
{
get { return lowestLimb; }
}
public Limb RefLimb public Limb RefLimb
{ {
@@ -278,7 +275,13 @@ namespace Barotrauma
limb.sprite.Depth = startDepth + limb.sprite.Depth * 0.0001f; limb.sprite.Depth = startDepth + limb.sprite.Depth * 0.0001f;
} }
FindLowestLimb();
collider = GetLimb(LimbType.Controller);
if (collider == null) return;
collider.body.FarseerBody.FixedRotation = true;
collider.pullJoint = null;
refLimb = collider;
} }
public void AddJoint(XElement subElement, float scale = 1.0f) public void AddJoint(XElement subElement, float scale = 1.0f)
@@ -345,57 +348,72 @@ namespace Barotrauma
CalculateImpact(f1, f2, contact); CalculateImpact(f1, f2, contact);
return true; return true;
} }
Vector2 colliderBottom = GetColliderBottom();
if (structure.IsPlatform) if (structure.IsPlatform)
{ {
if (ignorePlatforms) return false; if (ignorePlatforms) return false;
//the collision is ignored if the lowest limb is under the platform //the collision is ignored if the lowest limb is under the platform
if (lowestLimb==null || lowestLimb.Position.Y < structure.Rect.Y) return false; //if (lowestLimb==null || lowestLimb.Position.Y < structure.Rect.Y) return false;
if (colliderBottom.Y < ConvertUnits.ToSimUnits(structure.Rect.Y - 5)) return false;
} }
else if (structure.StairDirection != Direction.None && lowestLimb != null) else if (structure.StairDirection != Direction.None)
{ {
float stairPosY = structure.StairDirection == Direction.Right ?
lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X);
if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false; float stairBottomPos = ConvertUnits.ToSimUnits(structure.Rect.Y - structure.Rect.Height + 10);
if (colliderBottom.Y < stairBottomPos && targetMovement.Y < 0.5f)
if (targetMovement.Y < 0.5f)
{ {
if (inWater || lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + 50.0f) stairs = null;
{ return false;
stairs = null;
return false;
}
} }
if (targetMovement.Y >= 0.0f && colliderBottom.Y > ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 8.0f))
{
stairs = null;
return false;
}
stairs = structure;
//float stairPosY = structure.StairDirection == Direction.Right ?
// lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X);
//if (targetMovement.Y >= 0.0f && lowestLimb.SimPosition.Y > ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 8.0f)) //if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false;
//if (targetMovement.Y < 0.5f)
//{ //{
// //stairs = null; // if (inWater || lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + 50.0f)
// //return false; // {
// stairs = null;
// return false;
// }
//} //}
Limb limb = f1.Body.UserData as Limb;
if (limb != null)// && (limb.type == LimbType.LeftFoot || limb.type == LimbType.RightFoot))
{
if (contact.Manifold.LocalNormal.Y >= 0.0f)
{
if (limb.SimPosition.Y < lowestLimb.SimPosition.Y+0.2f)
{
stairs = structure;
return true;
}
}
else //Limb limb = f1.Body.UserData as Limb;
{ //if (limb != null)// && (limb.type == LimbType.LeftFoot || limb.type == LimbType.RightFoot))
stairs = null; //{
return false; // if (contact.Manifold.LocalNormal.Y >= 0.0f)
} // {
} // if (limb.SimPosition.Y < lowestLimb.SimPosition.Y+0.2f)
// {
// stairs = structure;
// return true;
// }
// }
// else
// {
// stairs = null;
// return false;
// }
//}
} }
@@ -717,7 +735,7 @@ namespace Barotrauma
Vector2 flowForce = Vector2.Zero; Vector2 flowForce = Vector2.Zero;
FindLowestLimb(); //FindLowestLimb();
FindHull(); FindHull();
@@ -1010,19 +1028,24 @@ namespace Barotrauma
limbDictionary.TryGetValue(limbType, out limb); limbDictionary.TryGetValue(limbType, out limb);
return limb; return limb;
} }
public void FindLowestLimb()
public Vector2 GetColliderBottom()
{ {
//find the lowest limb return collider == null ? Vector2.Zero : collider.SimPosition - Vector2.UnitY * (collider.body.height / 2 + collider.body.radius);
lowestLimb = null;
foreach (Limb limb in Limbs)
{
if (lowestLimb == null)
lowestLimb = limb;
else if (limb.SimPosition.Y < lowestLimb.SimPosition.Y)
lowestLimb = limb;
}
} }
//public void FindLowestLimb()
//{ //find the lowest limb
// lowestLimb = null;
// foreach (Limb limb in Limbs)
// {
// if (lowestLimb == null)
// lowestLimb = limb;
// else if (limb.SimPosition.Y < lowestLimb.SimPosition.Y)
// lowestLimb = limb;
// }
//}
public void Remove() public void Remove()
{ {
+2 -1
View File
@@ -16,7 +16,8 @@ namespace Barotrauma
public enum LimbType public enum LimbType
{ {
None, LeftHand, RightHand, LeftArm, RightArm, None, LeftHand, RightHand, LeftArm, RightArm,
LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist,
Controller
}; };
class Limb class Limb
-1
View File
@@ -556,7 +556,6 @@ namespace Barotrauma
foreach (Limb limb in c.AnimController.Limbs) foreach (Limb limb in c.AnimController.Limbs)
{ {
if (c.AnimController.LowestLimb == limb) continue;
limb.body.ApplyLinearImpulse(limb.Mass * impulse); limb.body.ApplyLinearImpulse(limb.Mass * impulse);
} }
} }
+9 -2
View File
@@ -383,9 +383,16 @@ namespace Barotrauma
float angle = MathUtils.GetShortestAngle(nextAngle, targetRotation); float angle = MathUtils.GetShortestAngle(nextAngle, targetRotation);
float torque = body.Mass * angle * 60.0f * (force/100.0f); float torque = angle * 60.0f * (force/100.0f);
body.ApplyTorque(torque); if (body.IsKinematic)
{
body.AngularVelocity = torque;
}
else
{
body.ApplyTorque(body.Mass * torque);
}
} }
public void Remove() public void Remove()