water ambience sounds change according to speed, oxygengenerator fills oxygen tanks even if their condition is 0, submarine refactoring & bugfixes, wire node editing bugfixes
This commit is contained in:
@@ -11,37 +11,32 @@ namespace Subsurface
|
||||
{
|
||||
private Vector2 position;
|
||||
|
||||
private float range;
|
||||
private float damage;
|
||||
private float structureDamage;
|
||||
private float stun;
|
||||
|
||||
private Attack attack;
|
||||
|
||||
private float force;
|
||||
|
||||
private LightSource light;
|
||||
|
||||
public float CameraShake;
|
||||
|
||||
public Explosion(Vector2 position, float range, float damage, float structureDamage, float stun = 0.0f, float force = 0.0f)
|
||||
{
|
||||
this.position = position;
|
||||
this.range = Math.Max(range, 1.0f);
|
||||
this.damage = damage;
|
||||
this.structureDamage = structureDamage;
|
||||
this.stun = stun;
|
||||
this.force = force;
|
||||
//public Explosion(Vector2 position, float range, float damage, float structureDamage, float stun = 0.0f, float force = 0.0f)
|
||||
//{
|
||||
// this.position = position;
|
||||
|
||||
CameraShake = range*10.0f;
|
||||
}
|
||||
// attack = new Attack(,);
|
||||
|
||||
// this.force = force;
|
||||
|
||||
|
||||
//}
|
||||
|
||||
public Explosion(XElement element)
|
||||
{
|
||||
range = Math.Max(ToolBox.GetAttributeFloat(element, "range", 1.0f), 1.0f);
|
||||
damage = ToolBox.GetAttributeFloat(element, "damage", 0.0f);
|
||||
structureDamage = ToolBox.GetAttributeFloat(element, "structuredamage", 0.0f);
|
||||
stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f);
|
||||
attack = new Attack(element);
|
||||
|
||||
force = ToolBox.GetAttributeFloat(element, "force", 0.0f);
|
||||
|
||||
CameraShake = attack.Range*10.0f;
|
||||
}
|
||||
|
||||
public void Explode()
|
||||
@@ -56,7 +51,7 @@ namespace Subsurface
|
||||
GameMain.ParticleManager.CreateParticle("shockwave", displayPosition,
|
||||
Vector2.Zero, 0.0f);
|
||||
|
||||
for (int i = 0; i < range * 10; i++)
|
||||
for (int i = 0; i < attack.Range * 10; i++)
|
||||
{
|
||||
GameMain.ParticleManager.CreateParticle("spark", displayPosition,
|
||||
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f);
|
||||
@@ -67,7 +62,7 @@ namespace Subsurface
|
||||
|
||||
|
||||
|
||||
float displayRange = ConvertUnits.ToDisplayUnits(range);
|
||||
float displayRange = ConvertUnits.ToDisplayUnits(attack.Range);
|
||||
|
||||
light = new LightSource(displayPosition, displayRange, Color.LightYellow);
|
||||
CoroutineManager.StartCoroutine(DimLight());
|
||||
@@ -75,7 +70,7 @@ namespace Subsurface
|
||||
float cameraDist = Vector2.Distance(GameMain.GameScreen.Cam.Position, displayPosition)/2.0f;
|
||||
GameMain.GameScreen.Cam.Shake = CameraShake * Math.Max((displayRange - cameraDist)/displayRange, 0.0f);
|
||||
|
||||
if (structureDamage > 0.0f)
|
||||
if (attack.StructureDamage > 0.0f)
|
||||
{
|
||||
List<Structure> structureList = new List<Structure>();
|
||||
|
||||
@@ -98,7 +93,7 @@ namespace Subsurface
|
||||
for (int i = 0; i < structure.SectionCount; i++)
|
||||
{
|
||||
float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i), displayPosition) / displayRange);
|
||||
if (distFactor > 0.0f) structure.AddDamage(i, structureDamage*distFactor);
|
||||
if (distFactor > 0.0f) structure.AddDamage(i, attack.StructureDamage*distFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,16 +102,16 @@ namespace Subsurface
|
||||
{
|
||||
float dist = Vector2.Distance(c.SimPosition, simPosition);
|
||||
|
||||
if (dist > range) continue;
|
||||
if (dist > attack.Range) continue;
|
||||
|
||||
float distFactor = 1.0f - dist / range;
|
||||
float distFactor = 1.0f - dist / attack.Range;
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
distFactor = 1.0f - Vector2.Distance(limb.SimPosition, simPosition)/range;
|
||||
|
||||
c.AddDamage(limb.SimPosition, DamageType.None, damage / c.AnimController.Limbs.Length * distFactor, 0.0f, stun * distFactor);
|
||||
distFactor = 1.0f - Vector2.Distance(limb.SimPosition, simPosition)/attack.Range;
|
||||
|
||||
c.AddDamage(limb.SimPosition, DamageType.None,
|
||||
attack.Damage / c.AnimController.Limbs.Length * distFactor, 0.0f, attack.Stun * distFactor, true);
|
||||
if (force>0.0f)
|
||||
{
|
||||
limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.SimPosition - simPosition) * distFactor * force);
|
||||
|
||||
@@ -40,6 +40,13 @@ namespace Subsurface
|
||||
get { return flowForce*soundVolume; }
|
||||
}
|
||||
|
||||
public Vector2 LerpedFlowForce
|
||||
{
|
||||
get { return lerpedFlowForce; }
|
||||
}
|
||||
|
||||
private Vector2 lerpedFlowForce;
|
||||
|
||||
public Hull FlowTargetHull
|
||||
{
|
||||
get { return flowTargetHull; }
|
||||
@@ -178,6 +185,14 @@ namespace Subsurface
|
||||
|
||||
public override void Draw(SpriteBatch sb, bool editing)
|
||||
{
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
Vector2 center = new Vector2(rect.X + rect.Width / 2.0f, -(rect.Y - rect.Width / 2.0f));
|
||||
GUI.DrawLine(sb, center, center + flowForce/10.0f, Color.Red);
|
||||
|
||||
GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + lerpedFlowForce / 10.0f + Vector2.One * 5.0f, Color.Orange);
|
||||
}
|
||||
|
||||
if (!editing) return;
|
||||
|
||||
Color clr = (open == 0.0f) ? Color.Red : Color.Cyan;
|
||||
@@ -251,6 +266,8 @@ namespace Subsurface
|
||||
UpdateRoomToRoom(deltaTime);
|
||||
}
|
||||
|
||||
lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, 0.1f);
|
||||
|
||||
if (FlowForce.Length() > 150.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume)
|
||||
{
|
||||
//UpdateFlowForce();
|
||||
|
||||
@@ -19,6 +19,6 @@ namespace Subsurface
|
||||
get;
|
||||
}
|
||||
|
||||
AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true);
|
||||
AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound=true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,10 @@ namespace Subsurface
|
||||
public static bool DisableSelect
|
||||
{
|
||||
get { return disableSelect; }
|
||||
set {
|
||||
set
|
||||
{
|
||||
disableSelect = value;
|
||||
if (disableSelect==true)
|
||||
if (disableSelect)
|
||||
{
|
||||
startMovingPos = Vector2.Zero;
|
||||
selectionSize = Vector2.Zero;
|
||||
@@ -52,6 +53,12 @@ namespace Subsurface
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool SelectedAny
|
||||
{
|
||||
get { return selectedList.Count > 0; }
|
||||
}
|
||||
|
||||
public bool MoveWithLevel
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -386,11 +386,11 @@ namespace Subsurface
|
||||
|
||||
}
|
||||
|
||||
public int FindSectionIndex(Vector2 pos)
|
||||
public int FindSectionIndex(Vector2 displayPos)
|
||||
{
|
||||
int index = (isHorizontal) ?
|
||||
(int)Math.Floor((pos.X - rect.X) / wallSectionSize) :
|
||||
(int)Math.Floor((rect.Y - pos.Y) / wallSectionSize);
|
||||
(int)Math.Floor((displayPos.X - rect.X) / wallSectionSize) :
|
||||
(int)Math.Floor((rect.Y - displayPos.Y) / wallSectionSize);
|
||||
|
||||
if (index < 0 || index > sections.Length - 1) return -1;
|
||||
return index;
|
||||
@@ -412,7 +412,7 @@ namespace Subsurface
|
||||
sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f);
|
||||
}
|
||||
|
||||
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false)
|
||||
public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = false)
|
||||
{
|
||||
if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f);
|
||||
|
||||
@@ -423,13 +423,13 @@ namespace Subsurface
|
||||
|
||||
if (playSound && !SectionHasHole(i))
|
||||
{
|
||||
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
|
||||
AmbientSoundManager.PlayDamageSound(damageSoundType, amount, position);
|
||||
DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
|
||||
AmbientSoundManager.PlayDamageSound(damageSoundType, attack.Damage, position);
|
||||
}
|
||||
|
||||
AddDamage(i, amount);
|
||||
AddDamage(i, attack.Damage);
|
||||
|
||||
return new AttackResult(amount, 0.0f);
|
||||
return new AttackResult(attack.Damage, 0.0f);
|
||||
}
|
||||
|
||||
private void SetDamage(int sectionIndex, float damage)
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Factories;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -15,7 +12,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using Voronoi2;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
@@ -32,20 +28,14 @@ namespace Subsurface
|
||||
|
||||
private static Submarine loaded;
|
||||
|
||||
private SubmarineBody subBody;
|
||||
|
||||
private static Vector2 lastPickedPosition;
|
||||
private static float lastPickedFraction;
|
||||
|
||||
static string SaveFolder;
|
||||
Md5Hash hash;
|
||||
|
||||
Vector2 speed;
|
||||
|
||||
Vector2 targetPosition;
|
||||
|
||||
private Rectangle borders;
|
||||
|
||||
private Body hullBody;
|
||||
|
||||
private string filePath;
|
||||
private string name;
|
||||
|
||||
@@ -70,12 +60,6 @@ namespace Subsurface
|
||||
get { return lastPickedFraction; }
|
||||
}
|
||||
|
||||
public List<Vector2> HullVertices
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Md5Hash MD5Hash
|
||||
{
|
||||
get
|
||||
@@ -98,14 +82,11 @@ namespace Subsurface
|
||||
{
|
||||
get
|
||||
{
|
||||
return (loaded==null) ? Rectangle.Empty : loaded.borders;
|
||||
return (loaded==null) ? Rectangle.Empty : Loaded.subBody.Borders;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 Center
|
||||
{
|
||||
get { return new Vector2(borders.X+borders.Width/2, borders.Y - borders.Height/2); }
|
||||
}
|
||||
|
||||
|
||||
public Vector2 Position
|
||||
{
|
||||
@@ -114,14 +95,16 @@ namespace Subsurface
|
||||
|
||||
public Vector2 Speed
|
||||
{
|
||||
get { return speed; }
|
||||
set
|
||||
{
|
||||
if (!MathUtils.IsValid(value)) return;
|
||||
speed = value;
|
||||
}
|
||||
get { return subBody.Speed; }
|
||||
set { subBody.Speed = value; }
|
||||
}
|
||||
|
||||
public List<Vector2> HullVertices
|
||||
{
|
||||
get { return subBody.HullVertices; }
|
||||
}
|
||||
|
||||
|
||||
public string FilePath
|
||||
{
|
||||
get { return filePath; }
|
||||
@@ -162,69 +145,6 @@ namespace Subsurface
|
||||
ID = -1;
|
||||
}
|
||||
|
||||
private List<Vector2> GenerateConvexHull()
|
||||
{
|
||||
List<Vector2> points = new List<Vector2>();
|
||||
|
||||
Vector2 leftMost = Vector2.Zero;
|
||||
|
||||
foreach (Structure wall in Structure.wallList)
|
||||
{
|
||||
for (int x = -1; x <= 1; x += 2)
|
||||
{
|
||||
for (int y = -1; y <= 1; y += 2)
|
||||
{
|
||||
Vector2 corner = new Vector2(wall.Rect.X + wall.Rect.Width / 2.0f, wall.Rect.Y - wall.Rect.Height / 2.0f);
|
||||
corner.X += x * wall.Rect.Width / 2.0f;
|
||||
corner.Y += y * wall.Rect.Height / 2.0f;
|
||||
|
||||
if (points.Contains(corner)) continue;
|
||||
|
||||
points.Add(corner);
|
||||
if (leftMost == Vector2.Zero || corner.X < leftMost.X) leftMost = corner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Vector2> hullPoints = new List<Vector2>();
|
||||
|
||||
Vector2 currPoint = leftMost;
|
||||
Vector2 endPoint;
|
||||
do
|
||||
{
|
||||
hullPoints.Add(currPoint);
|
||||
endPoint = points[0];
|
||||
|
||||
for (int i = 1; i < points.Count; i++)
|
||||
{
|
||||
if ((currPoint == endPoint)
|
||||
|| (Orientation(currPoint, endPoint, points[i]) == -1))
|
||||
{
|
||||
endPoint = points[i];
|
||||
}
|
||||
}
|
||||
|
||||
currPoint = endPoint;
|
||||
|
||||
}
|
||||
while (endPoint != hullPoints[0]);
|
||||
|
||||
return hullPoints;
|
||||
}
|
||||
|
||||
private static int Orientation(Vector2 p1, Vector2 p2, Vector2 p)
|
||||
{
|
||||
// Determinant
|
||||
float Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y);
|
||||
|
||||
if (Orin > 0)
|
||||
return -1; // (* Orientation is to the left-hand side *)
|
||||
if (Orin < 0)
|
||||
return 1; // (* Orientation is to the right-hand side *)
|
||||
|
||||
return 0; // (* Orientation is neutral aka collinear *)
|
||||
}
|
||||
|
||||
//drawing ----------------------------------------------------
|
||||
|
||||
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
@@ -419,188 +339,41 @@ namespace Subsurface
|
||||
|
||||
//movement ----------------------------------------------------
|
||||
|
||||
float collisionRigidness = 1.0f;
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
Vector2 translateAmount = speed * deltaTime;
|
||||
translateAmount += ConvertUnits.ToDisplayUnits(hullBody.Position) * collisionRigidness;
|
||||
|
||||
if (targetPosition != Vector2.Zero && Vector2.Distance(targetPosition, Position) > 50.0f)
|
||||
{
|
||||
translateAmount += (targetPosition - Position) * 0.01f;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPosition = Vector2.Zero;
|
||||
}
|
||||
|
||||
Translate(translateAmount);
|
||||
|
||||
//-------------------------
|
||||
|
||||
Vector2 totalForce = CalculateBuoyancy();
|
||||
|
||||
float dragCoefficient = 0.00001f;
|
||||
|
||||
float speedLength = (speed == Vector2.Zero) ? 0.0f : speed.Length();
|
||||
float drag = speedLength * speedLength * dragCoefficient * mass;
|
||||
|
||||
if (speed != Vector2.Zero)
|
||||
{
|
||||
totalForce += -Vector2.Normalize(speed) * drag;
|
||||
}
|
||||
|
||||
ApplyForce(totalForce);
|
||||
|
||||
//hullBodies[0].body.LinearVelocity = -hullBodies[0].body.Position;
|
||||
|
||||
//hullBody.SetTransform(Vector2.Zero , 0.0f);
|
||||
hullBody.LinearVelocity = -hullBody.Position/(float)Physics.step;
|
||||
|
||||
if (collidingCell == null)
|
||||
{
|
||||
collisionRigidness = MathHelper.Lerp(collisionRigidness, 1.0f, 0.1f);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (GraphEdge ge in collidingCell.edges)
|
||||
{
|
||||
Body body = PickBody(
|
||||
ConvertUnits.ToSimUnits(ge.point1+ GameMain.GameSession.Level.Position),
|
||||
ConvertUnits.ToSimUnits(ge.point2 + GameMain.GameSession.Level.Position), new List<Body>(){collidingCell.body});
|
||||
if (body == null || body.UserData == null) continue;
|
||||
|
||||
Structure structure = body.UserData as Structure;
|
||||
if (structure == null) continue;
|
||||
structure.AddDamage(lastPickedPosition, DamageType.Blunt, 50.0f, 0.0f, 0.0f, true);
|
||||
}
|
||||
|
||||
collidingCell = null;
|
||||
|
||||
//hullBodies[0].body.SetTransform(Vector2.Zero, 0.0f);
|
||||
|
||||
//position = hullBodies[0].body.Position;
|
||||
|
||||
//Level.Loaded.Move(-ConvertUnits.ToDisplayUnits(position - prevPosition));
|
||||
|
||||
//prevPosition = hullBodies[0].body.Position;
|
||||
if (Level.Loaded == null) return;
|
||||
|
||||
subBody.Update(deltaTime);
|
||||
}
|
||||
|
||||
private Vector2 CalculateBuoyancy()
|
||||
public void ApplyForce(Vector2 force)
|
||||
{
|
||||
float waterVolume = 0.0f;
|
||||
float volume = 0.0f;
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
waterVolume += hull.Volume;
|
||||
volume += hull.FullVolume;
|
||||
}
|
||||
|
||||
float waterPercentage = waterVolume / volume;
|
||||
|
||||
float neutralPercentage = 0.07f;
|
||||
|
||||
float buoyancy = neutralPercentage-waterPercentage;
|
||||
buoyancy *= mass * 30.0f;
|
||||
|
||||
return new Vector2(0.0f, buoyancy);
|
||||
subBody.ApplyForce(force);
|
||||
}
|
||||
|
||||
public void SetPosition(Vector2 position)
|
||||
{
|
||||
//hullBodies[0].body.SetTransform(position, 0.0f);
|
||||
if (!MathUtils.IsValid(position)) return;
|
||||
Level.Loaded.SetPosition(-position);
|
||||
//prevPosition = position;
|
||||
}
|
||||
|
||||
private void Translate(Vector2 amount)
|
||||
public void Translate(Vector2 amount)
|
||||
{
|
||||
if (amount == Vector2.Zero || !amount.IsValid()) return;
|
||||
if (amount == Vector2.Zero || !MathUtils.IsValid(amount)) return;
|
||||
|
||||
Level.Loaded.Move(-amount);
|
||||
}
|
||||
|
||||
float mass = 10000.0f;
|
||||
public void ApplyForce(Vector2 force)
|
||||
{
|
||||
speed += force/mass;
|
||||
}
|
||||
|
||||
VoronoiCell collidingCell;
|
||||
public bool OnCollision(Fixture f1, Fixture f2, Contact contact)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("colliding");
|
||||
VoronoiCell cell = f2.Body.UserData as VoronoiCell;
|
||||
if (cell==null) return true;
|
||||
|
||||
Vector2 normal = contact.Manifold.LocalNormal;
|
||||
Vector2 simSpeed = ConvertUnits.ToSimUnits(speed);
|
||||
float impact = Vector2.Dot(simSpeed, normal);
|
||||
|
||||
Vector2 u = Vector2.Dot(simSpeed, -normal)*-normal;
|
||||
Vector2 w = simSpeed - u;
|
||||
|
||||
Vector2 limbForce = normal * impact;
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull == null) continue;
|
||||
|
||||
if (impact > 2.0f) c.AnimController.StunTimer = (impact - 2.0f) * 0.1f;
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * limbForce);
|
||||
}
|
||||
}
|
||||
|
||||
if (impact >= 1.0f)
|
||||
{
|
||||
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, cell.body);
|
||||
|
||||
FixedArray2<Vector2> worldPoints;
|
||||
contact.GetWorldManifold(out normal, out worldPoints);
|
||||
|
||||
|
||||
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(worldPoints[0]));
|
||||
|
||||
GameMain.GameScreen.Cam.Shake = impact*2.0f;
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("IMPACT: "+impact + " normal: "+normal+" simspeed: "+simSpeed+" u: "+u+" w: " +w);
|
||||
if (impact < 4.0f)
|
||||
{
|
||||
speed = ConvertUnits.ToDisplayUnits(w * 0.9f - u * 0.2f);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = ConvertUnits.ToDisplayUnits(w * 0.9f + u * 0.5f);
|
||||
}
|
||||
|
||||
|
||||
collisionRigidness = 0.8f;
|
||||
|
||||
collidingCell = cell;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnSeparation(Fixture f1, Fixture f2)
|
||||
{
|
||||
collidingCell = null;
|
||||
}
|
||||
|
||||
public override void FillNetworkData(Networking.NetworkEventType type, NetOutgoingMessage message, object data)
|
||||
{
|
||||
message.Write((float)NetTime.Now);
|
||||
message.Write(Position.X);
|
||||
message.Write(Position.Y);
|
||||
|
||||
message.Write(speed.X);
|
||||
message.Write(speed.Y);
|
||||
message.Write(Speed.X);
|
||||
message.Write(Speed.Y);
|
||||
|
||||
}
|
||||
|
||||
@@ -630,13 +403,12 @@ namespace Subsurface
|
||||
|
||||
//newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime);
|
||||
|
||||
targetPosition = newTargetPosition;
|
||||
speed = newSpeed;
|
||||
subBody.TargetPosition = newTargetPosition;
|
||||
subBody.Speed = newSpeed;
|
||||
|
||||
lastNetworkUpdate = sendingTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//saving/loading ----------------------------------------------------
|
||||
|
||||
@@ -829,42 +601,7 @@ namespace Subsurface
|
||||
|
||||
}
|
||||
|
||||
List<Vector2> convexHull = GenerateConvexHull();
|
||||
|
||||
HullVertices = convexHull;
|
||||
|
||||
for (int i = 0; i < convexHull.Count; i++)
|
||||
{
|
||||
convexHull[i] = ConvertUnits.ToSimUnits(convexHull[i]);
|
||||
}
|
||||
|
||||
convexHull.Reverse();
|
||||
|
||||
//get farseer 'vertices' from vectors
|
||||
Vertices shapevertices = new Vertices(convexHull);
|
||||
|
||||
AABB hullAABB = shapevertices.GetAABB();
|
||||
|
||||
borders = new Rectangle(
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.LowerBound.X),
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.UpperBound.Y),
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f),
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f));
|
||||
|
||||
|
||||
var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit);
|
||||
|
||||
hullBody = BodyFactory.CreateCompoundPolygon(GameMain.World, triangulatedVertices, 5.0f);
|
||||
hullBody.BodyType = BodyType.Dynamic;
|
||||
|
||||
hullBody.CollisionCategories = Physics.CollisionMisc;
|
||||
hullBody.CollidesWith = Physics.CollisionLevel;
|
||||
hullBody.FixedRotation = true;
|
||||
hullBody.Awake = true;
|
||||
hullBody.SleepingAllowed = false;
|
||||
hullBody.GravityScale = 0.0f;
|
||||
hullBody.OnCollision += OnCollision;
|
||||
hullBody.OnSeparation += OnSeparation;
|
||||
subBody = new SubmarineBody(this);
|
||||
|
||||
MapEntity.LinkAll();
|
||||
|
||||
@@ -908,6 +645,8 @@ namespace Subsurface
|
||||
{
|
||||
if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
|
||||
subBody = null;
|
||||
|
||||
Entity.RemoveAll();
|
||||
|
||||
PhysicsBody.list.Clear();
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Common;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Factories;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Voronoi2;
|
||||
|
||||
namespace Subsurface
|
||||
{
|
||||
class SubmarineBody
|
||||
{
|
||||
|
||||
public List<Vector2> HullVertices
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private Submarine sub;
|
||||
|
||||
private Body body;
|
||||
|
||||
private Vector2 speed;
|
||||
|
||||
private Vector2 targetPosition;
|
||||
|
||||
public Rectangle Borders
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Vector2 Speed
|
||||
{
|
||||
get { return speed; }
|
||||
set
|
||||
{
|
||||
if (!MathUtils.IsValid(value)) return;
|
||||
speed = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 TargetPosition
|
||||
{
|
||||
get { return targetPosition; }
|
||||
set
|
||||
{
|
||||
if (!MathUtils.IsValid(value)) return;
|
||||
targetPosition = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Vector2 Center
|
||||
{
|
||||
get { return new Vector2(Borders.X + Borders.Width / 2, Borders.Y - Borders.Height / 2); }
|
||||
}
|
||||
|
||||
public SubmarineBody(Submarine sub)
|
||||
{
|
||||
this.sub = sub;
|
||||
|
||||
|
||||
List<Vector2> convexHull = GenerateConvexHull();
|
||||
HullVertices = convexHull;
|
||||
|
||||
for (int i = 0; i < convexHull.Count; i++)
|
||||
{
|
||||
convexHull[i] = ConvertUnits.ToSimUnits(convexHull[i]);
|
||||
}
|
||||
|
||||
convexHull.Reverse();
|
||||
|
||||
//get farseer 'vertices' from vectors
|
||||
Vertices shapevertices = new Vertices(convexHull);
|
||||
|
||||
AABB hullAABB = shapevertices.GetAABB();
|
||||
|
||||
Borders = new Rectangle(
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.LowerBound.X),
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.UpperBound.Y),
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f),
|
||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f));
|
||||
|
||||
|
||||
var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit);
|
||||
|
||||
body = BodyFactory.CreateCompoundPolygon(GameMain.World, triangulatedVertices, 5.0f);
|
||||
body.BodyType = BodyType.Dynamic;
|
||||
|
||||
body.CollisionCategories = Physics.CollisionMisc;
|
||||
body.CollidesWith = Physics.CollisionLevel;
|
||||
body.FixedRotation = true;
|
||||
body.Awake = true;
|
||||
body.SleepingAllowed = false;
|
||||
body.GravityScale = 0.0f;
|
||||
body.OnCollision += OnCollision;
|
||||
body.OnSeparation += OnSeparation;
|
||||
}
|
||||
|
||||
|
||||
private List<Vector2> GenerateConvexHull()
|
||||
{
|
||||
List<Vector2> points = new List<Vector2>();
|
||||
|
||||
Vector2 leftMost = Vector2.Zero;
|
||||
|
||||
foreach (Structure wall in Structure.wallList)
|
||||
{
|
||||
for (int x = -1; x <= 1; x += 2)
|
||||
{
|
||||
for (int y = -1; y <= 1; y += 2)
|
||||
{
|
||||
Vector2 corner = new Vector2(wall.Rect.X + wall.Rect.Width / 2.0f, wall.Rect.Y - wall.Rect.Height / 2.0f);
|
||||
corner.X += x * wall.Rect.Width / 2.0f;
|
||||
corner.Y += y * wall.Rect.Height / 2.0f;
|
||||
|
||||
if (points.Contains(corner)) continue;
|
||||
|
||||
points.Add(corner);
|
||||
if (leftMost == Vector2.Zero || corner.X < leftMost.X) leftMost = corner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Vector2> hullPoints = new List<Vector2>();
|
||||
|
||||
Vector2 currPoint = leftMost;
|
||||
Vector2 endPoint;
|
||||
do
|
||||
{
|
||||
hullPoints.Add(currPoint);
|
||||
endPoint = points[0];
|
||||
|
||||
for (int i = 1; i < points.Count; i++)
|
||||
{
|
||||
if ((currPoint == endPoint)
|
||||
|| (MathUtils.VectorOrientation(currPoint, endPoint, points[i]) == -1))
|
||||
{
|
||||
endPoint = points[i];
|
||||
}
|
||||
}
|
||||
|
||||
currPoint = endPoint;
|
||||
|
||||
}
|
||||
while (endPoint != hullPoints[0]);
|
||||
|
||||
return hullPoints;
|
||||
}
|
||||
|
||||
|
||||
float collisionRigidness = 1.0f;
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
Vector2 translateAmount = speed * deltaTime;
|
||||
translateAmount += ConvertUnits.ToDisplayUnits(body.Position) * collisionRigidness;
|
||||
|
||||
if (targetPosition != Vector2.Zero && Vector2.Distance(targetPosition, sub.Position) > 50.0f)
|
||||
{
|
||||
translateAmount += (targetPosition - sub.Position) * 0.01f;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPosition = Vector2.Zero;
|
||||
}
|
||||
|
||||
sub.Translate(translateAmount);
|
||||
|
||||
//-------------------------
|
||||
|
||||
Vector2 totalForce = CalculateBuoyancy();
|
||||
|
||||
float dragCoefficient = 0.00001f;
|
||||
|
||||
float speedLength = (speed == Vector2.Zero) ? 0.0f : speed.Length();
|
||||
float drag = speedLength * speedLength * dragCoefficient * mass;
|
||||
|
||||
if (speed != Vector2.Zero)
|
||||
{
|
||||
totalForce += -Vector2.Normalize(speed) * drag;
|
||||
}
|
||||
|
||||
ApplyForce(totalForce);
|
||||
|
||||
//hullBodies[0].body.LinearVelocity = -hullBodies[0].body.Position;
|
||||
|
||||
//hullBody.SetTransform(Vector2.Zero , 0.0f);
|
||||
body.LinearVelocity = -body.Position / (float)Physics.step;
|
||||
|
||||
if (collidingCell == null)
|
||||
{
|
||||
collisionRigidness = MathHelper.Lerp(collisionRigidness, 1.0f, 0.1f);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (GraphEdge ge in collidingCell.edges)
|
||||
{
|
||||
Body wallBody = Submarine.PickBody(
|
||||
ConvertUnits.ToSimUnits(ge.point1 + GameMain.GameSession.Level.Position),
|
||||
ConvertUnits.ToSimUnits(ge.point2 + GameMain.GameSession.Level.Position), new List<Body>() { collidingCell.body });
|
||||
if (wallBody == null || wallBody.UserData == null) continue;
|
||||
|
||||
Structure structure = wallBody.UserData as Structure;
|
||||
if (structure == null) continue;
|
||||
structure.AddDamage(
|
||||
structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition)), 50.0f);
|
||||
}
|
||||
|
||||
collidingCell = null;
|
||||
}
|
||||
|
||||
private Vector2 CalculateBuoyancy()
|
||||
{
|
||||
float waterVolume = 0.0f;
|
||||
float volume = 0.0f;
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
{
|
||||
waterVolume += hull.Volume;
|
||||
volume += hull.FullVolume;
|
||||
}
|
||||
|
||||
float waterPercentage = waterVolume / volume;
|
||||
|
||||
float neutralPercentage = 0.07f;
|
||||
|
||||
float buoyancy = neutralPercentage - waterPercentage;
|
||||
buoyancy *= mass * 30.0f;
|
||||
|
||||
return new Vector2(0.0f, buoyancy);
|
||||
}
|
||||
|
||||
float mass = 10000.0f;
|
||||
public void ApplyForce(Vector2 force)
|
||||
{
|
||||
speed += force / mass;
|
||||
}
|
||||
|
||||
VoronoiCell collidingCell;
|
||||
public bool OnCollision(Fixture f1, Fixture f2, Contact contact)
|
||||
{
|
||||
VoronoiCell cell = f2.Body.UserData as VoronoiCell;
|
||||
if (cell == null)
|
||||
{
|
||||
speed = new Vector2(speed.X * 0.9f, speed.Y * 0.2f);
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector2 normal = contact.Manifold.LocalNormal;
|
||||
Vector2 simSpeed = ConvertUnits.ToSimUnits(speed);
|
||||
float impact = Vector2.Dot(simSpeed, normal);
|
||||
|
||||
Vector2 u = Vector2.Dot(simSpeed, -normal) * -normal;
|
||||
Vector2 w = simSpeed - u;
|
||||
|
||||
Vector2 limbForce = normal * impact;
|
||||
|
||||
float length = limbForce.Length();
|
||||
if (length > 10.0f) limbForce = (limbForce / length) * 10.0f;
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull == null) continue;
|
||||
|
||||
if (impact > 2.0f) c.AnimController.StunTimer = (impact - 2.0f) * 0.1f;
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (c.AnimController.LowestLimb == limb) continue;
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * limbForce);
|
||||
}
|
||||
}
|
||||
|
||||
if (impact >= 1.0f)
|
||||
{
|
||||
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, cell.body);
|
||||
|
||||
FarseerPhysics.Common.FixedArray2<Vector2> worldPoints;
|
||||
contact.GetWorldManifold(out normal, out worldPoints);
|
||||
|
||||
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(worldPoints[0]));
|
||||
|
||||
GameMain.GameScreen.Cam.Shake = impact * 2.0f;
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("IMPACT: " + impact + " normal: " + normal + " simspeed: " + simSpeed + " u: " + u + " w: " + w);
|
||||
if (impact < 4.0f)
|
||||
{
|
||||
speed = ConvertUnits.ToDisplayUnits(w * 0.9f - u * 0.2f);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = ConvertUnits.ToDisplayUnits(w * 0.9f + u * 0.5f);
|
||||
}
|
||||
|
||||
|
||||
collisionRigidness = 0.8f;
|
||||
|
||||
collidingCell = cell;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnSeparation(Fixture f1, Fixture f2)
|
||||
{
|
||||
collidingCell = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user