From 704c7c7561e4a90cf75cf78e1fac991c34e437af Mon Sep 17 00:00:00 2001 From: Regalis Date: Sun, 16 Oct 2016 22:23:32 +0300 Subject: [PATCH] Collider-controlled monster movement --- .../Factories/BodyFactory.cs | 23 ++ .../Content/Characters/Crawler/crawler.xml | 24 +- .../Content/Characters/Mantis/mantis.xml | 2 + .../Animation/FishAnimController.cs | 231 ++++-------------- .../Animation/HumanoidAnimController.cs | 163 +----------- .../Source/Characters/Animation/Ragdoll.cs | 109 +++++++-- Subsurface/Source/Physics/PhysicsBody.cs | 16 +- 7 files changed, 205 insertions(+), 363 deletions(-) diff --git a/Farseer Physics Engine 3.5/Factories/BodyFactory.cs b/Farseer Physics Engine 3.5/Factories/BodyFactory.cs index 8ef734a6f..2bc288197 100644 --- a/Farseer Physics Engine 3.5/Factories/BodyFactory.cs +++ b/Farseer Physics Engine 3.5/Factories/BodyFactory.cs @@ -192,6 +192,29 @@ namespace FarseerPhysics.Factories return body; } + public static Body CreateCapsuleHorizontal(World world, float width, float endRadius, float density, + object userData = null) + { + //Create the middle rectangle + Vertices rectangle = PolygonTools.CreateRectangle(width / 2, endRadius); + + List list = new List(); + list.Add(rectangle); + + Body body = CreateCompoundPolygon(world, list, density, userData); + body.UserData = userData; + + //Create the two circles + CircleShape topCircle = new CircleShape(endRadius, density); + topCircle.Position = new Vector2(width / 2, 0); + body.CreateFixture(topCircle); + + CircleShape bottomCircle = new CircleShape(endRadius, density); + bottomCircle.Position = new Vector2(-(width / 2), 0); + body.CreateFixture(bottomCircle); + return body; + } + /// /// Creates a rounded rectangle. /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices) diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index ca7e38e98..313a7867d 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -7,52 +7,54 @@ + + - + - + 0 - + - + - + - + - + - + - + - + diff --git a/Subsurface/Content/Characters/Mantis/mantis.xml b/Subsurface/Content/Characters/Mantis/mantis.xml index c5c53f194..0ab4a4544 100644 --- a/Subsurface/Content/Characters/Mantis/mantis.xml +++ b/Subsurface/Content/Characters/Mantis/mantis.xml @@ -15,6 +15,8 @@ footrotation ="180.0" flip="true"> + + diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index 812fd6e9c..f218ffb17 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -63,14 +63,9 @@ namespace Barotrauma if (stunTimer>0.0f) { - //UpdateStruggling(deltaTime); stunTimer -= deltaTime; return; } - else if (SimplePhysicsEnabled) - { - UpdateSimpleAnim(); - } else { if (inWater)// || RefLimb.inWater) @@ -128,7 +123,7 @@ namespace Barotrauma if (flipTimer>1.0f || character.IsNetworkPlayer) { Flip(); - if (mirror) Mirror(); + if (mirror || !inWater) Mirror(); flipTimer = 0.0f; } } @@ -137,12 +132,26 @@ namespace Barotrauma void UpdateSineAnim(float deltaTime) { movement = TargetMovement*swimSpeed; + + Limb torso = GetLimb(LimbType.Torso); + Limb head = GetLimb(LimbType.Head); + + Limb mainLimb = torso == null ? head : torso; + + mainLimb.pullJoint.Enabled = true; + mainLimb.pullJoint.WorldAnchorB = collider.SimPosition; + if (movement.LengthSquared() < 0.00001f) return; - if (!inWater) movement.Y = Math.Min(0.0f, movement.Y); - float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2; + float angle = (rotateTowardsMovement) ? + mainLimb.body.Rotation + MathUtils.GetShortestAngle(mainLimb.body.Rotation, movementAngle) : + HeadAngle * Dir; + + collider.SmoothRotate(angle, 25.0f); + mainLimb.body.SmoothRotate(angle, 25.0f); + Limb tail = GetLimb(LimbType.Tail); if (tail != null && waveAmplitude > 0.0f) { @@ -151,102 +160,30 @@ namespace Barotrauma float waveRotation = (float)Math.Sin(walkPos / waveLength); tail.body.ApplyTorque(waveRotation * tail.Mass * 100.0f * waveAmplitude); - - //limbs[tailIndex].body.ApplyTorque((Math.Sign(angle) + Math.Max(Math.Min(angle * 10.0f, 10.0f), -10.0f)) * limbs[tailIndex].body.Mass); - //limbs[tailIndex].body.ApplyTorque(-limbs[tailIndex].body.AngularVelocity * 0.5f * limbs[tailIndex].body.Mass); } - Vector2 steerForce = Vector2.Zero; - - Limb head = GetLimb(LimbType.Head); - if (head == null) head = GetLimb(LimbType.Torso); - - if (head != null) - { - float angle = (rotateTowardsMovement) ? - head.body.Rotation+ MathUtils.GetShortestAngle(head.body.Rotation, movementAngle) : - HeadAngle*Dir; - - - head.body.SmoothRotate(angle, 25.0f); - //rotate head towards the angle of movement - //float torque = (Math.Sign(angle)*10.0f + MathHelper.Clamp(angle * 10.0f, -10.0f, 10.0f)); - //angular drag - //torque -= head.body.AngularVelocity * 0.5f; - //head.body.ApplyTorque(torque * head.body.Mass); - - - //the movement vector if going to the direction of the head - //Vector2 headMovement = new Vector2( - // (float)Math.Cos(head.body.Rotation - MathHelper.PiOver2), - // (float)Math.Sin(head.body.Rotation - MathHelper.PiOver2)); - //headMovement *= movement.Length(); - - //the movement angle is between direction of the head and the direction - //where the Character is actually trying to go - - //current * (float)alpha + previous * (1.0f - (float)alpha); - - - steerForce = (movement+correctionMovement) * 50.0f - head.LinearVelocity * 30.0f; - // force += (headMovement - movement) * Math.Min(head.LinearVelocity.Length()/movement.Length(), 1.0f); - - if (!inWater) steerForce.Y = 0.0f; - } for (int i = 0; i < Limbs.Count(); i++) { - if (steerForce != Vector2.Zero) - { - Vector2 pullPos = Limbs[i].pullJoint == null ? Limbs[i].SimPosition : Limbs[i].pullJoint.WorldAnchorA; - Limbs[i].body.ApplyForce(steerForce * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); + Vector2 pullPos = Limbs[i].pullJoint == null ? Limbs[i].SimPosition : Limbs[i].pullJoint.WorldAnchorA; + Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); - } - - if (Limbs[i].type != LimbType.Torso) continue; + - float dist = (Limbs[0].SimPosition - Limbs[i].SimPosition).Length(); + if (Limbs[i] == mainLimb) continue; - Vector2 limbPos = Limbs[0].SimPosition - Vector2.Normalize(movement) * dist; + float dist = (mainLimb.SimPosition - Limbs[i].SimPosition).Length(); + + Vector2 limbPos = mainLimb.SimPosition - Vector2.Normalize(movement) * dist; Limbs[i].body.ApplyForce(((limbPos - Limbs[i].SimPosition) * 3.0f - Limbs[i].LinearVelocity * 3.0f) * Limbs[i].Mass); } - - if (!inWater) - { - UpdateWalkAnim(deltaTime); - } - else - { - floorY = Limbs[0].SimPosition.Y; - } - } - - void UpdateSimpleAnim() - { - //todo: reimplement - - //movement = MathUtils.SmoothStep(movement, TargetMovement*swimSpeed, 1.0f); - //if (movement == Vector2.Zero) return; - - //float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2; - //RefLimb.body.SmoothRotate( - // (rotateTowardsMovement) ? - // RefLimb.body.Rotation + MathUtils.GetShortestAngle(RefLimb.body.Rotation, movementAngle) : - // HeadAngle*Dir); - - //collider.LinearVelocity = movement; - - ////RefLimb.body.SmoothRotate(0.0f); - - //foreach (Limb l in Limbs) - //{ - // if (l == RefLimb) continue; - // l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); - //} + collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement, 0.5f); + + floorY = Limbs[0].SimPosition.Y; } - + void UpdateWalkAnim(float deltaTime) { movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, 0.2f); @@ -254,104 +191,38 @@ namespace Barotrauma IgnorePlatforms = (TargetMovement.Y < -Math.Abs(TargetMovement.X)); - Limb colliderLimb; - float colliderHeight; + Limb mainLimb; + float mainLimbHeight, mainLimbAngle; Limb torso = GetLimb(LimbType.Torso); Limb head = GetLimb(LimbType.Head); if (torso != null) { - colliderLimb = torso; - colliderHeight = TorsoPosition; - - colliderLimb.body.SmoothRotate(TorsoAngle * Dir, 10.0f); + mainLimb = torso; + mainLimbHeight = TorsoPosition; + mainLimbAngle = torsoAngle; } else { - colliderLimb = head; - colliderHeight = HeadPosition; - - if (onGround) colliderLimb.body.SmoothRotate(HeadAngle * Dir, 100.0f); + mainLimb = head; + mainLimbHeight = HeadPosition; + mainLimbAngle = headAngle; } + + //collider.SmoothRotate(TorsoAngle * Dir, 10.0f); + mainLimb.body.SmoothRotate(mainLimbAngle * Dir, 50.0f); - Vector2 colliderPos = colliderLimb.SimPosition; + collider.LinearVelocity = new Vector2( + movement.X, + collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); - Vector2 rayStart = colliderPos; - Vector2 rayEnd = rayStart - new Vector2(0.0f, colliderHeight); - if (stairs != null) rayEnd.Y -= 0.5f; + mainLimb.MoveToPos(GetColliderBottom() + Vector2.UnitY * mainLimbHeight, 10.0f); + + mainLimb.pullJoint.Enabled = true; + mainLimb.pullJoint.WorldAnchorB = GetColliderBottom() + Vector2.UnitY * mainLimbHeight; - //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) - { - //TODO: fix - //if (LowestLimb.SimPosition.Y < structure.SimPosition.Y) - //{ - // return -1; - //} - //else - //{ - // stairs = structure; - //} - } - break; - case Physics.CollisionPlatform: - Structure platform = fixture.Body.UserData as Structure; - //TODO: fix - //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; - } - onFloorTimer = 0.05f; - return closestFraction; - } , rayStart, rayEnd); - - //the ragdoll "stays on ground" for 50 millisecs after separation - if (onFloorTimer <= 0.0f) - { - onGround = false; - } - else - { - onFloorTimer -= deltaTime; - } - - if (!onGround) return; - - 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; - - - if (Math.Abs(colliderPos.Y - floorY) < colliderHeight * 1.2f) - { - colliderLimb.MoveToPos(new Vector2(colliderPos.X + movement.X * 0.2f, floorY + colliderHeight), 5.0f); - } - - float walkCycleSpeed = head.LinearVelocity.X * 0.05f; - - walkPos -= walkCycleSpeed; + walkPos -= mainLimb.LinearVelocity.X * 0.05f; Vector2 transformedStepSize = new Vector2( (float)Math.Cos(walkPos) * stepSize.X * 3.0f, @@ -363,7 +234,7 @@ namespace Barotrauma { case LimbType.LeftFoot: case LimbType.RightFoot: - Vector2 footPos = new Vector2(limb.SimPosition.X, colliderPos.Y - colliderHeight); + Vector2 footPos = new Vector2(limb.SimPosition.X, mainLimb.SimPosition.Y - mainLimbHeight); if (limb.RefJointIndex>-1) { @@ -382,18 +253,18 @@ namespace Barotrauma } else if (limb.type == LimbType.RightFoot) { - limb.MoveToPos(footPos +new Vector2( + 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); + 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); + if (legTorque != 0.0f) limb.body.ApplyTorque(limb.Mass * legTorque * Dir); break; } } diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 37f3afef9..39267fc32 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -76,6 +76,18 @@ namespace Barotrauma return; } + //re-enable collider + if (!collider.FarseerBody.Enabled) + { + var lowestLimb = FindLowestLimb(); + + collider.SetTransform(new Vector2( + collider.SimPosition.X, + Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)), + 0.0f); + + collider.FarseerBody.Enabled = true; + } //stun (= disable the animations) if the ragdoll receives a large enough impact if (strongestImpact > 0.0f) @@ -85,157 +97,6 @@ namespace Barotrauma return; } - //if (inWater) stairs = null; - - //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.FarseerBody.ContactList; - while (collider.FarseerBody.Enabled && contacts != null && contacts.Contact != null) - { - if (contacts.Contact.Enabled && contacts.Contact.IsTouching) - { - Vector2 normal; - FarseerPhysics.Common.FixedArray2 points; - - contacts.Contact.GetWorldManifold(out normal, out points); - - switch (contacts.Contact.FixtureA.CollisionCategories) - { - case Physics.CollisionStairs: - Structure structure = contacts.Contact.FixtureA.Body.UserData as Structure; - if (structure != null && onStairs) - { - stairs = structure; - } - break; - } - // 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; - //} - - - if (points[0].Y < collider.SimPosition.Y) - { - - floorY = Math.Max(floorY, points[0].Y); - - onGround = true; - onFloorTimer = 0.1f; - } - - - } - - contacts = contacts.Next; - - } - - //the ragdoll "stays on ground" for 50 millisecs after separation - if (onFloorTimer <= 0.0f) - { - onGround = false; - //if (GetLimb(LimbType.Torso).inWater) inWater = true; - //TODO: joku järkevämpi systeemi - //if (!inWater && lastTimeOnFloor + 200 < gameTime.TotalGameTime.Milliseconds) - // stunTimer = Math.Max(stunTimer, (float)gameTime.TotalGameTime.TotalMilliseconds + 100.0f); - } - else - { - onFloorTimer -= deltaTime; - } - - - //re-enable collider (unless swimming) - if (!collider.FarseerBody.Enabled) - { - var lowestLimb = FindLowestLimb(); - collider.SetTransform(new Vector2( - collider.SimPosition.X, - Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)), - 0.0f); - collider.FarseerBody.Enabled = true; - } if (swimming) { diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index d60c9640f..00d761ccd 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -112,24 +112,27 @@ namespace Barotrauma get { return simplePhysicsEnabled; } set { - //TODO: reimplement - - return; - //if (value == simplePhysicsEnabled) return; + if (value == simplePhysicsEnabled) return; - //simplePhysicsEnabled = value; + simplePhysicsEnabled = value; - //foreach (Limb limb in Limbs) - //{ - // limb.body.Enabled = !simplePhysicsEnabled; - //} + foreach (Limb limb in Limbs) + { + limb.body.Enabled = !simplePhysicsEnabled; + } - //foreach (RevoluteJoint joint in limbJoints) - //{ - // joint.Enabled = !simplePhysicsEnabled; - //} + foreach (RevoluteJoint joint in limbJoints) + { + joint.Enabled = !simplePhysicsEnabled; + } - //refLimb.body.Enabled = true; + if (!simplePhysicsEnabled) + { + foreach (Limb limb in Limbs) + { + limb.body.SetTransform(collider.SimPosition, collider.Rotation); + } + } } } @@ -279,7 +282,8 @@ namespace Barotrauma if (collider == null) { DebugConsole.ThrowError("No collider configured for ''"+character.Name+"''!"); - collider = new PhysicsBody(0.0f, 0.0f, 0.1f, 5.0f); + collider = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f); + collider.BodyType = BodyType.Dynamic; } collider.CollisionCategories = Physics.CollisionCharacter; @@ -384,7 +388,10 @@ namespace Barotrauma //the collision is ignored if the lowest limb is under the platform //if (lowestLimb==null || lowestLimb.Position.Y < structure.Rect.Y) return false; + if (colliderBottom.Y < ConvertUnits.ToSimUnits(structure.Rect.Y - 5)) return false; + if (f1.Body.Position.Y < ConvertUnits.ToSimUnits(structure.Rect.Y - 5)) return false; + } else if (structure.StairDirection != Direction.None) { @@ -397,8 +404,8 @@ namespace Barotrauma if (colliderBottom.Y < stairBottomPos && targetMovement.Y < 0.5f) return false; //2. bottom of the collider is at the top of the stairs and the character isn't trying to move downwards - if (targetMovement.Y >= 0.0f && colliderBottom.Y >= ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y*5)) return false; - + if (targetMovement.Y >= 0.0f && colliderBottom.Y >= ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 5)) return false; + //3. collided with the stairs from below if (contact.Manifold.LocalNormal.Y < 0.0f) return false; @@ -820,7 +827,73 @@ namespace Barotrauma } limb.Update(deltaTime); - } + } + + + bool onStairs = stairs != null; + stairs = null; + + var contacts = collider.FarseerBody.ContactList; + while (collider.FarseerBody.Enabled && contacts != null && contacts.Contact != null) + { + if (contacts.Contact.Enabled && contacts.Contact.IsTouching) + { + Vector2 normal; + FarseerPhysics.Common.FixedArray2 points; + + contacts.Contact.GetWorldManifold(out normal, out points); + + switch (contacts.Contact.FixtureA.CollisionCategories) + { + case Physics.CollisionStairs: + Structure structure = contacts.Contact.FixtureA.Body.UserData as Structure; + if (structure != null && onStairs) + { + stairs = structure; + } + break; + } + // 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; + //} + + + if (points[0].Y < collider.SimPosition.Y) + { + floorY = Math.Max(floorY, points[0].Y); + + onGround = true; + onFloorTimer = 0.1f; + } + + + } + + contacts = contacts.Next; + } + + //the ragdoll "stays on ground" for 50 millisecs after separation + if (onFloorTimer <= 0.0f) + { + onGround = false; + } + else + { + onFloorTimer -= deltaTime; + } + + } private float GetFloorY() diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 49644e33c..945aefd28 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -242,7 +242,6 @@ namespace Barotrauma body.Restitution = 0.05f; body.BodyType = BodyType.Dynamic; - //body.AngularDamping = Limb.LimbAngularDamping; body.UserData = this; @@ -260,6 +259,11 @@ namespace Barotrauma body = BodyFactory.CreateRectangle(GameMain.World, width, height, density); bodyShape = Shape.Rectangle; } + else if (radius != 0.0f && width != 0.0f) + { + body = BodyFactory.CreateCapsuleHorizontal(GameMain.World, width, radius, density); + bodyShape = Shape.Capsule; + } else if (radius != 0.0f && height != 0.0f) { body = BodyFactory.CreateCapsule(GameMain.World, height, radius, density); @@ -436,7 +440,7 @@ namespace Barotrauma case PhysicsBody.Shape.Capsule: bodyShapeTexture = GUI.CreateCapsule( (int)ConvertUnits.ToDisplayUnits(radius), - (int)ConvertUnits.ToDisplayUnits(height)); + (int)ConvertUnits.ToDisplayUnits(Math.Max(height,width))); break; case PhysicsBody.Shape.Circle: bodyShapeTexture = GUI.CreateCircle((int)ConvertUnits.ToDisplayUnits(radius)); @@ -444,12 +448,18 @@ namespace Barotrauma } } + float rot = -DrawRotation; + if (bodyShape == PhysicsBody.Shape.Capsule && width > height) + { + rot -= MathHelper.PiOver2; + } + spriteBatch.Draw( bodyShapeTexture, new Vector2(DrawPosition.X, -DrawPosition.Y), null, color, - -DrawRotation, + rot, new Vector2(bodyShapeTexture.Width / 2, bodyShapeTexture.Height / 2), 1.0f, SpriteEffects.None, 0.0f); }