diff --git a/Subsurface/Characters/AI/SteeringManager.cs b/Subsurface/Characters/AI/SteeringManager.cs index 7a371dcc2..e65798f6b 100644 --- a/Subsurface/Characters/AI/SteeringManager.cs +++ b/Subsurface/Characters/AI/SteeringManager.cs @@ -32,7 +32,7 @@ namespace Subsurface { this.host = host; - wanderAngle = ToolBox.RandomFloatLocal(0.0f, MathHelper.TwoPi); + wanderAngle = MathUtils.RandomFloatLocal(0.0f, MathHelper.TwoPi); } public void SteeringSeek(Vector2 target, float speed = 1.0f) @@ -90,7 +90,7 @@ namespace Subsurface float angleChange = 1.5f; - wanderAngle += ToolBox.RandomFloatLocal(0.0f, 1.0f) * angleChange - angleChange * 0.5f; + wanderAngle += MathUtils.RandomFloatLocal(0.0f, 1.0f) * angleChange - angleChange * 0.5f; Vector2 newSteering = circleCenter + displacement; float steeringSpeed = (newSteering + host.Steering).Length(); diff --git a/Subsurface/Characters/Character.cs b/Subsurface/Characters/Character.cs index a8470820f..04510c06b 100644 --- a/Subsurface/Characters/Character.cs +++ b/Subsurface/Characters/Character.cs @@ -769,13 +769,13 @@ namespace Subsurface for (int i = 0; i < 10; i++) { Particle p = Game1.particleManager.CreateParticle("waterblood", - torso.SimPosition + new Vector2(ToolBox.RandomFloatLocal(-0.5f, 0.5f), ToolBox.RandomFloatLocal(-0.5f, 0.5f)), + torso.SimPosition + new Vector2(MathUtils.RandomFloatLocal(-0.5f, 0.5f), MathUtils.RandomFloatLocal(-0.5f, 0.5f)), Vector2.Zero); if (p!=null) p.Size *= 2.0f; Game1.particleManager.CreateParticle("bubbles", torso.SimPosition, - new Vector2(ToolBox.RandomFloatLocal(-0.5f, 0.5f), ToolBox.RandomFloatLocal(-1.0f,0.5f))); + new Vector2(MathUtils.RandomFloatLocal(-0.5f, 0.5f), MathUtils.RandomFloatLocal(-1.0f,0.5f))); } foreach (var joint in animController.limbJoints) diff --git a/Subsurface/Characters/FishAnimController.cs b/Subsurface/Characters/FishAnimController.cs index 91838b854..1767554df 100644 --- a/Subsurface/Characters/FishAnimController.cs +++ b/Subsurface/Characters/FishAnimController.cs @@ -72,7 +72,7 @@ namespace Subsurface else { Limb head = GetLimb(LimbType.Head); - float rotation = ToolBox.WrapAngleTwoPi(head.Rotation); + float rotation = MathUtils.WrapAngleTwoPi(head.Rotation); rotation = MathHelper.ToDegrees(rotation); if (rotation < 0.0f) rotation += 360; @@ -98,12 +98,12 @@ namespace Subsurface void UpdateSineAnim(float deltaTime) { - movement = ToolBox.SmoothStep(movement, TargetMovement*swimSpeed, 1.0f); + movement = MathUtils.SmoothStep(movement, TargetMovement*swimSpeed, 1.0f); if (movement == Vector2.Zero) return; if (!inWater) movement.Y = Math.Min(0.0f, movement.Y); - float movementAngle = ToolBox.VectorToAngle(movement) - MathHelper.PiOver2; + float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2; Limb tail = GetLimb(LimbType.Tail); if (tail != null && waveAmplitude>0.0f) @@ -112,7 +112,7 @@ namespace Subsurface float waveRotation = (float)Math.Sin(walkPos / waveLength)*waveAmplitude; - float angle = ToolBox.GetShortestAngle(tail.body.Rotation, movementAngle + waveRotation); + float angle = MathUtils.GetShortestAngle(tail.body.Rotation, movementAngle + waveRotation); //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); @@ -123,7 +123,7 @@ namespace Subsurface Limb head = GetLimb(LimbType.Head); if (head != null) { - float angle = ToolBox.GetShortestAngle(head.body.Rotation, movementAngle); + float angle = MathUtils.GetShortestAngle(head.body.Rotation, movementAngle); head.body.SmoothRotate(head.body.Rotation+angle, 25.0f); @@ -179,7 +179,7 @@ namespace Subsurface void UpdateWalkAnim(float deltaTime) { - movement = ToolBox.SmoothStep(movement, TargetMovement * walkSpeed, 0.2f); + movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, 0.2f); if (movement == Vector2.Zero) return; Limb colliderLimb; diff --git a/Subsurface/Characters/HumanoidAnimController.cs b/Subsurface/Characters/HumanoidAnimController.cs index 2b49680cd..2ca0847f3 100644 --- a/Subsurface/Characters/HumanoidAnimController.cs +++ b/Subsurface/Characters/HumanoidAnimController.cs @@ -174,7 +174,7 @@ namespace Subsurface float footMid = (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f; - movement = ToolBox.SmoothStep(movement, TargetMovement, 0.5f); + movement = MathUtils.SmoothStep(movement, TargetMovement, 0.5f); movement.Y = 0.0f; //place the anchors of the head and the torso to make the ragdoll stand @@ -201,12 +201,12 @@ namespace Subsurface { torso.pullJoint.Enabled = true; torso.pullJoint.WorldAnchorB = - ToolBox.SmoothStep(torso.SimPosition, + MathUtils.SmoothStep(torso.SimPosition, new Vector2(footMid + movement.X * 0.35f, colliderPos.Y + TorsoPosition - Math.Abs(walkPosX * 0.05f)), getUpSpeed); head.pullJoint.Enabled = true; head.pullJoint.WorldAnchorB = - ToolBox.SmoothStep(head.SimPosition, + MathUtils.SmoothStep(head.SimPosition, new Vector2(footMid + movement.X * 0.4f, colliderPos.Y + HeadPosition - Math.Abs(walkPosX * 0.05f)), getUpSpeed); } @@ -389,7 +389,7 @@ namespace Subsurface torso.body.ApplyTorque(torque); } - movement = ToolBox.SmoothStep(movement, TargetMovement, 0.3f); + movement = MathUtils.SmoothStep(movement, TargetMovement, 0.3f); //dont try to move upwards if head is already out of water if (surfaceLimiter > 1.0f) @@ -513,7 +513,7 @@ namespace Subsurface onGround = false; IgnorePlatforms = true; - movement = ToolBox.SmoothStep(movement, TargetMovement, 0.3f); + movement = MathUtils.SmoothStep(movement, TargetMovement, 0.3f); Vector2 footPos, handPos; @@ -543,12 +543,12 @@ namespace Subsurface MoveLimb(leftHand, new Vector2(handPos.X, - ToolBox.Round(handPos.Y - stepHeight, stepHeight * 2.0f) + stepHeight + ladderSimPos.Y), + MathUtils.Round(handPos.Y - stepHeight, stepHeight * 2.0f) + stepHeight + ladderSimPos.Y), 5.2f); MoveLimb(rightHand, new Vector2(handPos.X, - ToolBox.Round(handPos.Y, stepHeight * 2.0f) + ladderSimPos.Y), + MathUtils.Round(handPos.Y, stepHeight * 2.0f) + ladderSimPos.Y), 5.2f); leftHand.body.ApplyTorque(Dir * 2.0f); @@ -560,12 +560,12 @@ namespace Subsurface MoveLimb(leftFoot, new Vector2(footPos.X, - ToolBox.Round(footPos.Y + stepHeight, stepHeight * 2.0f) - stepHeight + ladderSimPos.Y), + MathUtils.Round(footPos.Y + stepHeight, stepHeight * 2.0f) - stepHeight + ladderSimPos.Y), 7.5f, true); MoveLimb(rightFoot, new Vector2(footPos.X, - ToolBox.Round(footPos.Y, stepHeight * 2.0f) + ladderSimPos.Y), + MathUtils.Round(footPos.Y, stepHeight * 2.0f) + ladderSimPos.Y), 7.5f, true); //apply torque to the legs to make the knees bend @@ -642,8 +642,8 @@ namespace Subsurface Vector2 diff = (mousePos - torso.SimPosition) * Dir; - holdAngle = ToolBox.VectorToAngle(new Vector2(diff.X, diff.Y * Dir)) - torso.body.Rotation * Dir; - holdAngle = MathHelper.Clamp(ToolBox.WrapAnglePi(holdAngle), -1.3f, 1.0f); + holdAngle = MathUtils.VectorToAngle(new Vector2(diff.X, diff.Y * Dir)) - torso.body.Rotation * Dir; + holdAngle = MathHelper.Clamp(MathUtils.WrapAnglePi(holdAngle), -1.3f, 1.0f); itemAngle = (torso.body.Rotation + holdAngle * Dir); @@ -701,7 +701,7 @@ namespace Subsurface Vector2 bodyVelocity = torso.body.LinearVelocity / 60.0f; item.body.ResetDynamics(); - item.body.SetTransform(ToolBox.SmoothStep(item.body.Position, transformedHoldPos + bodyVelocity, 0.5f), itemAngle); + item.body.SetTransform(MathUtils.SmoothStep(item.body.Position, transformedHoldPos + bodyVelocity, 0.5f), itemAngle); //item.body.SmoothRotate(itemAngle, 50.0f); @@ -723,10 +723,10 @@ namespace Subsurface float c = ConvertUnits.ToDisplayUnits(Vector2.Distance(transformedHoldPos + transformedHandlePos[i], shoulderPos)); c = MathHelper.Clamp(a + b - 1, b-a, c); - float ang2 = ToolBox.VectorToAngle((transformedHoldPos + transformedHandlePos[i]) - shoulderPos)+MathHelper.PiOver2; + float ang2 = MathUtils.VectorToAngle((transformedHoldPos + transformedHandlePos[i]) - shoulderPos)+MathHelper.PiOver2; - float armAngle = ToolBox.SolveTriangleSSS(a, b, c); - float handAngle = ToolBox.SolveTriangleSSS(b, a, c); + float armAngle = MathUtils.SolveTriangleSSS(a, b, c); + float handAngle = MathUtils.SolveTriangleSSS(b, a, c); arm.body.SmoothRotate((ang2 - armAngle * Dir), 20.0f); hand.body.SmoothRotate((ang2 + handAngle * Dir), 100.0f); @@ -755,7 +755,7 @@ namespace Subsurface character.SelectedItems[i].body.SetTransform( torso.SimPosition + Vector2.Transform(difference, -torsoTransform), - ToolBox.WrapAngleTwoPi(-character.SelectedItems[i].body.Rotation)); + MathUtils.WrapAngleTwoPi(-character.SelectedItems[i].body.Rotation)); } } @@ -775,7 +775,7 @@ namespace Subsurface break; default: if (!inWater) l.body.SetTransform(l.body.Position, - ToolBox.WrapAnglePi(l.body.Rotation * (l.DoesFlip ? -1.0f : 1.0f))); + MathUtils.WrapAnglePi(l.body.Rotation * (l.DoesFlip ? -1.0f : 1.0f))); break; } } diff --git a/Subsurface/Characters/Limb.cs b/Subsurface/Characters/Limb.cs index d62f04b3f..9f0ed97b3 100644 --- a/Subsurface/Characters/Limb.cs +++ b/Subsurface/Characters/Limb.cs @@ -275,7 +275,7 @@ namespace Subsurface float mid = (armorLimits.X + armorLimits.Y) / 2.0f; - float angleDiff = ToolBox.GetShortestAngle(ToolBox.VectorToAngle(position - SimPosition), mid); + float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(position - SimPosition), mid); if (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f) { @@ -314,7 +314,7 @@ namespace Subsurface Game1.particleManager.CreateParticle("blood", SimPosition, - particleVel * ToolBox.RandomFloatLocal(1.0f, 3.0f)); + particleVel * MathUtils.RandomFloatLocal(1.0f, 3.0f)); } for (int i = 0; i < bloodAmount / 2; i++) @@ -370,7 +370,7 @@ namespace Subsurface soundTimer -= deltaTime; - //if (ToolBox.RandomFloat(0.0f, 1000.0f) < Bleeding) + //if (MathUtils.RandomFloat(0.0f, 1000.0f) < Bleeding) //{ // Game1.particleManager.CreateParticle( // !inWater ? "blood" : "waterblood", diff --git a/Subsurface/Characters/Ragdoll.cs b/Subsurface/Characters/Ragdoll.cs index 932776d19..dc18b26f7 100644 --- a/Subsurface/Characters/Ragdoll.cs +++ b/Subsurface/Characters/Ragdoll.cs @@ -290,8 +290,7 @@ namespace Subsurface { Vector2 normal = contact.Manifold.LocalNormal; float impact = Vector2.Dot(f1.Body.LinearVelocity, -normal); - - + Limb l = (Limb)f1.Body.UserData; if (impact > 1.0f && l.HitSound != null && l.soundTimer<=0.0f) l.HitSound.Play(Math.Min(impact / 5.0f, 1.0f), impact*100.0f, l.body.FarseerBody); diff --git a/Subsurface/Content/Items/Engine/engine.png b/Subsurface/Content/Items/Engine/engine.png new file mode 100644 index 000000000..d8bf526cd Binary files /dev/null and b/Subsurface/Content/Items/Engine/engine.png differ diff --git a/Subsurface/Content/Items/Engine/engine.xml b/Subsurface/Content/Items/Engine/engine.xml new file mode 100644 index 000000000..4f804353d --- /dev/null +++ b/Subsurface/Content/Items/Engine/engine.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/Items/Engine/fabricator.png b/Subsurface/Content/Items/Engine/fabricator.png new file mode 100644 index 000000000..e82943efb Binary files /dev/null and b/Subsurface/Content/Items/Engine/fabricator.png differ diff --git a/Subsurface/Content/Items/Pump/pump.xml b/Subsurface/Content/Items/Pump/pump.xml index f4cd0ca95..edd6267a4 100644 --- a/Subsurface/Content/Items/Pump/pump.xml +++ b/Subsurface/Content/Items/Pump/pump.xml @@ -11,6 +11,7 @@ - + + diff --git a/Subsurface/Events/MonsterEvent.cs b/Subsurface/Events/MonsterEvent.cs index 7544fddc2..d060fa99a 100644 --- a/Subsurface/Events/MonsterEvent.cs +++ b/Subsurface/Events/MonsterEvent.cs @@ -32,8 +32,8 @@ namespace Subsurface for (int i = 0; i < amount; i++) { Vector2 position = (randomWayPoint == null) ? Vector2.Zero : randomWayPoint.SimPosition; - position.X += ToolBox.RandomFloatLocal(-0.5f,0.5f); - position.Y += ToolBox.RandomFloatLocal(-0.5f,0.5f); + position.X += MathUtils.RandomFloatLocal(-0.5f,0.5f); + position.Y += MathUtils.RandomFloatLocal(-0.5f,0.5f); monsters[i] = new Character(characterFile, position); } } diff --git a/Subsurface/FarseerPhysics MonoGame.dll b/Subsurface/FarseerPhysics MonoGame.dll deleted file mode 100644 index 66d295861..000000000 Binary files a/Subsurface/FarseerPhysics MonoGame.dll and /dev/null differ diff --git a/Subsurface/GUI/GUI.cs b/Subsurface/GUI/GUI.cs index 9408588f0..3f80d1b19 100644 --- a/Subsurface/GUI/GUI.cs +++ b/Subsurface/GUI/GUI.cs @@ -328,7 +328,7 @@ namespace Subsurface alpha -= 1.0f - msg.LifeTime; } - msg.Pos = ToolBox.SmoothStep(msg.Pos, currPos, deltaTime*20.0f); + msg.Pos = MathUtils.SmoothStep(msg.Pos, currPos, deltaTime*20.0f); spriteBatch.DrawString(font, msg.Text, new Vector2((int)msg.Pos.X, (int)msg.Pos.Y), diff --git a/Subsurface/GameSession/CrewManager.cs b/Subsurface/GameSession/CrewManager.cs index 631306fe2..7cde3fb91 100644 --- a/Subsurface/GameSession/CrewManager.cs +++ b/Subsurface/GameSession/CrewManager.cs @@ -107,14 +107,17 @@ namespace Subsurface GUIComponent characterBlock = listBox.GetChild(killedCharacter) as GUIComponent; if (characterBlock != null) characterBlock.Color = Color.DarkRed * 0.5f; - if (characters.Find(c => !c.IsDead)==null) - { - Game1.GameSession.EndShift(null, null); - } + //if (characters.Find(c => !c.IsDead)==null) + //{ + // Game1.GameSession.EndShift(null, null); + //} } public void StartShift() { + listBox.ClearChildren(); + characters.Clear(); + foreach (CharacterInfo ci in characterInfos) { WayPoint randomWayPoint = WayPoint.GetRandom(WayPoint.SpawnType.Human); diff --git a/Subsurface/GameSession/GameMode.cs b/Subsurface/GameSession/GameMode.cs index 5be3b8bfa..bdd7acd68 100644 --- a/Subsurface/GameSession/GameMode.cs +++ b/Subsurface/GameSession/GameMode.cs @@ -137,7 +137,7 @@ namespace Subsurface if (endMessage != "" || this.endMessage == null) this.endMessage = endMessage; - Game1.GameSession.EndShift(null, null); + Game1.GameSession.EndShift(endMessage); } public static void Init() diff --git a/Subsurface/GameSession/GameSession.cs b/Subsurface/GameSession/GameSession.cs index e2dab348a..641c14183 100644 --- a/Subsurface/GameSession/GameSession.cs +++ b/Subsurface/GameSession/GameSession.cs @@ -113,8 +113,7 @@ namespace Subsurface public void StartShift(TimeSpan duration, Level level) { - - if (Submarine.Loaded != submarine) submarine.Load(); + submarine.Load(); level.Generate(submarine==null ? 100.0f : Math.Max(Submarine.Borders.Width, Submarine.Borders.Height)); @@ -133,19 +132,17 @@ namespace Subsurface if (level!=null) { - submarine.Move(level.StartPosition - submarine.Center, 1.0f); + submarine.SetPosition(level.StartPosition); } //crewManager.StartShift(); taskManager.StartShift(scriptedEventCount); } - public bool EndShift(GUIButton button, object obj) + public void EndShift(string endMessage) { if (Game1.Server!=null) - { - string endMessage = gameMode.EndMessage; - + { Game1.Server.EndGame(endMessage); } @@ -159,7 +156,7 @@ namespace Subsurface taskManager.EndShift(); //gameMode.End(); - return true; + //return true; } diff --git a/Subsurface/GameSession/SinglePlayerMode.cs b/Subsurface/GameSession/SinglePlayerMode.cs index d644d04ae..924f11b53 100644 --- a/Subsurface/GameSession/SinglePlayerMode.cs +++ b/Subsurface/GameSession/SinglePlayerMode.cs @@ -156,7 +156,7 @@ namespace Subsurface Character.characterList.RemoveAt(i); } - Game1.GameSession.EndShift(null, null); + Game1.GameSession.EndShift(""); return true; } diff --git a/Subsurface/Items/CharacterInventory.cs b/Subsurface/Items/CharacterInventory.cs index e61fce794..17611bd93 100644 --- a/Subsurface/Items/CharacterInventory.cs +++ b/Subsurface/Items/CharacterInventory.cs @@ -231,6 +231,7 @@ namespace Subsurface } else { + draggingItem.body.SetTransform(character.SimPosition, 0.0f); draggingItem.Drop(character); //draggingItem = null; } diff --git a/Subsurface/Items/Components/Engine.cs b/Subsurface/Items/Components/Engine.cs new file mode 100644 index 000000000..4db0fa5bc --- /dev/null +++ b/Subsurface/Items/Components/Engine.cs @@ -0,0 +1,108 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace Subsurface.Items.Components +{ + class Engine : Powered + { + + float force; + + float targetForce; + + float maxForce; + + float powerPerForce; + + [Editable, HasDefaultValue(1.0f, true)] + public float PowerPerForce + { + get { return powerPerForce; } + set + { + powerPerForce = Math.Max(0.0f, value); + } + } + + [Editable, HasDefaultValue(50000.0f, true)] + public float MaxForce + { + get { return maxForce; } + set + { + maxForce = Math.Max(0.0f, value); + } + } + + public float Force + { + get { return force;} + set { force = MathHelper.Clamp(value, -100.0f, 100.0f); } + } + + public Engine(Item item, XElement element) + : base(item, element) + { + isActive = true; + + } + + public override void Update(float deltaTime, Camera cam) + { + base.Update(deltaTime, cam); + + currPowerConsumption = Math.Abs(targetForce) * powerPerForce; + + Force = MathHelper.Lerp(force, (voltage < minVoltage) ? 0.0f : targetForce, 0.1f); + if (Force != 0.0f) + { + Submarine.Loaded.ApplyForce(new Vector2((force / 100.0f) * maxForce * (voltage / minVoltage), 0.0f)); + } + + voltage = 0.0f; + } + + public override void DrawHUD(SpriteBatch spriteBatch, Character character) + { + //isActive = true; + + int width = 300, height = 300; + int x = Game1.GraphicsWidth / 2 - width / 2; + int y = Game1.GraphicsHeight / 2 - height / 2 - 50; + + GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true); + + spriteBatch.DrawString(GUI.font, "Force: " + (int)targetForce+" %", new Vector2(x + 30, y + 30), Color.White); + + if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 30, 40, 40), "+", true)) targetForce += 1.0f; + if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 80, 40, 40), "-", true)) targetForce -= 1.0f; + + item.NewComponentEvent(this, true); + } + + public override void UpdateBroken(float deltaTime, Camera cam) + { + force = MathHelper.Lerp(force, 0.0f, 0.1f); + } + + public override void ReceiveSignal(string signal, Connection connection, Item sender) + { + base.ReceiveSignal(signal, connection, sender); + + if (connection.name == "set_force") + { + float tempForce; + if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out tempForce)) + { + Force = tempForce; + } + } + } + } +} diff --git a/Subsurface/Items/Components/Pump.cs b/Subsurface/Items/Components/Pump.cs index 3b47a67c6..302a78c80 100644 --- a/Subsurface/Items/Components/Pump.cs +++ b/Subsurface/Items/Components/Pump.cs @@ -1,14 +1,16 @@ -using System.Collections.Specialized; +using Microsoft.Xna.Framework; +using System.Collections.Specialized; +using System.Globalization; using System.Xml.Linq; namespace Subsurface.Items.Components { class Pump : Powered { - float flow; + float flowPercentage; float maxFlow; - bool flowIn; + //bool flowIn; Hull hull1, hull2; @@ -37,9 +39,9 @@ namespace Subsurface.Items.Components if (hull2 == null && hull1 == null) return; float powerFactor = (currPowerConsumption==0.0f) ? 1.0f : voltage; - flow = maxFlow * powerFactor; + //flowPercentage = maxFlow * powerFactor; - float deltaVolume = flow * ((flowIn) ? 1.0f : -1.0f); + float deltaVolume = (flowPercentage/100.0f) * maxFlow * powerFactor; hull1.Volume += deltaVolume; if (hull2 != null) hull2.Volume -= deltaVolume; @@ -139,21 +141,31 @@ namespace Subsurface.Items.Components { isActive = !isActive; } - else if (connection.name == "set_state") + else if (connection.name == "set_active") { isActive = (signal != "0"); } + else if (connection.name == "set_speed") + { + float tempSpeed; + if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out tempSpeed)) + { + flowPercentage = MathHelper.Clamp(flowPercentage, -100.0f, 100.0f); + } + } + + } public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message) { - message.Write(flowIn); + message.Write(flowPercentage); message.Write(isActive); } public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message) { - flowIn = message.ReadBoolean(); + flowPercentage = message.ReadFloat(); isActive = message.ReadBoolean(); } } diff --git a/Subsurface/Items/Components/Reactor.cs b/Subsurface/Items/Components/Reactor.cs index d47887699..433926992 100644 --- a/Subsurface/Items/Components/Reactor.cs +++ b/Subsurface/Items/Components/Reactor.cs @@ -141,16 +141,34 @@ namespace Subsurface.Items.Components } else if (autoTemp) { - float load = 0.0f; - foreach (MapEntity e in item.linkedTo) - { - Item it = e as Item; - if (it == null) continue; - PowerTransfer pt = it.GetComponent(); - if (pt != null) load += pt.PowerLoad; + float load = 0.0f; + + List connections = item.Connections; + if (connections!=null && connections.Count>0) + { + foreach (Connection connection in connections) + { + foreach (Connection recipient in connection.Recipients) + { + Item it = recipient.Item as Item; + if (it == null) continue; + + PowerTransfer pt = it.GetComponent(); + if (pt != null) load += pt.PowerLoad; + } + } } + //foreach (MapEntity e in item.linkedTo) + //{ + // Item it = e as Item; + // if (it == null) continue; + + // PowerTransfer pt = it.GetComponent(); + // if (pt != null) load += pt.PowerLoad; + //} + fissionRate = Math.Min(load / 200.0f, shutDownTemp); //float target = Math.Min(targetTemp, load); CoolingRate = coolingRate + (temperature - Math.Min(load, shutDownTemp) + deltaTemp)*0.1f; @@ -319,8 +337,6 @@ namespace Subsurface.Items.Components if (GUI.DrawButton(spriteBatch, new Rectangle(x + 450, y + 180, 40, 40), "-", true)) shutDownTemp -= 100.0f; item.NewComponentEvent(this, true); - - } static void UpdateGraph(IList graph, T newValue) diff --git a/Subsurface/Items/Components/Rope.cs b/Subsurface/Items/Components/Rope.cs index 0f541e78a..4edf38726 100644 --- a/Subsurface/Items/Components/Rope.cs +++ b/Subsurface/Items/Components/Rope.cs @@ -269,7 +269,7 @@ namespace Subsurface.Items.Components spriteBatch.Draw(sprite.Texture, ConvertUnits.ToDisplayUnits(start), null, Color.White, - ToolBox.VectorToAngle(end - start), + MathUtils.VectorToAngle(end - start), new Vector2(0.0f, sprite.size.Y / 2.0f), new Vector2((ConvertUnits.ToDisplayUnits(Vector2.Distance(start, end))) / sprite.Texture.Width, 1.0f), SpriteEffects.None, diff --git a/Subsurface/Items/Components/Signal/Connection.cs b/Subsurface/Items/Components/Signal/Connection.cs index bc07c0cae..e7b6ef802 100644 --- a/Subsurface/Items/Components/Signal/Connection.cs +++ b/Subsurface/Items/Components/Signal/Connection.cs @@ -175,9 +175,22 @@ namespace Subsurface.Items.Components bool mouseInRect = panelRect.Contains(PlayerInput.MousePosition); + Wire equippedWire = null; + //if the character using the panel has a wire item equipped + //and the wire hasn't been connected yet, draw it on the panel + for (int i = 0; i < character.SelectedItems.Length; i++) + { + Item selectedItem = character.SelectedItems[i]; + + if (selectedItem == null) continue; + + Wire wireComponent = selectedItem.GetComponent(); + if (wireComponent != null) equippedWire = wireComponent; + } + Vector2 rightPos = new Vector2(x + width - 110, y + 20); Vector2 leftPos = new Vector2(x + 110, y + 20); - + float wireInterval = 10.0f; float rightWireX = x+width / 2 + wireInterval; @@ -199,8 +212,9 @@ namespace Subsurface.Items.Components if (c.isOutput) { c.Draw(spriteBatch, panel.Item, rightPos, - new Vector2(rightPos.X + 20, rightPos.Y), - new Vector2(rightWireX, y + height), mouseInRect); + new Vector2(rightPos.X + 20, rightPos.Y), + new Vector2(rightWireX, y + height), + mouseInRect, equippedWire != null); rightPos.Y += 30; rightWireX += wireInterval; @@ -209,59 +223,41 @@ namespace Subsurface.Items.Components { c.Draw(spriteBatch, panel.Item, leftPos, new Vector2(leftPos.X - 100, leftPos.Y), - new Vector2(leftWireX, y + height), mouseInRect); + new Vector2(leftWireX, y + height), + mouseInRect, equippedWire != null); leftPos.Y += 30; leftWireX -= wireInterval; } } - - - //draw a wire for all the items that are linked to this item, but not to any of the signal connections - //foreach (MapEntity entity in panel.Item.linkedTo) - //{ - // Item linked = entity as Item; - // if (linked == null) continue; - - // //if the item is already connected, don't draw it again - // if (panel.connections.Find(c => c.linked.Contains()) != null) continue; - - // DrawWire(spriteBatch, false, linked, - // new Vector2(leftPos.X + (leftPos.Y - y), y + height- 50), - // new Vector2(leftPos.X + (leftPos.Y - y), y + height), mouseInRect); - - - - - - // leftPos.Y += 30.0f; - //} - + //if the character using the panel has a wire item equipped //and the wire hasn't been connected yet, draw it on the panel - - - for (int i = 0; i < character.SelectedItems.Length; i++ ) + if (equippedWire!=null) { - Item selectedItem = character.SelectedItems[i]; - - if (selectedItem == null) continue; - - Wire wireComponent = selectedItem.GetComponent(); - - if (wireComponent != null && - panel.connections.Find(c => c.wires.Contains(wireComponent)) == null) + if (panel.connections.Find(c => c.wires.Contains(equippedWire)) == null) { - DrawWire(spriteBatch, selectedItem, selectedItem, + DrawWire(spriteBatch, equippedWire.Item, equippedWire.Item, new Vector2(x + width / 2, y + height - 100), - new Vector2(x + width / 2, y + height), mouseInRect); + new Vector2(x + width / 2, y + height), mouseInRect, false); - if (draggingConnected == selectedItem) Inventory.draggingItem = selectedItem; + if (draggingConnected == equippedWire.Item) Inventory.draggingItem = equippedWire.Item; - break; + //break; } } + //for (int i = 0; i < character.SelectedItems.Length; i++ ) + //{ + // Item selectedItem = character.SelectedItems[i]; + + // if (selectedItem == null) continue; + + // Wire wireComponent = selectedItem.GetComponent(); + + + //} + //stop dragging a wire item if cursor is outside the panel if (mouseInRect) Inventory.draggingItem = null; @@ -275,7 +271,7 @@ namespace Subsurface.Items.Components } } - private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn) + private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, bool wireEquipped) { spriteBatch.DrawString(GUI.font, name, new Vector2(labelPos.X, labelPos.Y-10), Color.White); @@ -289,7 +285,7 @@ namespace Subsurface.Items.Components Connection recipient = wires[i].OtherConnection(this); - DrawWire(spriteBatch, wires[i].Item, (recipient == null) ? wires[i].Item : recipient.item, position, wirePosition, mouseIn); + DrawWire(spriteBatch, wires[i].Item, (recipient == null) ? wires[i].Item : recipient.item, position, wirePosition, mouseIn, wireEquipped); wirePosition.X += (isOutput) ? -20 : 20; } @@ -318,6 +314,9 @@ namespace Subsurface.Items.Components if (index>-1) { wires[index].RemoveConnection(this); + wires[index].Item.SetTransform(item.SimPosition, 0.0f); + wires[index].Item.Drop(); + wires[index].Item.body.Enabled = true; wires[index] = null; } } @@ -326,7 +325,7 @@ namespace Subsurface.Items.Components } - private static void DrawWire(SpriteBatch spriteBatch, Item wireItem, Item item, Vector2 end, Vector2 start, bool mouseIn) + private static void DrawWire(SpriteBatch spriteBatch, Item wireItem, Item item, Vector2 end, Vector2 start, bool mouseIn, bool wireEquipped) { if (draggingConnected == wireItem) { @@ -339,27 +338,29 @@ namespace Subsurface.Items.Components int textX = (int)start.X; float connLength = 10.0f; + Color color = (wireEquipped) ? Color.Gray : Color.White; + if (Math.Abs(end.X-start.X) start.X) ? -1.0f : 1.0f; wireCorner.Draw(spriteBatch, - new Vector2(start.X, end.Y), 0.0f, 1.0f, + new Vector2(start.X, end.Y), color, 0.0f, 1.0f, (end.X > start.X) ? SpriteEffects.None : SpriteEffects.FlipHorizontally); float wireStartX = start.X - wireCorner.size.X / 2 * dir; @@ -368,14 +369,14 @@ namespace Subsurface.Items.Components pos = new Vector2(Math.Min(wireStartX,wireEndX), end.Y - wireVertical.size.Y / 2); size = new Vector2(Math.Abs(wireStartX - wireEndX), wireHorizontal.size.Y); - wireHorizontal.DrawTiled(spriteBatch, pos, size, Color.White); + wireHorizontal.DrawTiled(spriteBatch, pos, size, color); rect = new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y); - if (rect.Contains(PlayerInput.MousePosition)) mouseOn = true; + if (!wireEquipped && rect.Contains(PlayerInput.MousePosition)) mouseOn = true; - connector.Draw(spriteBatch, end, -MathHelper.PiOver2*dir); + connector.Draw(spriteBatch, end, color, -MathHelper.PiOver2*dir); } - if (draggingConnected == null) + if (draggingConnected == null && !wireEquipped) { if (mouseOn || Vector2.Distance(end, PlayerInput.MousePosition)<20.0f) { @@ -387,7 +388,7 @@ namespace Subsurface.Items.Components spriteBatch.DrawString(GUI.font, item.Name, new Vector2(textX, start.Y-30), - mouseOn ? Color.Gold : Color.White, + (mouseOn && !wireEquipped) ? Color.Gold : Color.White, MathHelper.PiOver2, GUI.font.MeasureString(item.Name)*0.5f, 1.0f, SpriteEffects.None, 0.0f); @@ -431,7 +432,6 @@ namespace Subsurface.Items.Components Item wireItem = MapEntity.FindEntityByID(wireId[i]) as Item; if (wireItem == null) continue; - wires[i] = wireItem.GetComponent(); if (wires[i]!=null) diff --git a/Subsurface/Items/Components/Signal/Wire.cs b/Subsurface/Items/Components/Signal/Wire.cs index f00bc8503..8c238b175 100644 --- a/Subsurface/Items/Components/Signal/Wire.cs +++ b/Subsurface/Items/Components/Signal/Wire.cs @@ -122,15 +122,15 @@ namespace Subsurface.Items.Components item.FindHull(); Vector2 position = item.Position; - position.X = ToolBox.Round(item.Position.X, nodeDistance); + position.X = MathUtils.Round(item.Position.X, nodeDistance); if (item.currentHull == null) { - position.Y = ToolBox.Round(item.Position.Y, nodeDistance); + position.Y = MathUtils.Round(item.Position.Y, nodeDistance); } else { position.Y -= item.currentHull.Rect.Y - item.currentHull.Rect.Height; - position.Y = Math.Max(ToolBox.Round(position.Y, nodeDistance), heightFromFloor); + position.Y = Math.Max(MathUtils.Round(position.Y, nodeDistance), heightFromFloor); position.Y += item.currentHull.Rect.Y - item.currentHull.Rect.Height; } @@ -258,7 +258,7 @@ namespace Subsurface.Items.Components spriteBatch.Draw(wireSprite.Texture, start, null, color, - ToolBox.VectorToAngle(end - start), + MathUtils.VectorToAngle(end - start), new Vector2(0.0f, wireSprite.size.Y / 2.0f), new Vector2((Vector2.Distance(start, end)) / wireSprite.Texture.Width, 0.3f), SpriteEffects.None, diff --git a/Subsurface/Items/Components/Steering.cs b/Subsurface/Items/Components/Steering.cs new file mode 100644 index 000000000..43367febe --- /dev/null +++ b/Subsurface/Items/Components/Steering.cs @@ -0,0 +1,84 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace Subsurface.Items.Components +{ + class Steering : ItemComponent + { + Vector2 currVelocity; + Vector2 targetVelocity; + + public Steering(Item item, XElement element) + : base(item, element) + { + isActive = true; + } + + public override void Update(float deltaTime, Camera cam) + { + base.Update(deltaTime, cam); + + item.SendSignal(targetVelocity.X.ToString(), "velocity_x_out", item); + item.SendSignal(targetVelocity.Y.ToString(), "velocity_y_out", item); + } + + public override void DrawHUD(SpriteBatch spriteBatch, Character character) + { + //isActive = true; + + int width = 300, height = 300; + int x = Game1.GraphicsWidth / 2 - width / 2; + int y = Game1.GraphicsHeight / 2 - height / 2 - 50; + + GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true); + + Rectangle velRect = new Rectangle(x+20, y+20, 100, 100); + GUI.DrawRectangle(spriteBatch, velRect, Color.White, false); + + GUI.DrawLine(spriteBatch, + new Vector2(velRect.Center.X,velRect.Center.Y), + new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y), + Color.Gray); + + Vector2 targetVelPos = new Vector2(velRect.Center.X + targetVelocity.X, velRect.Center.Y - targetVelocity.Y); + + GUI.DrawLine(spriteBatch, + new Vector2(velRect.Center.X, velRect.Center.Y), + targetVelPos, + Color.LightGray); + + GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 5, (int)targetVelPos.Y - 5, 10, 10), Color.White); + + if (Vector2.Distance(PlayerInput.MousePosition, targetVelPos)<10.0f) + { + GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X -10, (int)targetVelPos.Y - 10, 20, 20), Color.Red); + + if (PlayerInput.LeftButtonDown()) + { + targetVelocity = PlayerInput.MousePosition - new Vector2(velRect.Center.X, velRect.Center.Y); + targetVelocity.Y = -targetVelocity.Y; + } + } + + //spriteBatch.DrawString(GUI.font, "Force: " + (int)force + " %", new Vector2(x + 30, y + 30), Color.White); + + //if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 30, 40, 40), "+", true)) targetForce += 1.0f; + //if (GUI.DrawButton(spriteBatch, new Rectangle(x + 280, y + 80, 40, 40), "-", true)) targetForce -= 1.0f; + + item.NewComponentEvent(this, true); + } + + public override void ReceiveSignal(string signal, Connection connection, Item sender) + { + if (connection.name == "velocity_in") + { + currVelocity = ToolBox.ParseToVector2(signal, false); + } + } + } +} diff --git a/Subsurface/Items/Components/Turret.cs b/Subsurface/Items/Components/Turret.cs index a5d5d3d31..079b06b9e 100644 --- a/Subsurface/Items/Components/Turret.cs +++ b/Subsurface/Items/Components/Turret.cs @@ -112,11 +112,11 @@ namespace Subsurface.Items.Components if (targetRotation < minRotation || targetRotation > maxRotation) { - float diff = ToolBox.WrapAngleTwoPi(targetRotation - (minRotation + maxRotation) / 2.0f); + float diff = MathUtils.WrapAngleTwoPi(targetRotation - (minRotation + maxRotation) / 2.0f); targetRotation = (diff > Math.PI) ? minRotation : maxRotation; } - rotation = ToolBox.CurveAngle(rotation, targetRotation, 0.05f); + rotation = MathUtils.CurveAngle(rotation, targetRotation, 0.05f); //if (!prefab.FocusOnSelected) return; @@ -131,7 +131,7 @@ namespace Subsurface.Items.Components Vector2 offset = character.CursorPosition - centerPos; offset.Y = -offset.Y; - targetRotation = ToolBox.WrapAngleTwoPi(ToolBox.VectorToAngle(offset)); + targetRotation = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(offset)); isActive = true; diff --git a/Subsurface/Map/Explosion.cs b/Subsurface/Map/Explosion.cs index 5974e38c2..55f2ad76e 100644 --- a/Subsurface/Map/Explosion.cs +++ b/Subsurface/Map/Explosion.cs @@ -48,7 +48,7 @@ namespace Subsurface for (int i = 0; i ToolBox.RandomFloatLocal(0.2f,10.0f)) + if (maxDelta > MathUtils.RandomFloatLocal(0.2f,10.0f)) { Game1.particleManager.CreateParticle("mist", ConvertUnits.ToSimUnits(new Vector2(rect.X + WaveWidth * i,surface + waveY[i])), diff --git a/Subsurface/Map/Level.cs b/Subsurface/Map/Level.cs index 9851ce1f0..fd655d3af 100644 --- a/Subsurface/Map/Level.cs +++ b/Subsurface/Map/Level.cs @@ -24,7 +24,7 @@ namespace Subsurface private int siteInterval; - const int gridCellWidth = 1000; + const int gridCellWidth = 2000; List[,] cellGrid; //List bodies; @@ -66,7 +66,7 @@ namespace Subsurface Game1.random = new Random(seed); - if (loaded != this && loaded != null) + if (loaded != null) { loaded.Unload(); } @@ -160,7 +160,7 @@ namespace Subsurface borders.Right - siteInterval * 2, borders.Y + borders.Height - siteInterval * 2); Vector2 start = pathCells[Game1.random.Next(1,pathCells.Count-2)].Center; - Vector2 end = new Vector2(ToolBox.RandomFloat(pathBorders.X, pathBorders.Right), ToolBox.RandomFloat(pathBorders.Y, pathBorders.Bottom)); + Vector2 end = new Vector2(MathUtils.RandomFloat(pathBorders.X, pathBorders.Right), MathUtils.RandomFloat(pathBorders.Y, pathBorders.Bottom)); pathCells.AddRange ( @@ -174,12 +174,16 @@ namespace Subsurface startPosition = pathCells[0].Center; endPosition = pathCells[pathCells.Count - 1].Center; + cells = CleanCells(pathCells); + foreach (VoronoiCell cell in pathCells) { cells.Remove(cell); } - GenerateLevel(cells); + //GenerateBodies(cells, pathCells); + + GeneratePolygons(cells, pathCells); Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); @@ -303,6 +307,25 @@ namespace Subsurface return tooCloseCells; } + /// + /// remove all cells except those that are adjacent to the empty cells + /// + private List CleanCells(List emptyCells) + { + List newCells = new List(); + + foreach (VoronoiCell cell in emptyCells) + { + foreach (GraphEdge edge in cell.edges) + { + VoronoiCell adjacent = edge.AdjacentCell(cell); + if (!newCells.Contains(adjacent)) newCells.Add(adjacent); + } + } + + return newCells; + } + /// /// check whether line from a to b is intersecting with line from c to b /// @@ -319,6 +342,18 @@ namespace Subsurface return (r >= 0 && r <= 1) && (s >= 0 && s <= 1); } + + //public Microsoft.Xna.Framework.Point GridCell(Vector2 position) + //{ + // Microsoft.Xna.Framework.Point point = new Microsoft.Xna.Framework.Point( + // (int)Math.Floor(position.X / gridCellWidth), + // (int)Math.Floor(position.Y / gridCellWidth)); + + // point.X = MathHelper.Clamp(point.X, 0, cellGrid.GetLength(0) - 1); + // point.Y = MathHelper.Clamp(point.X, 0, cellGrid.GetLength(1) - 1); + + // return point; + //} /// /// find the index of the cell which the point is inside @@ -354,25 +389,71 @@ namespace Subsurface return cells.IndexOf(closestCell); } - private void GenerateLevel(List cells) + private void GenerateBodies(List cells, List emptyCells) + { + foreach (VoronoiCell cell in cells) + { + List points = new List(); + foreach (GraphEdge edge in cell.edges) + { + VoronoiCell adjacentCell = edge.AdjacentCell(cell); + if (!emptyCells.Contains(adjacentCell)) continue; + + if (!points.Contains(edge.point1)) points.Add(edge.point1); + if (!points.Contains(edge.point2)) points.Add(edge.point2); + + + } + + if (points.Count == 0) continue; + + for (int i = 0 ; i cells, List emptyCells) { List verticeList = new List(); //bodies = new List(); - List tempVertices = new List(); + List bodyPoints = new List(); int n = 0; foreach (VoronoiCell cell in cells) { n = (n + 30) % 255; + bodyPoints.Clear(); tempVertices.Clear(); foreach (GraphEdge ge in cell.edges) { if (ge.point1 == ge.point2) continue; if (!tempVertices.Contains(ge.point1)) tempVertices.Add(ge.point1); if (!tempVertices.Contains(ge.point2)) tempVertices.Add(ge.point2); + + VoronoiCell adjacentCell = ge.AdjacentCell(cell); + if (!emptyCells.Contains(adjacentCell)) continue; + + if (!bodyPoints.Contains(ge.point1)) bodyPoints.Add(ge.point1); + if (!bodyPoints.Contains(ge.point2)) bodyPoints.Add(ge.point2); } if (tempVertices.Count < 3) continue; @@ -404,10 +485,28 @@ namespace Subsurface if (isSame) continue; - CreateBody(cell, triangleVertices); + //CreateBody(cell, triangleVertices); } + if (bodyPoints.Count < 2) continue; + bodyPoints.Sort(new CompareCCW(cell.Center)); + + for (int i = 0; i < bodyPoints.Count; i++) + { + bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]); + } + + Vertices bodyVertices = new Vertices(bodyPoints); + + Body edgeBody = BodyFactory.CreateChainShape( + Game1.world, bodyVertices, cell); + edgeBody.UserData = cell; + + edgeBody.BodyType = BodyType.Static; + edgeBody.CollisionCategories = Physics.CollisionWall | Physics.CollisionLevel; + + cell.body = edgeBody; } vertices = verticeList.ToArray(); @@ -415,77 +514,96 @@ namespace Subsurface //return bodies; } - private void CreateBody(VoronoiCell cell, List bodyVertices) + //private void CreateBody(VoronoiCell cell, List bodyVertices) + //{ + // for (int i = 0; i < bodyVertices.Count; i++) + // { + // bodyVertices[i] = ConvertUnits.ToSimUnits(bodyVertices[i]); + // } + // //get farseer 'vertices' from vectors + // Vertices _shapevertices = new Vertices(bodyVertices); + // //_shapevertices.Sort(new CompareCCW(cell.Center)); + + // //feed vertices array to BodyFactory.CreatePolygon to get a new farseer polygonal body + // Body _newBody = BodyFactory.CreatePolygon(Game1.world, _shapevertices, 15); + // _newBody.BodyType = BodyType.Static; + // _newBody.CollisionCategories = Physics.CollisionWall | Physics.CollisionLevel; + // _newBody.UserData = cell; + + // cell.body = _newBody; + //} + + + public Vector2 position; + + public void SetPosition(Vector2 pos) { - for (int i = 0; i < bodyVertices.Count; i++) + Vector2 amount = ConvertUnits.ToSimUnits(pos - position); + foreach (VoronoiCell cell in cells) { - bodyVertices[i] = ConvertUnits.ToSimUnits(bodyVertices[i]); + if (cell.body == null) continue; + //foreach (Body b in cell.bodies) + //{ + cell.body.SetTransform(cell.body.Position + amount, cell.body.Rotation); + //} } - //get farseer 'vertices' from vectors - Vertices _shapevertices = new Vertices(bodyVertices); - //_shapevertices.Sort(new CompareCCW(cell.Center)); - //feed vertices array to BodyFactory.CreatePolygon to get a new farseer polygonal body - Body _newBody = BodyFactory.CreatePolygon(Game1.world, _shapevertices, 15); - _newBody.BodyType = BodyType.Static; - _newBody.CollisionCategories = Physics.CollisionWall; - - cell.bodies.Add(_newBody); + position = pos; } - - Vector2 position; - public void Move(Vector2 amount, float deltaTime) + public void Move(Vector2 amount) { - amount = amount * deltaTime; position += amount; amount = ConvertUnits.ToSimUnits(amount); foreach (VoronoiCell cell in cells) { - foreach (Body b in cell.bodies) - { - b.SetTransform(b.Position+amount, b.Rotation); - } + if (cell.body == null) continue; + //foreach (Body b in cell.bodies) + //{ + // b.SetTransform(b.Position+amount, b.Rotation); + //} + cell.body.SetTransform(cell.body.Position + amount, cell.body.Rotation); } - - } - - - public void SetObserverPosition(Vector2 position) - { - position = position - this.position; - int gridPosX = (int)Math.Floor(position.X / gridCellWidth); - int gridPosY = (int)Math.Floor(position.Y / gridCellWidth); - int searchOffset = 1; - - for (int x = 0; x < cellGrid.GetLength(0); x++) + foreach (Character character in Character.characterList) { - for (int y = 0; y = startX && x <= endX && y >= startY && y <= endY); + //} } } } @@ -494,7 +612,37 @@ namespace Subsurface public void RenderLines(SpriteBatch spriteBatch) { - GUI.DrawRectangle(spriteBatch, new Rectangle(borders.X, borders.Y-borders.Height, borders.Width, borders.Height), Color.Cyan); + //GUI.DrawRectangle(spriteBatch, new Rectangle(borders.X, borders.Y-borders.Height, borders.Width, borders.Height), Color.Cyan); + + //for (int x = 0; x < cellGrid.GetLength(0); x++) + //{ + // for (int y = 0; y < cellGrid.GetLength(1); y++) + // { + // GUI.DrawRectangle(spriteBatch, + // new Rectangle(x * gridCellWidth + (int)position.X, borders.Y - borders.Height + y * gridCellWidth - (int)position.Y, gridCellWidth, gridCellWidth), + // Color.Cyan); + // } + //} + + int gridPosX = (int)Math.Floor(-observerPosition.X / gridCellWidth); + int gridPosY = (int)Math.Floor(-observerPosition.Y / gridCellWidth); + int searchOffset = 2; + + int startX = Math.Max(gridPosX - searchOffset, 0); + int endX = Math.Min(gridPosX + searchOffset, cellGrid.GetLength(0) - 1); + + int startY = Math.Max(gridPosY - searchOffset, 0); + int endY = Math.Min(gridPosY + searchOffset, cellGrid.GetLength(1) - 1); + + for (int x = startX; x < endX; x++) + { + for (int y = startY; y < endY; y++) + { + GUI.DrawRectangle(spriteBatch, + new Rectangle(x * gridCellWidth + (int)position.X, borders.Y - borders.Height + y * gridCellWidth - (int)position.Y, gridCellWidth, gridCellWidth), + Color.Cyan); + } + } foreach (VoronoiCell cell in cells) { @@ -505,8 +653,8 @@ namespace Subsurface Vector2 end = cell.edges[i].point2+position; end.Y = -end.Y; - - GUI.DrawLine(spriteBatch, start, end, Color.Red); + + GUI.DrawLine(spriteBatch, start, end, (cell.body!=null && cell.body.Enabled) ? Color.Green : Color.Red); } } } @@ -528,13 +676,15 @@ namespace Subsurface private void Unload() { - foreach (VoronoiCell cell in cells) - { - foreach (Body b in cell.bodies) - { - Game1.world.RemoveBody(b); - } - } + position = Vector2.Zero; + + //foreach (VoronoiCell cell in cells) + //{ + // //foreach (Body b in cell.bodies) + // //{ + // Game1.world.RemoveBody(cell.body); + // //} + //} //bodies = null; @@ -547,36 +697,5 @@ namespace Subsurface vertexBuffer = null; } } - - class CompareCCW : IComparer - { - private Vector2 center; - - public CompareCCW(Vector2 center) - { - this.center = center; - } - public int Compare(Vector2 a, Vector2 b) - { - if (a.X - center.X >= 0 && b.X - center.X < 0) return -1; - if (a.X - center.X < 0 && b.X - center.X >= 0) return 1; - if (a.X - center.X == 0 && b.X - center.X == 0) - { - if (a.Y - center.Y >= 0 || b.Y - center.Y >= 0) return Math.Sign(b.Y-a.Y); - return Math.Sign(a.Y-b.Y); - } - - // compute the cross product of vectors (center -> a) x (center -> b) - float det = (a.X - center.X) * (b.Y - center.Y) - (b.X - center.X) * (a.Y - center.Y); - if (det < 0) return -1; - if (det > 0) return 1; - - // points a and b are on the same line from the center - // check which point is closer to the center - float d1 = (a.X - center.X) * (a.X - center.X) + (a.Y - center.Y) * (a.Y - center.Y); - float d2 = (b.X - center.X) * (b.X - center.X) + (b.Y - center.Y) * (b.Y - center.Y); - return Math.Sign(d2-d1); - } - } - + } diff --git a/Subsurface/Map/Structure.cs b/Subsurface/Map/Structure.cs index f3ce6dc14..a8e47a75c 100644 --- a/Subsurface/Map/Structure.cs +++ b/Subsurface/Map/Structure.cs @@ -418,7 +418,12 @@ namespace Subsurface { if (sections[sectionIndex].gap == null) { - sections[sectionIndex].gap = new Gap(sections[sectionIndex].rect, !isHorizontal); + Rectangle gapRect = sections[sectionIndex].rect; + gapRect.X -= 10; + gapRect.Y += 10; + gapRect.Width += 20; + gapRect.Height += 20; + sections[sectionIndex].gap = new Gap(gapRect, !isHorizontal); } } diff --git a/Subsurface/Map/Submarine.cs b/Subsurface/Map/Submarine.cs index 5b6722236..f10201689 100644 --- a/Subsurface/Map/Submarine.cs +++ b/Subsurface/Map/Submarine.cs @@ -1,6 +1,10 @@ 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 Microsoft.Xna.Framework.Graphics; using System; @@ -9,6 +13,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Xml.Linq; +using Voronoi2; namespace Subsurface { @@ -19,30 +24,29 @@ namespace Subsurface class Submarine { - static string SaveFolder; - Md5Hash hash; - public static List SavedSubmarines = new List(); - + private static Submarine loaded; - //public static Map Loaded - //{ - // get { return loaded; } - // set { loaded = value; } - //} - - public static readonly Vector2 gridSize = new Vector2(16.0f, 16.0f); private static Vector2 lastPickedPosition; private static float lastPickedFraction; + static string SaveFolder; + Md5Hash hash; + + Vector2 speed; + private Rectangle borders; + private Body hullBody; + private string filePath; private string name; + //properties ---------------------------------------------------- + public string Name { get { return name; } @@ -94,6 +98,104 @@ namespace Subsurface get { return filePath; } } + //constructors & generation ---------------------------------------------------- + + public Submarine(string filePath, string hash = "") + { + this.filePath = filePath; + try + { + name = System.IO.Path.GetFileNameWithoutExtension(filePath); + } + catch (Exception e) + { + DebugConsole.ThrowError("Error loading map " + filePath + "!", e); + } + + if (hash != "") + { + this.hash = new Md5Hash(hash); + } + else + { + //XDocument doc = OpenDoc(filePath); + + //string md5Hash = ToolBox.GetAttributeString(doc.Root, "md5hash", ""); + //if (md5Hash == "" || md5Hash.Length < 16) + //{ + // DebugConsole.ThrowError("Couldn't find a valid MD5 hash in the map file"); + //} + + //this.mapHash = new MapHash(md5Hash); + } + + } + + private List GenerateConvexHull() + { + List points = new List(); + + 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 hullPoints = new List(); + + 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) { for (int i = 0; i < MapEntity.mapEntityList.Count(); i++ ) @@ -109,6 +211,19 @@ namespace Subsurface if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth < 0.5f) MapEntity.mapEntityList[i].Draw(spriteBatch, editing); } + + if (loaded == null) return; + + //foreach (HullBody hb in loaded.hullBodies) + //{ + // spriteBatch.Draw( + // hb.shapeTexture, + // ConvertUnits.ToDisplayUnits(new Vector2(hb.body.Position.X, -hb.body.Position.Y)), + // null, + // Color.White, + // -hb.body.Rotation, + // new Vector2(hb.shapeTexture.Width / 2, hb.shapeTexture.Height / 2), 1.0f, SpriteEffects.None, 0.0f); + //} } public static void DrawBack(SpriteBatch spriteBatch, bool editing = false) @@ -120,6 +235,8 @@ namespace Subsurface } } + //math/physics stuff ---------------------------------------------------- + public static Vector2 MouseToWorldGrid(Camera cam) { Vector2 position = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y); @@ -135,8 +252,7 @@ namespace Subsurface return position; } - - + public static Rectangle AbsRect(Vector2 pos, Vector2 size) { if (size.X < 0.0f) @@ -173,28 +289,6 @@ namespace Subsurface } } - public void Move(Vector2 amount, float deltaTime) - { - if (amount == Vector2.Zero) return; - - Level.Loaded.Move(-amount, deltaTime); - - //foreach (MapEntity e in Structure.mapEntityList) - //{ - // e.Move(amount); - //} - - //amount = ConvertUnits.ToSimUnits(amount*deltaTime); - //foreach (Character c in Character.characterList) - //{ - // if (c.animController.CurrentHull != null) continue; - // foreach (Limb l in c.animController.limbs) - // { - // l.body.SetTransform(l.body.Position - amount, l.body.Rotation); - // } - //} - } - public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List ignoredBodies = null) { float closestFraction = 1.0f; @@ -220,8 +314,7 @@ namespace Subsurface lastPickedFraction = closestFraction; return closestBody; } - - + public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd) { Body closestBody = null; @@ -286,7 +379,134 @@ namespace Subsurface return true; } + + //movement ---------------------------------------------------- + float collisionRigidness = 1.0f; + + public void Update(float deltaTime) + { + Translate(ConvertUnits.ToDisplayUnits(hullBody.Position) * collisionRigidness + speed * deltaTime); + + + CalculateBuoyancy(); + + float dragCoefficient = 0.00001f; + + float speedLength = speed.Length(); + float drag = speedLength * speedLength * dragCoefficient * mass; + System.Diagnostics.Debug.WriteLine("speed: "+speed); + if (speed!=Vector2.Zero) + { + ApplyForce(-Vector2.Normalize(speed)*drag); + } + //hullBodies[0].body.LinearVelocity = -hullBodies[0].body.Position; + + + + hullBody.SetTransform(Vector2.Zero , 0.0f); + + 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+ Game1.GameSession.Level.position), + ConvertUnits.ToSimUnits(ge.point2 + Game1.GameSession.Level.position), new List(){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); + } + + //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; + + } + + private void 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.1f; + + float buoyancy = neutralPercentage-waterPercentage; + buoyancy *= mass * 10.0f; + + ApplyForce(new Vector2(0.0f, buoyancy)); + } + + public void SetPosition(Vector2 position) + { + //hullBodies[0].body.SetTransform(position, 0.0f); + Translate(position); + //prevPosition = position; + } + + private void Translate(Vector2 amount) + { + if (amount == Vector2.Zero) return; + + Level.Loaded.Move(-amount); + } + + float mass = 10000.0f; + public void ApplyForce(Vector2 force) + { + speed += force/mass; + } + + //public void Move(Vector2 amount) + //{ + // speed = Vector2.Lerp(speed, amount, 0.05f); + //} + + 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; + float impact = Vector2.Dot(ConvertUnits.ToSimUnits(speed), normal); + + System.Diagnostics.Debug.WriteLine("IMPACT:"+impact); + if (impact < 5.0f) return true; + + + collisionRigidness = 0.8f; + + collidingCell = cell; + + return true; + } + + public void OnSeparation(Fixture f1, Fixture f2) + { + collidingCell = null; + } + + + //saving/loading ---------------------------------------------------- public void Save() { @@ -375,38 +595,6 @@ namespace Subsurface } } - public Submarine(string filePath, string hash="") - { - this.filePath = filePath; - try - { - name = Path.GetFileNameWithoutExtension(filePath); - } - catch (Exception e) - { - DebugConsole.ThrowError("Error loading map " + filePath + "!", e); - } - - - if (hash != "") - { - this.hash = new Md5Hash(hash); - } - else - { - //XDocument doc = OpenDoc(filePath); - - //string md5Hash = ToolBox.GetAttributeString(doc.Root, "md5hash", ""); - //if (md5Hash == "" || md5Hash.Length < 16) - //{ - // DebugConsole.ThrowError("Couldn't find a valid MD5 hash in the map file"); - //} - - //this.mapHash = new MapHash(md5Hash); - } - - } - private XDocument OpenDoc(string file) { XDocument doc = null; @@ -414,7 +602,7 @@ namespace Subsurface try { - extension = Path.GetExtension(file); + extension = System.IO.Path.GetExtension(file); } catch { @@ -469,6 +657,7 @@ namespace Subsurface public void Load() { + Unload(); //string file = filePath; XDocument doc = OpenDoc(filePath); @@ -507,16 +696,50 @@ namespace Subsurface } - borders = new Rectangle(0, 0, 1, 1); - foreach (Hull hull in Hull.hullList) + List convexHull = GenerateConvexHull(); + for (int i = 0; i < convexHull.Count; i++) { - if (hull.Rect.X < borders.X || borders.X == 0) borders.X = hull.Rect.X; - if (hull.Rect.Y > borders.Y || borders.Y == 0) borders.Y = hull.Rect.Y; - - if (hull.Rect.X + hull.Rect.Width > borders.X + borders.Width) borders.Width = hull.Rect.X + hull.Rect.Width - borders.X; - if (hull.Rect.Y - hull.Rect.Height < borders.Y - borders.Height) borders.Height = borders.Y - (hull.Rect.Y - hull.Rect.Height); + 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 hullBody = BodyFactory.CreateCompoundPolygon(Game1.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; + //body.IsSensor = true; + + //body.SetTransform(); + + //HullBody hullBody = new HullBody(); + //hullBody.body = body; + ////hullBody.shapeTexture = GUI.CreateRectangle(borders.Width, borders.Height); + + //hullBodies = new List(); + //hullBodies.Add(hullBody); + MapEntity.LinkAll(); foreach (Item item in Item.itemList) { @@ -554,11 +777,17 @@ namespace Subsurface Entity.RemoveAll(); PhysicsBody.list.Clear(); - + Ragdoll.list.Clear(); Game1.world.Clear(); } } + + //class HullBody + //{ + // public Body body; + // //public Texture2D shapeTexture; + //} } diff --git a/Subsurface/Map/VoronoiElements.cs b/Subsurface/Map/VoronoiElements.cs index 7b5aa49a6..e850c4053 100644 --- a/Subsurface/Map/VoronoiElements.cs +++ b/Subsurface/Map/VoronoiElements.cs @@ -121,7 +121,7 @@ namespace Voronoi2 public List edges; public Site site; - public List bodies; + public Body body; public Vector2 Center { @@ -132,7 +132,7 @@ namespace Voronoi2 { edges = new List(); - bodies = new List(); + //bodies = new List(); this.site = site; } } diff --git a/Subsurface/MathUtils.cs b/Subsurface/MathUtils.cs new file mode 100644 index 000000000..85d84ab1c --- /dev/null +++ b/Subsurface/MathUtils.cs @@ -0,0 +1,187 @@ +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Subsurface +{ + static class MathUtils + { + public static Vector2 SmoothStep(Vector2 v1, Vector2 v2, float amount) + { + return new Vector2( + MathHelper.SmoothStep(v1.X, v2.X, amount), + MathHelper.SmoothStep(v1.Y, v2.Y, amount)); + } + + public static float Round(float value, float div) + { + return (float)Math.Floor(value / div) * div; + } + + public static float RandomFloat(int minimum, int maximum) + { + return RandomFloat((float)minimum, (float)maximum); + } + + public static float RandomFloat(float minimum, float maximum) + { + return (float)Game1.random.NextDouble() * (maximum - minimum) + minimum; + } + + public static int RandomInt(int minimum, int maximum) + { + return Game1.random.Next(maximum - minimum) + minimum; + } + + public static float RandomFloatLocal(float minimum, float maximum) + { + return (float)Game1.localRandom.NextDouble() * (maximum - minimum) + minimum; + } + + public static int RandomIntLocal(int minimum, int maximum) + { + return Game1.localRandom.Next(maximum - minimum) + minimum; + } + + public static float VectorToAngle(Vector2 vector) + { + return (float)Math.Atan2(vector.Y, vector.X); + } + + public static float CurveAngle(float from, float to, float step) + { + // Ensure that 0 <= angle < 2pi for both "from" and "to" + while (from < 0) + from += MathHelper.TwoPi; + while (from >= MathHelper.TwoPi) + from -= MathHelper.TwoPi; + + while (to < 0) + to += MathHelper.TwoPi; + while (to >= MathHelper.TwoPi) + to -= MathHelper.TwoPi; + + if (Math.Abs(from - to) < MathHelper.Pi) + { + // The simple case - a straight lerp will do. + return MathHelper.Lerp(from, to, step); + } + + // If we get here we have the more complex case. + // First, increment the lesser value to be greater. + if (from < to) + from += MathHelper.TwoPi; + else + to += MathHelper.TwoPi; + + float retVal = MathHelper.Lerp(from, to, step); + + // Now ensure the return value is between 0 and 2pi + if (retVal >= MathHelper.TwoPi) + retVal -= MathHelper.TwoPi; + return retVal; + } + + public static float WrapAngleTwoPi(float angle) + { + // Ensure that 0 <= angle < 2pi for both "from" and "to" + while (angle < 0) + angle += MathHelper.TwoPi; + while (angle >= MathHelper.TwoPi) + angle -= MathHelper.TwoPi; + + return angle; + } + + public static float WrapAnglePi(float angle) + { + // Ensure that -pi <= angle < pi for both "from" and "to" + while (angle < -MathHelper.Pi) + angle += MathHelper.TwoPi; + while (angle >= MathHelper.Pi) + angle -= MathHelper.TwoPi; + + return angle; + } + + public static float GetShortestAngle(float from, float to) + { + // Ensure that 0 <= angle < 2pi for both "from" and "to" + from = WrapAngleTwoPi(from); + to = WrapAngleTwoPi(to); + + if (Math.Abs(from - to) < MathHelper.Pi) + { + return to - from; + } + + // If we get here we have the more complex case. + // First, increment the lesser value to be greater. + if (from < to) + from += MathHelper.TwoPi; + else + to += MathHelper.TwoPi; + + return to - from; + } + + /// + /// solves the angle opposite to side a (parameters: lengths of each side) + /// + public static float SolveTriangleSSS(float a, float b, float c) + { + float A = (float)Math.Acos((b * b + c * c - a * a) / (2 * b * c)); + + if (float.IsNaN(A)) A = 1.0f; + + return A; + } + + public static byte AngleToByte(float angle) + { + angle = WrapAngleTwoPi(angle); + angle = angle * (255.0f / MathHelper.TwoPi); + return Convert.ToByte(angle); + } + + public static float ByteToAngle(byte b) + { + float angle = (float)b; + angle = angle * (MathHelper.TwoPi / 255.0f); + return angle; + } + } + + class CompareCCW : IComparer + { + private Vector2 center; + + public CompareCCW(Vector2 center) + { + this.center = center; + } + public int Compare(Vector2 a, Vector2 b) + { + if (a.X - center.X >= 0 && b.X - center.X < 0) return -1; + if (a.X - center.X < 0 && b.X - center.X >= 0) return 1; + if (a.X - center.X == 0 && b.X - center.X == 0) + { + if (a.Y - center.Y >= 0 || b.Y - center.Y >= 0) return Math.Sign(b.Y - a.Y); + return Math.Sign(a.Y - b.Y); + } + + // compute the cross product of vectors (center -> a) x (center -> b) + float det = (a.X - center.X) * (b.Y - center.Y) - (b.X - center.X) * (a.Y - center.Y); + if (det < 0) return -1; + if (det > 0) return 1; + + // points a and b are on the same line from the center + // check which point is closer to the center + float d1 = (a.X - center.X) * (a.X - center.X) + (a.Y - center.Y) * (a.Y - center.Y); + float d2 = (b.X - center.X) * (b.X - center.X) + (b.Y - center.Y) * (b.Y - center.Y); + return Math.Sign(d2 - d1); + } + } +} diff --git a/Subsurface/Networking/GameClient.cs b/Subsurface/Networking/GameClient.cs index 4ec335a25..0e328bb25 100644 --- a/Subsurface/Networking/GameClient.cs +++ b/Subsurface/Networking/GameClient.cs @@ -327,7 +327,7 @@ namespace Subsurface.Networking Game1.NetLobbyScreen.Select(); - if (Game1.GameSession!=null) Game1.GameSession.EndShift(null, null); + if (Game1.GameSession!=null) Game1.GameSession.EndShift(""); DebugConsole.ThrowError(endMessage); diff --git a/Subsurface/Particles/Particle.cs b/Subsurface/Particles/Particle.cs index 17fea5eb3..2eca53f32 100644 --- a/Subsurface/Particles/Particle.cs +++ b/Subsurface/Particles/Particle.cs @@ -66,7 +66,7 @@ namespace Subsurface.Particles velocity = speed; - this.rotation = rotation + ToolBox.RandomFloatLocal(prefab.startRotationMin, prefab.startRotationMax); + this.rotation = rotation + MathUtils.RandomFloatLocal(prefab.startRotationMin, prefab.startRotationMax); prevRotation = rotation; float rand = (float)Game1.localRandom.NextDouble(); @@ -96,7 +96,7 @@ namespace Subsurface.Particles if (prefab.rotateToDirection) { - rotation = ToolBox.VectorToAngle(velocity); + rotation = MathUtils.VectorToAngle(velocity); } else { diff --git a/Subsurface/Physics/Physics.cs b/Subsurface/Physics/Physics.cs index b2d220450..472f80e5f 100644 --- a/Subsurface/Physics/Physics.cs +++ b/Subsurface/Physics/Physics.cs @@ -8,21 +8,19 @@ namespace Subsurface { private static double alpha; - public const Category CollisionNone = Category.None; - public const Category CollisionAll = Category.All; - public const Category CollisionWall = Category.Cat1; - public const Category CollisionCharacter = Category.Cat2; - public const Category CollisionPlatform = Category.Cat3; - public const Category CollisionStairs = Category.Cat4; - public const Category CollisionMisc = Category.Cat5; - public const Category CollisionProjectile = Category.Cat6; + public const Category CollisionNone = Category.None; + public const Category CollisionAll = Category.All; + public const Category CollisionWall = Category.Cat1; + public const Category CollisionCharacter = Category.Cat2; + public const Category CollisionPlatform = Category.Cat3; + public const Category CollisionStairs = Category.Cat4; + public const Category CollisionMisc = Category.Cat5; + public const Category CollisionProjectile = Category.Cat6; + public const Category CollisionLevel = Category.Cat7; public static double accumulator; public static double step = 1.0f/60.0f; - public static bool updated; - - public const float DisplayToSimRation = 100.0f; public static double Alpha diff --git a/Subsurface/Physics/PhysicsBody.cs b/Subsurface/Physics/PhysicsBody.cs index 02513d8dd..fbbb6b60e 100644 --- a/Subsurface/Physics/PhysicsBody.cs +++ b/Subsurface/Physics/PhysicsBody.cs @@ -297,7 +297,7 @@ namespace Subsurface { float nextAngle = body.Rotation + body.AngularVelocity * (float)Physics.step; - float angle = ToolBox.GetShortestAngle(nextAngle, targetRotation); + float angle = MathUtils.GetShortestAngle(nextAngle, targetRotation); float torque = body.Mass * angle * 60.0f * (force/100.0f); diff --git a/Subsurface/Screens/GameScreen.cs b/Subsurface/Screens/GameScreen.cs index 51b09b751..ccb62723a 100644 --- a/Subsurface/Screens/GameScreen.cs +++ b/Subsurface/Screens/GameScreen.cs @@ -57,7 +57,7 @@ namespace Subsurface AmbientSoundManager.Update(); - if (Game1.GameSession.Level!=null) + if (Game1.GameSession!=null && Game1.GameSession.Level != null) { Vector2 targetMovement = Vector2.Zero; if (PlayerInput.KeyDown(Keys.I)) targetMovement.Y += 1.0f; @@ -65,7 +65,7 @@ namespace Subsurface if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f; if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f; - Game1.GameSession.Submarine.Move(targetMovement*1000.0f, (float)deltaTime); + Game1.GameSession.Submarine.ApplyForce(targetMovement*100000.0f); } if (Game1.GameSession!=null) Game1.GameSession.Update((float)deltaTime); @@ -94,6 +94,8 @@ namespace Subsurface Ragdoll.UpdateAll((float)Physics.step); + if (Game1.GameSession != null && Game1.GameSession.Level != null) Game1.GameSession.Submarine.Update((float)Physics.step); + Game1.world.Step((float)Physics.step); Physics.accumulator -= Physics.step; @@ -256,6 +258,12 @@ namespace Subsurface cam.Transform); Submarine.DrawFront(spriteBatch); + + if (Game1.GameSession != null && Game1.GameSession.Level != null) + { + Game1.GameSession.Level.RenderLines(spriteBatch); + //Game1.GameSession.Level.SetObserverPosition(cam.WorldViewCenter); + } spriteBatch.End(); diff --git a/Subsurface/Subsurface.csproj b/Subsurface/Subsurface.csproj index 34f6dd413..c66b513c0 100644 --- a/Subsurface/Subsurface.csproj +++ b/Subsurface/Subsurface.csproj @@ -80,6 +80,7 @@ + @@ -88,6 +89,7 @@ + @@ -132,6 +134,7 @@ + @@ -191,10 +194,6 @@ - - False - .\FarseerPhysics MonoGame.dll - False .\Lidgren.Network.dll @@ -309,6 +308,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -701,6 +709,10 @@ + + {0aad36e3-51a5-4a07-ab60-5c8a66bd38b7} + Farseer Physics MonoGame + {1e6bf44d-6e31-40cc-8321-3d5958c983e7} Subsurface_content diff --git a/Subsurface/ToolBox.cs b/Subsurface/ToolBox.cs index e2d183aa4..b7a3e93d9 100644 --- a/Subsurface/ToolBox.cs +++ b/Subsurface/ToolBox.cs @@ -11,178 +11,6 @@ namespace Subsurface { static class ToolBox { - public static Vector2 SmoothStep(Vector2 v1, Vector2 v2, float amount) - { - return new Vector2( - MathHelper.SmoothStep(v1.X, v2.X, amount), - MathHelper.SmoothStep(v1.Y, v2.Y, amount)); - } - - public static float Round(float value, float div) - { - return (float)Math.Floor(value / div) * div; - } - - public static float RandomFloat(float minimum, float maximum) - { - return (float)Game1.random.NextDouble() * (maximum - minimum) + minimum; - } - - public static int RandomInt(int minimum, int maximum) - { - return Game1.random.Next(maximum - minimum) + minimum; - } - - public static float RandomFloatLocal(float minimum, float maximum) - { - return (float)Game1.localRandom.NextDouble() * (maximum - minimum) + minimum; - } - - public static int RandomIntLocal(int minimum, int maximum) - { - return Game1.localRandom.Next(maximum - minimum) + minimum; - } - - public static float VectorToAngle(Vector2 vector) - { - return (float)Math.Atan2(vector.Y, vector.X); - } - - public static float CurveAngle(float from, float to, float step) - { - // Ensure that 0 <= angle < 2pi for both "from" and "to" - while (from < 0) - from += MathHelper.TwoPi; - while (from >= MathHelper.TwoPi) - from -= MathHelper.TwoPi; - - while (to < 0) - to += MathHelper.TwoPi; - while (to >= MathHelper.TwoPi) - to -= MathHelper.TwoPi; - - if (Math.Abs(from - to) < MathHelper.Pi) - { - // The simple case - a straight lerp will do. - return MathHelper.Lerp(from, to, step); - } - - // If we get here we have the more complex case. - // First, increment the lesser value to be greater. - if (from < to) - from += MathHelper.TwoPi; - else - to += MathHelper.TwoPi; - - float retVal = MathHelper.Lerp(from, to, step); - - // Now ensure the return value is between 0 and 2pi - if (retVal >= MathHelper.TwoPi) - retVal -= MathHelper.TwoPi; - return retVal; - } - - public static float WrapAngleTwoPi(float angle) - { - // Ensure that 0 <= angle < 2pi for both "from" and "to" - while (angle < 0) - angle += MathHelper.TwoPi; - while (angle >= MathHelper.TwoPi) - angle -= MathHelper.TwoPi; - - return angle; - } - - public static float WrapAnglePi(float angle) - { - // Ensure that -pi <= angle < pi for both "from" and "to" - while (angle < -MathHelper.Pi) - angle += MathHelper.TwoPi; - while (angle >= MathHelper.Pi) - angle -= MathHelper.TwoPi; - - return angle; - } - - public static float GetShortestAngle(float from, float to) - { - // Ensure that 0 <= angle < 2pi for both "from" and "to" - from = WrapAngleTwoPi(from); - to = WrapAngleTwoPi(to); - - if (Math.Abs(from - to) < MathHelper.Pi) - { - return to - from; - } - - // If we get here we have the more complex case. - // First, increment the lesser value to be greater. - if (from < to) - from += MathHelper.TwoPi; - else - to += MathHelper.TwoPi; - - return to - from; - } - - /// - /// solves the angle opposite to side a (parameters: lengths of each side) - /// - public static float SolveTriangleSSS(float a, float b, float c) - { - float A = (float)Math.Acos((b*b + c*c - a*a) / (2*b*c)); - - if (float.IsNaN(A)) A = 1.0f; - - return A; - } - - - //public static void CompressStringToFile(string fileName, string value) - //{ - // // A. - // // Write string to temporary file. - // string temp = Path.GetTempFileName(); - // File.WriteAllText(temp, value); - - // // B. - // // Read file into byte array buffer. - // byte[] b; - // using (FileStream f = new FileStream(temp, FileMode.Open)) - // { - // b = new byte[f.Length]; - // f.Read(b, 0, (int)f.Length); - // } - - // // C. - // // Use GZipStream to write compressed bytes to target file. - // using (FileStream f2 = new FileStream(fileName, FileMode.Create)) - // using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false)) - // { - // gz.Write(b, 0, b.Length); - // } - //} - - //public static Stream DecompressFiletoStream(string fileName) - //{ - // if (!File.Exists(fileName)) - // { - // DebugConsole.ThrowError("File ''"+fileName+" doesn't exist!"); - // return null; - // } - - // using (FileStream originalFileStream = new FileStream(fileName, FileMode.Open)) - // { - // MemoryStream decompressedFileStream = new MemoryStream(); - - // using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)) - // { - // decompressionStream.CopyTo(decompressedFileStream); - // return decompressedFileStream; - // } - // } - //} - public static XDocument TryLoadXml(string filePath) { XDocument doc; @@ -352,7 +180,7 @@ namespace Subsurface return ParseToVector4(val); } - public static Vector2 ParseToVector2(string stringVector2) + public static Vector2 ParseToVector2(string stringVector2, bool errorMessages = true) { string[] components = stringVector2.Split(','); @@ -360,6 +188,7 @@ namespace Subsurface if (components.Length!=2) { + if (!errorMessages) return vector; DebugConsole.ThrowError("Failed to parse the string "+stringVector2+" to Vector2"); return vector; } @@ -375,8 +204,6 @@ namespace Subsurface return vector.X.ToString("G", CultureInfo.InvariantCulture) + "," + vector.Y.ToString("G", CultureInfo.InvariantCulture); } - - public static Vector4 ParseToVector4(string stringVector4) { string[] components = stringVector4.Split(','); @@ -489,22 +316,5 @@ namespace Subsurface return ""; } } - - - - public static byte AngleToByte(float angle) - { - angle = WrapAngleTwoPi(angle); - angle = angle * (255.0f / MathHelper.TwoPi); - return Convert.ToByte(angle); - } - - public static float ByteToAngle(byte b) - { - float angle = (float)b; - angle = angle * (MathHelper.TwoPi / 255.0f); - return angle; - } - } } diff --git a/Subsurface_Solution.sln b/Subsurface_Solution.sln index a9464db71..71e54b9b9 100644 --- a/Subsurface_Solution.sln +++ b/Subsurface_Solution.sln @@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Performance1.psess = Performance1.psess EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Farseer Physics MonoGame", "..\Lataukset\Selain-lataukset\Farseer Physics Engine 3.5\Farseer Physics Engine 3.5\Farseer Physics MonoGame.csproj", "{0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Android|Any CPU = Android|Any CPU @@ -162,6 +164,51 @@ Global {1E6BF44D-6E31-40CC-8321-3D5958C983E7}.Windows8|Mixed Platforms.ActiveCfg = Windows8|Any CPU {1E6BF44D-6E31-40CC-8321-3D5958C983E7}.Windows8|Mixed Platforms.Build.0 = Windows8|Any CPU {1E6BF44D-6E31-40CC-8321-3D5958C983E7}.Windows8|x86.ActiveCfg = Windows8|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Android|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Android|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Android|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Android|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Android|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|Any CPU.ActiveCfg = Debug|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|x86.ActiveCfg = Debug|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|x86.Build.0 = Debug|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.iOS|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.iOS|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.iOS|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.iOS|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.iOS|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Linux|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Linux|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Linux|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Linux|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Linux|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.OSX|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.OSX|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.OSX|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.OSX|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.OSX|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.PSM|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.PSM|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.PSM|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.PSM|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.PSM|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows|x86.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows8|Any CPU.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows8|Mixed Platforms.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows8|Mixed Platforms.Build.0 = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows8|x86.ActiveCfg = Release|x86 + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Windows8|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index ccbf38e72..fb3481370 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ