diff --git a/Subsurface/Camera.cs b/Subsurface/Camera.cs
index 30f5842d8..662fdb27b 100644
--- a/Subsurface/Camera.cs
+++ b/Subsurface/Camera.cs
@@ -162,6 +162,8 @@ namespace Subsurface
if (Keyboard.GetState().IsKeyDown(Keys.Right)) moveCam.X += moveSpeed;
if (Keyboard.GetState().IsKeyDown(Keys.Down)) moveCam.Y -= moveSpeed;
if (Keyboard.GetState().IsKeyDown(Keys.Up)) moveCam.Y += moveSpeed;
+
+ Zoom = MathHelper.Clamp(Zoom + PlayerInput.ScrollWheelSpeed / 1000.0f, 0.1f, 2.0f);
}
else
{
diff --git a/Subsurface/Characters/AI/EnemyAIController.cs b/Subsurface/Characters/AI/EnemyAIController.cs
index 8044270f4..9b3aafbf7 100644
--- a/Subsurface/Characters/AI/EnemyAIController.cs
+++ b/Subsurface/Characters/AI/EnemyAIController.cs
@@ -219,9 +219,9 @@ namespace Subsurface
//check if there's a wall between the target and the character
Vector2 rayStart = character.animController.limbs[0].SimPosition;
Vector2 rayEnd = selectedTarget.Position;
- Body closestBody = Map.CheckVisibility(rayStart, rayEnd);
+ Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd);
- if (Map.LastPickedFraction == 1.0f || closestBody == null)
+ if (Submarine.LastPickedFraction == 1.0f || closestBody == null)
{
wallAttackPos = Vector2.Zero;
return;
@@ -230,11 +230,11 @@ namespace Subsurface
Structure wall = closestBody.UserData as Structure;
if (wall == null)
{
- wallAttackPos = Map.LastPickedPosition;
+ wallAttackPos = Submarine.LastPickedPosition;
}
else
{
- int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Map.LastPickedPosition));
+ int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition));
float sectionDamage = wall.SectionDamage(sectionIndex);
for (int i = sectionIndex - 2; i <= sectionIndex + 2; i++)
@@ -377,7 +377,7 @@ namespace Subsurface
Vector2 rayStart = character.animController.limbs[0].SimPosition;
Vector2 rayEnd = target.Position;
- Body closestBody = Map.CheckVisibility(rayStart, rayEnd);
+ Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd);
Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure;
//if (targetCharacter != null)
diff --git a/Subsurface/Characters/AI/SteeringManager.cs b/Subsurface/Characters/AI/SteeringManager.cs
index 0b6337300..7a371dcc2 100644
--- a/Subsurface/Characters/AI/SteeringManager.cs
+++ b/Subsurface/Characters/AI/SteeringManager.cs
@@ -32,7 +32,7 @@ namespace Subsurface
{
this.host = host;
- wanderAngle = ToolBox.RandomFloat(0.0f, MathHelper.TwoPi);
+ wanderAngle = ToolBox.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.RandomFloat(0.0f, 1.0f) * angleChange - angleChange * 0.5f;
+ wanderAngle += ToolBox.RandomFloatLocal(0.0f, 1.0f) * angleChange - angleChange * 0.5f;
Vector2 newSteering = circleCenter + displacement;
float steeringSpeed = (newSteering + host.Steering).Length();
@@ -113,7 +113,7 @@ namespace Subsurface
if (rayCastTimer <= 0.0f)
{
rayCastTimer = RayCastInterval;
- Body closestBody = Map.CheckVisibility(host.Position, ahead);
+ Body closestBody = Submarine.CheckVisibility(host.Position, ahead);
if (closestBody == null)
{
avoidSteering = Vector2.Zero;
@@ -124,7 +124,7 @@ namespace Subsurface
Structure closestStructure = closestBody.UserData as Structure;
if (closestStructure!=null)
{
- Vector2 obstaclePosition = Map.LastPickedPosition;
+ Vector2 obstaclePosition = Submarine.LastPickedPosition;
if (closestStructure.IsHorizontal)
{
obstaclePosition.Y = closestStructure.SimPosition.Y;
@@ -134,7 +134,7 @@ namespace Subsurface
obstaclePosition.X = closestStructure.SimPosition.X;
}
- avoidSteering = Vector2.Normalize(Map.LastPickedPosition - obstaclePosition);
+ avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - obstaclePosition);
}
}
diff --git a/Subsurface/Characters/Character.cs b/Subsurface/Characters/Character.cs
index b84404b8a..a8470820f 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.RandomFloat(-0.5f, 0.5f), ToolBox.RandomFloat(-0.5f, 0.5f)),
+ torso.SimPosition + new Vector2(ToolBox.RandomFloatLocal(-0.5f, 0.5f), ToolBox.RandomFloatLocal(-0.5f, 0.5f)),
Vector2.Zero);
if (p!=null) p.Size *= 2.0f;
Game1.particleManager.CreateParticle("bubbles",
torso.SimPosition,
- new Vector2(ToolBox.RandomFloat(-0.5f, 0.5f), ToolBox.RandomFloat(-1.0f,0.5f)));
+ new Vector2(ToolBox.RandomFloatLocal(-0.5f, 0.5f), ToolBox.RandomFloatLocal(-1.0f,0.5f)));
}
foreach (var joint in animController.limbJoints)
diff --git a/Subsurface/Characters/Limb.cs b/Subsurface/Characters/Limb.cs
index 39e57402f..d62f04b3f 100644
--- a/Subsurface/Characters/Limb.cs
+++ b/Subsurface/Characters/Limb.cs
@@ -314,7 +314,7 @@ namespace Subsurface
Game1.particleManager.CreateParticle("blood",
SimPosition,
- particleVel * ToolBox.RandomFloat(1.0f, 3.0f));
+ particleVel * ToolBox.RandomFloatLocal(1.0f, 3.0f));
}
for (int i = 0; i < bloodAmount / 2; i++)
diff --git a/Subsurface/Characters/Ragdoll.cs b/Subsurface/Characters/Ragdoll.cs
index 48809eb49..932776d19 100644
--- a/Subsurface/Characters/Ragdoll.cs
+++ b/Subsurface/Characters/Ragdoll.cs
@@ -462,7 +462,7 @@ namespace Subsurface
//limb isn't in any room -> it's in the water
limb.inWater = true;
}
- else if (limbHull.Volume>0.0f && Map.RectContains(limbHull.Rect, limbPosition))
+ else if (limbHull.Volume>0.0f && Submarine.RectContains(limbHull.Rect, limbPosition))
{
if (limbPosition.Y < limbHull.Surface)
diff --git a/Subsurface/Content/Items/Diving/divinggear.xml b/Subsurface/Content/Items/Diving/divinggear.xml
index 0c5b41dc6..d3923ec3e 100644
--- a/Subsurface/Content/Items/Diving/divinggear.xml
+++ b/Subsurface/Content/Items/Diving/divinggear.xml
@@ -40,7 +40,7 @@
-
+
diff --git a/Subsurface/DebugConsole.cs b/Subsurface/DebugConsole.cs
index 660b7f103..e1b5043e5 100644
--- a/Subsurface/DebugConsole.cs
+++ b/Subsurface/DebugConsole.cs
@@ -197,6 +197,10 @@ namespace Subsurface
case "editchar":
Game1.EditCharacterScreen.Select();
break;
+ case "freecamera":
+ Character.Controlled = null;
+ Game1.GameScreen.Cam.TargetPos = Vector2.Zero;
+ break;
case "editwater":
case "water":
if (Game1.Client== null)
@@ -205,7 +209,8 @@ namespace Subsurface
}
break;
case "generatelevel":
- Game1.Level = new Level(Game1.localRandom.Next(), 20, 500, 500);
+ Game1.Level = new Level(100, 500,500, 50);
+ Game1.Level.Generate(100.0f);
break;
case "fowenabled":
case "fow":
@@ -218,12 +223,12 @@ namespace Subsurface
break;
case "savemap":
if (commands.Length < 2) break;
- Map.SaveCurrent("Content/SavedMaps/" + commands[1]);
+ Submarine.SaveCurrent("Content/SavedMaps/" + commands[1]);
NewMessage("map saved", Color.Green);
break;
case "loadmap":
if (commands.Length < 2) break;
- Map.Load("Content/SavedMaps/" + commands[1]);
+ Submarine.Load("Content/SavedMaps/" + commands[1]);
break;
case "savegame":
SaveUtil.SaveGame(SaveUtil.SaveFolder+"save");
diff --git a/Subsurface/Events/MonsterEvent.cs b/Subsurface/Events/MonsterEvent.cs
index 6702dc2f2..7544fddc2 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.RandomFloat(-0.5f,0.5f);
- position.Y += ToolBox.RandomFloat(-0.5f,0.5f);
+ position.X += ToolBox.RandomFloatLocal(-0.5f,0.5f);
+ position.Y += ToolBox.RandomFloatLocal(-0.5f,0.5f);
monsters[i] = new Character(characterFile, position);
}
}
diff --git a/Subsurface/GUI/GUI.cs b/Subsurface/GUI/GUI.cs
index f53eedb3c..9408588f0 100644
--- a/Subsurface/GUI/GUI.cs
+++ b/Subsurface/GUI/GUI.cs
@@ -7,7 +7,13 @@ using Microsoft.Xna.Framework.Input;
namespace Subsurface
{
[Flags]
- public enum Alignment { CenterX = 1, Left = 2, Right = 4, CenterY = 8, Top = 16, Bottom = 32 }
+ public enum Alignment
+ {
+ CenterX = 1, Left = 2, Right = 4, CenterY = 8, Top = 16, Bottom = 32 ,
+ TopRight = (Top | Right), TopLeft = (Top | Left), TopCenter = (CenterX | Top),
+ Center = (CenterX | CenterY),
+ BottomRight = (Bottom | Right), BottomLeft = (Bottom | Left), BottomCenter = (CenterX | Bottom)
+ }
class GUIMessage
@@ -258,15 +264,15 @@ namespace Subsurface
public static void Draw(float deltaTime, SpriteBatch spriteBatch, Camera cam)
{
- //spriteBatch.DrawString(font,
- // "FPS: " + (int)Game1.frameCounter.AverageFramesPerSecond
- // + " - render: "+Game1.renderTimeElapsed,
- // new Vector2(10, 10), Color.White);
+ spriteBatch.DrawString(font,
+ "FPS: " + (int)Game1.frameCounter.AverageFramesPerSecond
+ + " - render: " + Game1.renderTimeElapsed,
+ new Vector2(10, 10), Color.White);
- //spriteBatch.DrawString(font,
- // "Physics: " + Game1.world.UpdateTime
- // + " - bodies: " + Game1.world.BodyList.Count,
- // new Vector2(10, 30), Color.White);
+ spriteBatch.DrawString(font,
+ "Physics: " + Game1.world.UpdateTime
+ + " - bodies: " + Game1.world.BodyList.Count,
+ new Vector2(10, 30), Color.White);
if (Character.Controlled != null && cam!=null) Character.Controlled.DrawHud(spriteBatch, cam);
diff --git a/Subsurface/Game1.cs b/Subsurface/Game1.cs
index 0dc69062c..847a4062d 100644
--- a/Subsurface/Game1.cs
+++ b/Subsurface/Game1.cs
@@ -15,10 +15,12 @@ namespace Subsurface
///
class Game1 : Game
{
- GraphicsDeviceManager graphics;
+ public static GraphicsDeviceManager graphics;
static int graphicsWidth, graphicsHeight;
static SpriteBatch spriteBatch;
+ public static GraphicsDevice CurrGraphicsDevice;
+
public static FrameCounter frameCounter;
public static readonly Version version = Assembly.GetEntryAssembly().GetName().Version;
@@ -46,7 +48,7 @@ namespace Subsurface
public static Random localRandom;
public static Random random;
- private Stopwatch renderTimer;
+ //private Stopwatch renderTimer;
public static int renderTimeElapsed;
@@ -55,6 +57,7 @@ namespace Subsurface
get { return GameScreen.Cam; }
}
+
public static int GraphicsWidth
{
get { return graphicsWidth; }
@@ -68,7 +71,7 @@ namespace Subsurface
public Game1()
{
graphics = new GraphicsDeviceManager(this);
-
+
graphicsWidth = 1280;
graphicsHeight = 720;
@@ -76,13 +79,13 @@ namespace Subsurface
graphics.PreferredBackBufferWidth = graphicsWidth;
graphics.PreferredBackBufferHeight = graphicsHeight;
Content.RootDirectory = "Content";
-
+
//graphics.SynchronizeWithVerticalRetrace = false;
//graphics.ApplyChanges();
frameCounter = new FrameCounter();
- renderTimer = new Stopwatch();
+ //renderTimer = new Stopwatch();
IsMouseVisible = true;
@@ -107,6 +110,8 @@ namespace Subsurface
{
base.Initialize();
+ CurrGraphicsDevice = GraphicsDevice;
+
particleManager = new ParticleManager("Content/Particles/prefabs.xml", Cam);
GameMode.Init();
@@ -145,7 +150,7 @@ namespace Subsurface
AmbientSoundManager.Init("Content/Sounds/Sounds.xml");
- Map.PreloadMaps("Content/SavedMaps");
+ Submarine.Preload("Content/SavedMaps");
GameScreen = new GameScreen(graphics.GraphicsDevice);
MainMenuScreen = new MainMenuScreen(this);
LobbyScreen = new LobbyScreen();
@@ -209,7 +214,7 @@ namespace Subsurface
///
protected override void Draw(GameTime gameTime)
{
- renderTimer.Restart();
+ //renderTimer.Restart();
double deltaTime = gameTime.ElapsedGameTime.TotalSeconds;
@@ -217,8 +222,8 @@ namespace Subsurface
Screen.Selected.Draw(deltaTime, GraphicsDevice, spriteBatch);
- renderTimeElapsed = (int)renderTimer.Elapsed.Ticks;
- renderTimer.Stop();
+ //renderTimeElapsed = (int)renderTimer.Elapsed.Ticks;
+ //renderTimer.Stop();
}
protected override void OnExiting(object sender, EventArgs args)
diff --git a/Subsurface/GameSession/GameSession.cs b/Subsurface/GameSession/GameSession.cs
index 6762a6f45..e2dab348a 100644
--- a/Subsurface/GameSession/GameSession.cs
+++ b/Subsurface/GameSession/GameSession.cs
@@ -27,15 +27,29 @@ namespace Subsurface
private string savePath;
- private Map selectedMap;
+ private Submarine submarine;
- public GameSession(Map selectedMap, GameModePreset gameModePreset)
- :this(selectedMap, gameModePreset.Instantiate())
+ private Level level;
+
+ public Map map;
+
+ public Level Level
+ {
+ get { return level; }
+ }
+
+ public Submarine Submarine
+ {
+ get { return submarine; }
+ }
+
+ public GameSession(Submarine submarine, GameModePreset gameModePreset)
+ :this(submarine, gameModePreset.Instantiate())
{
}
- public GameSession(Map selectedMap, GameMode gameMode = null)
+ public GameSession(Submarine selectedMap, GameMode gameMode = null)
{
taskManager = new TaskManager(this);
@@ -43,6 +57,8 @@ namespace Subsurface
guiRoot = new GUIFrame(new Rectangle(0,0,Game1.GraphicsWidth,Game1.GraphicsWidth), Color.Transparent);
+ map = new Map(Game1.random.Next(), 500);
+
int width = 350, height = 100;
if (Game1.Client!=null || Game1.Server!=null)
{
@@ -67,7 +83,7 @@ namespace Subsurface
//startTime = DateTime.Now;
//endTime = startTime + gameDuration;
- this.selectedMap = selectedMap;
+ this.submarine = selectedMap;
//if (!save) return;
@@ -75,7 +91,7 @@ namespace Subsurface
}
- public GameSession(Map selectedMap, string savePath, string filePath)
+ public GameSession(Submarine selectedMap, string savePath, string filePath)
: this(selectedMap)
{
XDocument doc = ToolBox.TryLoadXml(filePath);
@@ -95,14 +111,31 @@ namespace Subsurface
this.savePath = savePath;
}
+ public void StartShift(TimeSpan duration, Level level)
+ {
+
+ if (Submarine.Loaded != submarine) submarine.Load();
+
+ level.Generate(submarine==null ? 100.0f : Math.Max(Submarine.Borders.Width, Submarine.Borders.Height));
+
+ this.level = level;
+
+ StartShift(duration, 1);
+ }
+
public void StartShift(TimeSpan duration, int scriptedEventCount = 1)
{
//if (crewManager.characterInfos.Count == 0) return;
- if (Map.Loaded!=selectedMap) selectedMap.Load();
+ if (Submarine.Loaded!=submarine) submarine.Load();
if (gameMode!=null) gameMode.Start(duration);
+ if (level!=null)
+ {
+ submarine.Move(level.StartPosition - submarine.Center, 1.0f);
+ }
+
//crewManager.StartShift();
taskManager.StartShift(scriptedEventCount);
}
@@ -122,7 +155,7 @@ namespace Subsurface
SaveUtil.SaveGame(savePath);
}
-
+
taskManager.EndShift();
//gameMode.End();
diff --git a/Subsurface/Items/Components/Door.cs b/Subsurface/Items/Components/Door.cs
index aa6bd1cbd..459cba8cd 100644
--- a/Subsurface/Items/Components/Door.cs
+++ b/Subsurface/Items/Components/Door.cs
@@ -215,7 +215,7 @@ namespace Subsurface.Items.Components
{
base.Move(amount);
- LinkedGap.Move(amount);
+ //LinkedGap.Move(amount);
body.SetTransform(body.Position + ConvertUnits.ToSimUnits(amount), 0.0f);
diff --git a/Subsurface/Items/Components/MiniMap.cs b/Subsurface/Items/Components/MiniMap.cs
index aa41886c1..1f501484d 100644
--- a/Subsurface/Items/Components/MiniMap.cs
+++ b/Subsurface/Items/Components/MiniMap.cs
@@ -41,12 +41,12 @@ namespace Subsurface.Items.Components
Rectangle miniMap = new Rectangle(x + 20, y + 40, width - 40, height - 60);
- float size = Math.Min((float)miniMap.Width / (float)Map.Borders.Width, (float)miniMap.Height / (float)Map.Borders.Height);
+ float size = Math.Min((float)miniMap.Width / (float)Submarine.Borders.Width, (float)miniMap.Height / (float)Submarine.Borders.Height);
foreach (Hull hull in Hull.hullList)
{
Rectangle hullRect = new Rectangle(
- miniMap.X + (int)((hull.Rect.X - Map.Borders.X) * size),
- miniMap.Y - (int)((hull.Rect.Y - Map.Borders.Y) * size),
+ miniMap.X + (int)((hull.Rect.X - Submarine.Borders.X) * size),
+ miniMap.Y - (int)((hull.Rect.Y - Submarine.Borders.Y) * size),
(int)(hull.Rect.Width * size),
(int)(hull.Rect.Height * size));
@@ -71,8 +71,8 @@ namespace Subsurface.Items.Components
if (c.animController.CurrentHull!=null) continue;
Rectangle characterRect = new Rectangle(
- miniMap.X + (int)((c.Position.X - Map.Borders.X) * size),
- miniMap.Y - (int)((c.Position.Y - Map.Borders.Y) * size),
+ miniMap.X + (int)((c.Position.X - Submarine.Borders.X) * size),
+ miniMap.Y - (int)((c.Position.Y - Submarine.Borders.Y) * size),
5, 5);
GUI.DrawRectangle(spriteBatch, characterRect, Color.White, true);
diff --git a/Subsurface/Items/Components/RepairTool.cs b/Subsurface/Items/Components/RepairTool.cs
index 9571498ba..f781bbf33 100644
--- a/Subsurface/Items/Components/RepairTool.cs
+++ b/Subsurface/Items/Components/RepairTool.cs
@@ -109,8 +109,8 @@ namespace Subsurface.Items.Components
ignoredBodies.Add(limb.body.FarseerBody);
}
- Body targetBody = Map.PickBody(TransformedBarrelPos, targetPosition, ignoredBodies);
- pickedPosition = Map.LastPickedPosition;
+ Body targetBody = Submarine.PickBody(TransformedBarrelPos, targetPosition, ignoredBodies);
+ pickedPosition = Submarine.LastPickedPosition;
if (targetBody==null || targetBody.UserData==null) return true;
diff --git a/Subsurface/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Items/Components/Signal/ConnectionPanel.cs
index 884c82285..a331234a5 100644
--- a/Subsurface/Items/Components/Signal/ConnectionPanel.cs
+++ b/Subsurface/Items/Components/Signal/ConnectionPanel.cs
@@ -6,8 +6,7 @@ using System.Xml.Linq;
namespace Subsurface.Items.Components
{
class ConnectionPanel : ItemComponent
- {
-
+ {
public List connections;
Character user;
@@ -31,10 +30,20 @@ namespace Subsurface.Items.Components
}
}
- public override void Move(Vector2 amount)
- {
- base.Move(amount);
- }
+ //public override void Move(Vector2 amount)
+ //{
+ // base.Move(amount);
+
+ // foreach (Connection c in connections)
+ // {
+ // foreach (Wire w in c.wires)
+ // {
+ // if (w == null) continue;
+
+ // w.Move
+ // }
+ // }
+ //}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
diff --git a/Subsurface/Items/Components/Signal/Wire.cs b/Subsurface/Items/Components/Signal/Wire.cs
index b2ce301cf..f00bc8503 100644
--- a/Subsurface/Items/Components/Signal/Wire.cs
+++ b/Subsurface/Items/Components/Signal/Wire.cs
@@ -35,6 +35,15 @@ namespace Subsurface.Items.Components
connections = new Connection[2];
}
+ public override void Move(Vector2 amount)
+ {
+ amount = FarseerPhysics.ConvertUnits.ToDisplayUnits(amount);
+ for (int i = 0; i h.Rect.X && rect.X + rect.Width < h.Rect.X+h.Rect.Width &&
@@ -250,20 +250,20 @@ namespace Subsurface
pos.Y = ConvertUnits.ToSimUnits(MathHelper.Clamp(lowerSurface, rect.Y-rect.Height, rect.Y));
Game1.particleManager.CreateParticle("watersplash",
- new Vector2(pos.X, pos.Y - ToolBox.RandomFloat(0.0f, 0.1f)),
- new Vector2(flowForce.X * ToolBox.RandomFloat(0.005f, 0.007f), flowForce.Y * ToolBox.RandomFloat(0.005f, 0.007f)));
+ new Vector2(pos.X, pos.Y - ToolBox.RandomFloatLocal(0.0f, 0.1f)),
+ new Vector2(flowForce.X * ToolBox.RandomFloatLocal(0.005f, 0.007f), flowForce.Y * ToolBox.RandomFloatLocal(0.005f, 0.007f)));
- pos.Y = ConvertUnits.ToSimUnits(ToolBox.RandomFloat(lowerSurface, rect.Y - rect.Height));
+ pos.Y = ConvertUnits.ToSimUnits(ToolBox.RandomFloatLocal(lowerSurface, rect.Y - rect.Height));
Game1.particleManager.CreateParticle("bubbles", pos, flowForce / 200.0f);
}
else
{
pos.Y += Math.Sign(flowForce.Y) * ConvertUnits.ToSimUnits(rect.Height / 2.0f);
- for (int i = 0; i < rect.Width; i += (int)ToolBox.RandomFloat(80, 100))
+ for (int i = 0; i < rect.Width; i += (int)ToolBox.RandomFloatLocal(80, 100))
{
- pos.X = ConvertUnits.ToSimUnits(ToolBox.RandomFloat(rect.X, rect.X+rect.Width));
+ pos.X = ConvertUnits.ToSimUnits(ToolBox.RandomFloatLocal(rect.X, rect.X+rect.Width));
Subsurface.Particles.Particle splash = Game1.particleManager.CreateParticle("watersplash", pos,
- new Vector2(flowForce.X * ToolBox.RandomFloat(0.005f, 0.008f), flowForce.Y * ToolBox.RandomFloat(0.005f, 0.008f)));
+ new Vector2(flowForce.X * ToolBox.RandomFloatLocal(0.005f, 0.008f), flowForce.Y * ToolBox.RandomFloatLocal(0.005f, 0.008f)));
if (splash!=null) splash.Size = splash.Size * MathHelper.Clamp(rect.Width / 50.0f, 0.8f, 4.0f);
diff --git a/Subsurface/Map/Hull.cs b/Subsurface/Map/Hull.cs
index 5cc7c7af6..c35bb3cf0 100644
--- a/Subsurface/Map/Hull.cs
+++ b/Subsurface/Map/Hull.cs
@@ -150,8 +150,8 @@ namespace Subsurface
public override bool Contains(Vector2 position)
{
- return (Map.RectContains(rect, position) &&
- !Map.RectContains(new Rectangle(rect.X + 8, rect.Y - 8, rect.Width - 16, rect.Height - 16), position));
+ return (Submarine.RectContains(rect, position) &&
+ !Submarine.RectContains(new Rectangle(rect.X + 8, rect.Y - 8, rect.Width - 16, rect.Height - 16), position));
}
public int GetWaveIndex(Vector2 position)
@@ -189,7 +189,7 @@ namespace Subsurface
if (EditWater)
{
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
- if (Map.RectContains(rect, position))
+ if (Submarine.RectContains(rect, position))
{
if (PlayerInput.LeftButtonDown())
{
@@ -210,7 +210,7 @@ namespace Subsurface
for (int i = 0; i < waveY.Length; i++)
{
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
- if (maxDelta > ToolBox.RandomFloat(0.2f,10.0f))
+ if (maxDelta > ToolBox.RandomFloatLocal(0.2f,10.0f))
{
Game1.particleManager.CreateParticle("mist",
ConvertUnits.ToSimUnits(new Vector2(rect.X + WaveWidth * i,surface + waveY[i])),
@@ -390,12 +390,12 @@ namespace Subsurface
{
if (guess != null && hullList.Contains(guess))
{
- if (Map.RectContains(guess.rect, position)) return guess;
+ if (Submarine.RectContains(guess.rect, position)) return guess;
}
foreach (Hull w in hullList)
{
- if (Map.RectContains(w.rect, position)) return w;
+ if (Submarine.RectContains(w.rect, position)) return w;
}
return null;
diff --git a/Subsurface/Map/Level.cs b/Subsurface/Map/Level.cs
index 0c6715bfe..9851ce1f0 100644
--- a/Subsurface/Map/Level.cs
+++ b/Subsurface/Map/Level.cs
@@ -6,109 +6,548 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
+using System.Diagnostics;
using Voronoi2;
namespace Subsurface
{
class Level
{
+ public static Level Loaded
+ {
+ get { return loaded; }
+ }
+
+ static Level loaded;
+
private int seed;
- List bodies;
+ private int siteInterval;
+
+ const int gridCellWidth = 1000;
+ List[,] cellGrid;
+
+ //List bodies;
List cells;
- public Level(int seed, int siteCount, int width, int height)
+ BasicEffect basicEffect;
+
+ private VertexPositionColor[] vertices;
+ private VertexBuffer vertexBuffer;
+
+ private Vector2 startPosition;
+ private Vector2 endPosition;
+
+ Rectangle borders;
+
+ public Vector2 StartPosition
+ {
+ get { return startPosition; }
+ }
+
+ public Level(int seed, int width, int height, int siteInterval)
{
this.seed = seed;
- Voronoi voronoi = new Voronoi(1.0);
+ this.siteInterval = siteInterval;
- List sites = new List();
- Random rand = new Random(seed);
+ borders = new Rectangle(0, 0, width, height);
+ }
- for (int i = 0; i < siteCount; i++)
+ public static Level CreateRandom()
+ {
+ return new Level(100, 100000, 40000, 2000);
+ }
+
+ public void Generate(float minWidth)
+ {
+ Stopwatch sw = new Stopwatch();
+ sw.Start();
+
+ Game1.random = new Random(seed);
+
+ if (loaded != this && loaded != null)
{
- sites.Add(new PointF((float)(rand.NextDouble() * width), (float)(rand.NextDouble() * width)));
+ loaded.Unload();
}
- List graphEdges = MakeVoronoiGraph(sites, voronoi, width, height);
+ loaded = this;
+ Voronoi voronoi = new Voronoi(1.0);
+
+ List sites = new List();
+ Random rand = new Random(seed);
+
+ float siteVariance = siteInterval * 0.8f;
+ for (int x = siteInterval/2; x < borders.Width; x += siteInterval)
+ {
+ for (int y = siteInterval / 2; y < borders.Height; y += siteInterval)
+ {
+ sites.Add(new Vector2(
+ x + (float)(Game1.random.NextDouble() - 0.5) * siteVariance,
+ y + (float)(Game1.random.NextDouble() - 0.5) * siteVariance));
+ }
+ }
+
+ Stopwatch sw2 = new Stopwatch();
+ sw2.Start();
+
+ List graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height);
+
+
+ Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ cellGrid = new List[borders.Width / gridCellWidth, borders.Height / gridCellWidth];
+ for (int x = 0; x < borders.Width / gridCellWidth; x++)
+ {
+ for (int y = 0; y < borders.Height / gridCellWidth; y++)
+ {
+ cellGrid[x, y] = new List();
+ }
+ }
+
+ //construct voronoi cells based on the graph edges
cells = new List();
foreach (GraphEdge ge in graphEdges)
{
- for (int i = 0; i<2; i++)
+ for (int i = 0; i < 2; i++)
{
- Site site = (i==0) ? ge.site1 : ge.site2;
- VoronoiCell cell = cells.Find(c => c.site == site);
+ Site site = (i == 0) ? ge.site1 : ge.site2;
+
+ VoronoiCell cell = cellGrid[
+ (int)Math.Floor(site.coord.x / gridCellWidth),
+ (int)Math.Floor(site.coord.y / gridCellWidth)].Find(c => c.site == site);
+
if (cell == null)
{
cell = new VoronoiCell(site);
+ cellGrid[(int)Math.Floor(cell.Center.X / gridCellWidth), (int)Math.Floor(cell.Center.Y / gridCellWidth)].Add(cell);
cells.Add(cell);
}
- if (!cell.edges.Contains(ge)) cell.edges.Add(ge);
+
+ if (ge.cell1 == null)
+ {
+ ge.cell1 = cell;
+ }
+ else
+ {
+ ge.cell2 = cell;
+ }
+ cell.edges.Add(ge);
+ }
+ }
+
+ Debug.WriteLine("find cells: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ //generate a path from the left edge of the map to right edge
+ Rectangle pathBorders = new Rectangle(
+ borders.X + (int)minWidth, borders.Y + (int)minWidth,
+ borders.Right - (int)minWidth, borders.Y + borders.Height - (int)minWidth);
+
+ List pathCells = GeneratePath(
+ new Vector2((int)minWidth, Game1.random.Next((int)minWidth, borders.Height - (int)minWidth)),
+ new Vector2(borders.Width - (int)minWidth, Game1.random.Next((int)minWidth, borders.Height - (int)minWidth)),
+ cells, pathBorders, minWidth);
+
+
+ //generate a couple of random paths
+ for (int i = 0; i < Game1.random.Next() % 3; i++ )
+ {
+ pathBorders = new Rectangle(
+ borders.X + siteInterval * 2, borders.Y - siteInterval * 2,
+ 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));
+
+ pathCells.AddRange
+ (
+ GeneratePath( start,end, cells, pathBorders, 0.0f)
+ );
+ }
+
+ Debug.WriteLine("path: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ startPosition = pathCells[0].Center;
+ endPosition = pathCells[pathCells.Count - 1].Center;
+
+ foreach (VoronoiCell cell in pathCells)
+ {
+ cells.Remove(cell);
+ }
+
+ GenerateLevel(cells);
+
+ Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ vertexBuffer = new VertexBuffer(Game1.CurrGraphicsDevice, VertexPositionColor.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
+
+ vertexBuffer.SetData(vertices);
+
+ basicEffect = new BasicEffect(Game1.CurrGraphicsDevice);
+ basicEffect.VertexColorEnabled = true;
+
+ Debug.WriteLine("Generated a map with "+sites.Count+" sites in "+sw.ElapsedMilliseconds+" ms");
+ }
+
+ private List GeneratePath(Vector2 start, Vector2 end, List cells, Microsoft.Xna.Framework.Rectangle limits, float minWidth, float wanderAmount = 0.3f)
+ {
+
+ Stopwatch sw2 = new Stopwatch();
+ sw2.Start();
+
+ //how heavily the path "steers" towards the endpoint
+ //lower values will cause the path to "wander" more, higher will make it head straight to the end
+ wanderAmount = MathHelper.Clamp(wanderAmount, 0.0f, 1.0f);
+
+ List pathCells = new List();
+
+ VoronoiCell currentCell = cells[FindCellIndex(start)];
+ pathCells.Add(currentCell);
+
+ VoronoiCell endCell = cells[FindCellIndex(end)];
+
+ do
+ {
+ int edgeIndex = 0;
+
+ //steer towards target
+ if (Game1.random.NextDouble()>wanderAmount)
+ {
+ for (int i = 0; i < currentCell.edges.Count; i++)
+ {
+ if (!IsIntersecting(currentCell.Center, end, currentCell.edges[i].point1, currentCell.edges[i].point2)) continue;
+ edgeIndex = i;
+ break;
+ }
+ }
+ //choose random edge (ignoring ones where the adjacent cell is outside limits)
+ else
+ {
+ List allowedEdges = new List();
+
+ foreach(GraphEdge edge in currentCell.edges)
+ {
+ if (!limits.Contains(edge.AdjacentCell(currentCell).Center)) continue;
+
+ allowedEdges.Add(edge);
+ }
+ edgeIndex = (allowedEdges.Count==0) ?
+ 0 : currentCell.edges.IndexOf(allowedEdges[Game1.random.Next() % allowedEdges.Count]);
+ }
+
+ currentCell = currentCell.edges[edgeIndex].AdjacentCell(currentCell);
+
+
+ pathCells.Add(currentCell);
+
+ } while (currentCell!=endCell);
+
+ Debug.WriteLine("genpath: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ List removedCells = GetTooCloseCells(pathCells, minWidth);
+ foreach (VoronoiCell removedCell in removedCells)
+ {
+ if (pathCells.Contains(removedCell)) continue;
+ pathCells.Add(removedCell);
+ }
+
+ Debug.WriteLine("gettooclose: " + sw2.ElapsedMilliseconds + " ms");
+ sw2.Restart();
+
+ return pathCells;
+ }
+
+ private List GetTooCloseCells(List emptyCells, float minDistance)
+ {
+ List tooCloseCells = new List();
+
+ Vector2 position = emptyCells[0].Center;
+
+ if (minDistance == 0.0f) return tooCloseCells;
+
+ float step = 100.0f;
+
+ int targetCellIndex = 1;
+
+ minDistance *= 0.5f;
+ do
+ {
+ for (int x = -1; x<=1; x++)
+ {
+ for (int y = -1; y <= 1; y++)
+ {
+ if (x == 0 && y == 0) continue;
+ Vector2 cornerPos = position + new Vector2(x*minDistance, y*minDistance);
+
+ int cellIndex = FindCellIndex(cornerPos);
+ if (cellIndex == -1) continue;
+ if (!tooCloseCells.Contains(cells[cellIndex]))
+ {
+ tooCloseCells.Add(cells[cellIndex]);
+ }
+ }
+ }
+
+ position += Vector2.Normalize(emptyCells[targetCellIndex].Center - position) * step;
+
+ if (Vector2.Distance(emptyCells[targetCellIndex].Center, position) < step * 2.0f) targetCellIndex++;
+
+ } while (Vector2.Distance(position, emptyCells[emptyCells.Count - 1].Center) > step*2.0f);
+
+ return tooCloseCells;
+ }
+
+ ///
+ /// check whether line from a to b is intersecting with line from c to b
+ ///
+ bool IsIntersecting(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
+ {
+ float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));
+ float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));
+ float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));
+
+ if (denominator == 0) return numerator1 == 0 && numerator2 == 0;
+
+ float r = numerator1 / denominator;
+ float s = numerator2 / denominator;
+
+ return (r >= 0 && r <= 1) && (s >= 0 && s <= 1);
+ }
+
+ ///
+ /// find the index of the cell which the point is inside
+ /// (actually finds the cell whose center is closest, but it's always the correct cell assuming the point is inside the borders of the diagram)
+ ///
+ private int FindCellIndex(Vector2 position)
+ {
+ float closestDist = 0.0f;
+ VoronoiCell closestCell = null;
+
+ int gridPosX = (int)Math.Floor(position.X / gridCellWidth);
+ int gridPosY = (int)Math.Floor(position.Y / gridCellWidth);
+
+ int searchOffset = 1;
+
+ for (int x = Math.Max(gridPosX-searchOffset,0); x<=Math.Min(gridPosX+searchOffset, cellGrid.GetLength(0)-1); x++)
+ {
+ for (int y = Math.Max(gridPosY-searchOffset,0); y<=Math.Min(gridPosY+searchOffset, cellGrid.GetLength(1)-1); y++)
+ {
+ for (int i = 0; i < cellGrid[x,y].Count; i++)
+ {
+ float dist = Vector2.Distance(cellGrid[x, y][i].Center, position);
+ if (closestDist != 0.0f && dist > closestDist) continue;
+
+ closestDist = dist;
+ closestCell = cellGrid[x, y][i];
+ }
}
}
- bodies = new List();
+
+ return cells.IndexOf(closestCell);
+ }
+
+ private void GenerateLevel(List cells)
+ {
+ List verticeList = new List();
+ //bodies = new List();
+
+
+ List tempVertices = new List();
+
+ int n = 0;
foreach (VoronoiCell cell in cells)
{
- //List of vectors defining my custom poly
- List vlist = new List();
+ n = (n + 30) % 255;
+
+ tempVertices.Clear();
foreach (GraphEdge ge in cell.edges)
{
- if (!vlist.Contains(ge.point1)) vlist.Add(ge.point1);
- if (!vlist.Contains(ge.point2)) vlist.Add(ge.point2);
+ if (ge.point1 == ge.point2) continue;
+ if (!tempVertices.Contains(ge.point1)) tempVertices.Add(ge.point1);
+ if (!tempVertices.Contains(ge.point2)) tempVertices.Add(ge.point2);
}
- if (vlist.Count < 3) continue;
+ if (tempVertices.Count < 3) continue;
+
+ int triangleCount = tempVertices.Count - 2;
- for (int i = 0; i < vlist.Count; i++ )
+ tempVertices.Sort(new CompareCCW(cell.Center));
+
+ int lastIndex = 1;
+ for (int i = 0; i < triangleCount; i++ )
{
- vlist[i] = ConvertUnits.ToSimUnits(vlist[i]);
+ List triangleVertices = new List();
+
+ triangleVertices.Add(tempVertices[0]);
+ for (int j = lastIndex; j<=lastIndex+1; j++)
+ {
+ triangleVertices.Add(tempVertices[j]);
+ }
+ lastIndex += 1;
+
+ foreach (Vector2 vertex in triangleVertices)
+ {
+ verticeList.Add(new VertexPositionColor(new Vector3(vertex, 0.0f), Color.LightGray*0.8f));//new Color(n,(n*2)%255,(n*3)%255)*0.5f));
+ }
+
+ bool isSame = false;
+ if (triangleVertices[0].Y == triangleVertices[1].Y && triangleVertices[1].Y == triangleVertices[2].Y) isSame = true;
+ if (triangleVertices[0].X == triangleVertices[1].X && triangleVertices[1].X == triangleVertices[2].X) isSame = true;
+
+ if (isSame) continue;
+
+ CreateBody(cell, triangleVertices);
}
- //get farseer 'vertices' from vectors
- Vertices _shapevertices = new Vertices(vlist);
- _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;
-
- bodies.Add(_newBody);
}
+
+ vertices = verticeList.ToArray();
+
+ //return bodies;
}
- List MakeVoronoiGraph(List sites, Voronoi voronoi, int width, int height)
+ private void CreateBody(VoronoiCell cell, List bodyVertices)
{
- double[] xVal = new double[sites.Count];
- double[] yVal = new double[sites.Count];
- for (int i = 0; i < sites.Count; i++)
+ for (int i = 0; i < bodyVertices.Count; i++)
{
- xVal[i] = sites[i].X;
- yVal[i] = sites[i].Y;
+ bodyVertices[i] = ConvertUnits.ToSimUnits(bodyVertices[i]);
}
- return voronoi.generateVoronoi(xVal, yVal, 0, width, 0, height);
+ //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);
}
- public void Render(SpriteBatch spriteBatch)
+
+ Vector2 position;
+ public void Move(Vector2 amount, float deltaTime)
{
+ 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);
+ }
+ }
+
+ }
+
+
+
+ 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++)
+ {
+ for (int y = 0; y (PrimitiveType.TriangleList, vertices, 0, (int)Math.Floor(vertices.Length / 3.0f));
+ }
+
+ private void Unload()
+ {
+ foreach (VoronoiCell cell in cells)
+ {
+ foreach (Body b in cell.bodies)
+ {
+ Game1.world.RemoveBody(b);
+ }
+ }
+
+
+ //bodies = null;
+
+ vertices = null;
+
+ cells = null;
+
+ vertexBuffer.Dispose();
+ vertexBuffer = null;
+ }
+ }
+
class CompareCCW : IComparer
{
private Vector2 center;
@@ -119,24 +558,24 @@ namespace Subsurface
}
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) 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(a.Y - b.Y);
- return Math.Sign(b.Y - a.Y);
+ 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;
+ 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(d1 - d2);
+ return Math.Sign(d2-d1);
}
}
diff --git a/Subsurface/Map/Location.cs b/Subsurface/Map/Location.cs
new file mode 100644
index 000000000..f71f91d16
--- /dev/null
+++ b/Subsurface/Map/Location.cs
@@ -0,0 +1,37 @@
+using Microsoft.Xna.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Subsurface
+{
+ class Location
+ {
+ string name;
+
+ Vector2 mapPosition;
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public Vector2 MapPosition
+ {
+ get { return mapPosition; }
+ }
+
+ public Location(string name, Vector2 mapPosition)
+ {
+ this.name = name;
+
+ this.mapPosition = mapPosition;
+ }
+
+ public static Location CreateRandom(Vector2 position)
+ {
+ return new Location("Location " + (Game1.random.Next() % 10000), position);
+ }
+ }
+}
diff --git a/Subsurface/Map/Map.cs b/Subsurface/Map/Map.cs
index 0ac4f41f1..91216ace7 100644
--- a/Subsurface/Map/Map.cs
+++ b/Subsurface/Map/Map.cs
@@ -1,539 +1,239 @@
-using FarseerPhysics;
-using FarseerPhysics.Collision;
-using FarseerPhysics.Dynamics;
-using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
-using System.Reflection;
-using System.Xml.Linq;
+using System.Text;
+using Voronoi2;
namespace Subsurface
{
- public enum Direction : byte
- {
- None = 0, Left = 1, Right = 2
- }
-
class Map
{
- static string MapFolder;
- MapHash mapHash;
+ private List levels;
- public static List