Functional level generation + moving the submarine

This commit is contained in:
Regalis
2015-06-26 23:05:51 +03:00
parent bda9b31cbe
commit 9237a9efe2
48 changed files with 1629 additions and 750 deletions

View File

@@ -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
{

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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++)

View File

@@ -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)

View File

@@ -40,7 +40,7 @@
<sprite texture="DivingSuit.png" limb="RightArm" sourcerect="0,0,18,40" origin="0.5,0.4" depth="0.005"/>
<sprite texture="DivingSuit.png" limb="LeftArm" sourcerect="0,0,18,40" origin="0.5,0.4" depth="0.005"/>
<StatusEffect type="OnWearing" target="Contained,Character" targetnames="Oxygen Tank" Condition="-0.7" Oxygen="20.0"/>
<StatusEffect type="OnWearing" target="Contained,Character" targetnames="Oxygen Tank,human" Condition="-0.7" Oxygen="20.0"/>
<StatusEffect type="OnWearing" target="Character" PressureProtection="100.0"/>
</Wearable>

View File

@@ -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");

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -15,10 +15,12 @@ namespace Subsurface
/// </summary>
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
/// </summary>
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)

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -6,8 +6,7 @@ using System.Xml.Linq;
namespace Subsurface.Items.Components
{
class ConnectionPanel : ItemComponent
{
{
public List<Connection> 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)
{

View File

@@ -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<nodes.Count; i++)
{
nodes[i] += amount;
}
}
public Connection OtherConnection(Connection connection)
{
if (connection == null) return null;

View File

@@ -287,8 +287,9 @@ namespace Subsurface
if (itemList != null && body!=null)
{
Vector2 pos = new Vector2(rect.X + rect.Width / 2.0f, rect.Y - rect.Height / 2.0f);
body.SetTransform(ConvertUnits.ToSimUnits(pos), 0.0f);
amount = ConvertUnits.ToSimUnits(amount);
//Vector2 pos = new Vector2(rect.X + rect.Width / 2.0f, rect.Y - rect.Height / 2.0f);
body.SetTransform(body.Position+amount, body.Rotation);
}
foreach (ItemComponent ic in components)
{
@@ -679,7 +680,7 @@ namespace Subsurface
{
Rectangle transformedTrigger = item.TransformTrigger(trigger);
if (!Map.RectContains(transformedTrigger, displayPos))continue;
if (!Submarine.RectContains(transformedTrigger, displayPos))continue;
Vector2 triggerCenter =

View File

@@ -60,7 +60,7 @@ namespace Subsurface
public override void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
Vector2 position = Map.MouseToWorldGrid(cam);
Vector2 position = Submarine.MouseToWorldGrid(cam);
if (!resizeHorizontal && !resizeVertical)
{

View File

@@ -48,7 +48,7 @@ namespace Subsurface
for (int i = 0; i<range*10; i++)
{
Game1.particleManager.CreateParticle("explosionfire", position,
Vector2.Normalize(new Vector2(ToolBox.RandomFloat(-1.0f, 1.0f), ToolBox.RandomFloat(-1.0f, 1.0f))) * ToolBox.RandomFloat(3.0f, 4.0f),
Vector2.Normalize(new Vector2(ToolBox.RandomFloatLocal(-1.0f, 1.0f), ToolBox.RandomFloatLocal(-1.0f, 1.0f))) * ToolBox.RandomFloatLocal(3.0f, 4.0f),
0.0f);
}

View File

@@ -90,8 +90,8 @@ namespace Subsurface
public override bool Contains(Vector2 position)
{
return (Map.RectContains(rect, position) &&
!Map.RectContains(new Rectangle(rect.X + 4, rect.Y - 4, rect.Width - 8, rect.Height - 8), position));
return (Submarine.RectContains(rect, position) &&
!Submarine.RectContains(new Rectangle(rect.X + 4, rect.Y - 4, rect.Width - 8, rect.Height - 8), position));
}
private void FindHulls()
@@ -102,7 +102,7 @@ namespace Subsurface
foreach (Hull h in Hull.hullList)
{
if (!Map.RectsOverlap(h.Rect, rect, false)) continue;
if (!Submarine.RectsOverlap(h.Rect, rect, false)) continue;
//if the gap is inside the hull completely, ignore it
if (rect.X > 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);

View File

@@ -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;

View File

@@ -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<Body> bodies;
private int siteInterval;
const int gridCellWidth = 1000;
List<VoronoiCell>[,] cellGrid;
//List<Body> bodies;
List<VoronoiCell> 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<PointF> sites = new List<PointF>();
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<GraphEdge> graphEdges = MakeVoronoiGraph(sites, voronoi, width, height);
loaded = this;
Voronoi voronoi = new Voronoi(1.0);
List<Vector2> sites = new List<Vector2>();
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<GraphEdge> graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height);
Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms");
sw2.Restart();
cellGrid = new List<VoronoiCell>[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<VoronoiCell>();
}
}
//construct voronoi cells based on the graph edges
cells = new List<VoronoiCell>();
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<VoronoiCell> 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<VoronoiCell> GeneratePath(Vector2 start, Vector2 end, List<VoronoiCell> 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<VoronoiCell> pathCells = new List<VoronoiCell>();
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<GraphEdge> allowedEdges = new List<GraphEdge>();
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<VoronoiCell> 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<VoronoiCell> GetTooCloseCells(List<VoronoiCell> emptyCells, float minDistance)
{
List<VoronoiCell> tooCloseCells = new List<VoronoiCell>();
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;
}
/// <summary>
/// check whether line from a to b is intersecting with line from c to b
/// </summary>
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);
}
/// <summary>
/// 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)
/// </summary>
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<Body>();
return cells.IndexOf(closestCell);
}
private void GenerateLevel(List<VoronoiCell> cells)
{
List<VertexPositionColor> verticeList = new List<VertexPositionColor>();
//bodies = new List<Body>();
List<Vector2> tempVertices = new List<Vector2>();
int n = 0;
foreach (VoronoiCell cell in cells)
{
//List of vectors defining my custom poly
List<Vector2> vlist = new List<Vector2>();
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<Vector2> triangleVertices = new List<Vector2>();
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<GraphEdge> MakeVoronoiGraph(List<PointF> sites, Voronoi voronoi, int width, int height)
private void CreateBody(VoronoiCell cell, List<Vector2> 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 <cellGrid.GetLength(1); y++)
{
for (int i = 0; i < cellGrid[x, y].Count; i++)
{
foreach (Body b in cellGrid[x, y][i].bodies)
{
b.Enabled = false;
}
}
}
}
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++)
{
foreach (Body b in cellGrid[x, y][i].bodies)
{
b.Enabled = true;
}
}
}
}
}
public void RenderLines(SpriteBatch spriteBatch)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(borders.X, borders.Y-borders.Height, borders.Width, borders.Height), Color.Cyan);
foreach (VoronoiCell cell in cells)
{
for (int i = 0; i<cell.edges.Count; i++)
{
GUI.DrawLine(spriteBatch, cell.edges[i].point1, cell.edges[i].point2, Microsoft.Xna.Framework.Color.Red);
Vector2 start = cell.edges[i].point1+position;
start.Y = -start.Y;
Vector2 end = cell.edges[i].point2+position;
end.Y = -end.Y;
GUI.DrawLine(spriteBatch, start, end, Color.Red);
}
}
}
}
public void Render(GraphicsDevice graphicsDevice, Camera cam)
{
if (vertices == null) return;
if (vertices.Length <= 0) return;
basicEffect.World = Matrix.CreateTranslation(new Vector3(position, 0.0f))*cam.ShaderTransform
* Matrix.CreateOrthographic(Game1.GraphicsWidth, Game1.GraphicsHeight, -1, 1) * 0.5f;
basicEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.DrawUserPrimitives<VertexPositionColor>(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<Vector2>
{
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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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<Level> levels;
public static List<Map> SavedMaps = new List<Map>();
private List<Location> locations;
private static Map 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;
private Rectangle borders;
private string filePath;
private string name;
public string Name
{
get { return name; }
}
public static Vector2 LastPickedPosition
{
get { return lastPickedPosition; }
}
public static float LastPickedFraction
{
get { return lastPickedFraction; }
}
public MapHash MapHash
{
get
{
if (mapHash != null) return mapHash;
XDocument doc = OpenDoc(filePath);
mapHash = new MapHash(doc);
return mapHash;
}
}
public static Map Loaded
{
get { return loaded; }
}
public static Rectangle Borders
{
get
{
return (loaded==null) ? Rectangle.Empty : loaded.borders;
}
}
public string FilePath
{
get { return filePath; }
}
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++ )
{
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawFront(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth < 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawBack(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth >= 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static Vector2 MouseToWorldGrid(Camera cam)
{
Vector2 position = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
position = cam.ScreenToWorld(position);
return VectorToWorldGrid(position);
}
public static Vector2 VectorToWorldGrid(Vector2 position)
{
position.X = (float)Math.Floor(Convert.ToDouble(position.X / gridSize.X)) * gridSize.X;
position.Y = (float)Math.Ceiling(Convert.ToDouble(position.Y / gridSize.Y)) * gridSize.Y;
return position;
}
public static Rectangle AbsRect(Vector2 pos, Vector2 size)
{
if (size.X < 0.0f)
{
pos.X += size.X;
size.X = -size.X;
}
if (size.Y < 0.0f)
{
pos.Y -= size.Y;
size.Y = -size.Y;
}
return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
}
public static bool RectContains(Rectangle rect, Vector2 pos)
{
return (pos.X > rect.X && pos.X < rect.X + rect.Width
&& pos.Y < rect.Y && pos.Y > rect.Y - rect.Height);
}
public static bool RectsOverlap(Rectangle rect1, Rectangle rect2, bool inclusive=true)
{
if (inclusive)
{
return !(rect1.X > rect2.X + rect2.Width || rect1.X + rect1.Width < rect2.X ||
rect1.Y < rect2.Y - rect2.Height || rect1.Y - rect1.Height > rect2.Y);
}
else
{
return !(rect1.X >= rect2.X + rect2.Width || rect1.X + rect1.Width <= rect2.X ||
rect1.Y <= rect2.Y - rect2.Height || rect1.Y - rect1.Height >= rect2.Y);
}
}
private List<LocationConnection> connections;
public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List<Body> ignoredBodies = null)
private int seed;
private int size;
private Location currentLocation;
private Location selectedLocation;
public Map(int seed, int size)
{
float closestFraction = 1.0f;
Body closestBody = null;
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories == Category.None) return -1;
if (ignoredBodies != null && ignoredBodies.Contains(fixture.Body)) return -1;
this.seed = seed;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null && (structure.IsPlatform || !structure.HasBody)) return -1;
this.size = size;
if (fraction < closestFraction)
{
closestFraction = fraction;
if (fixture.Body!=null) closestBody = fixture.Body;
}
return fraction;
}
, rayStart, rayEnd);
levels = new List<Level>();
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestBody;
}
locations = new List<Location>();
connections = new List<LocationConnection>();
public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd)
{
Body closestBody = null;
float closestFraction = 1.0f;
GenerateLocations();
if (Vector2.Distance(rayStart,rayEnd)<0.01f)
{
closestFraction = 0.01f;
return null;
}
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories != Physics.CollisionWall) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null)
{
if (structure.IsPlatform || structure.StairDirection != Direction.None) return -1;
int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(point));
if (sectionIndex > -1 && structure.SectionHasHole(sectionIndex)) return -1;
}
if (fraction < closestFraction)
{
closestBody = fixture.Body;
closestFraction = fraction;
}
return closestFraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestBody;
}
public static Body PickBody(Vector2 point)
{
Body foundBody = null;
AABB aabb = new AABB(point, point);
Game1.world.QueryAABB(p =>
{
foundBody = p.Body;
return true;
}, ref aabb);
return foundBody;
}
public static bool InsideWall(Vector2 point)
{
Body foundBody = PickBody(point);
if (foundBody==null) return false;
Structure wall = foundBody.UserData as Structure;
if (wall == null || wall.IsPlatform) return false;
return true;
}
public void Save()
{
SaveAs(filePath);
}
public void SaveAs(string filePath)
{
//if (filePath=="")
//for (int i = 0; i<10; i++)
//{
// DebugConsole.ThrowError("No save file selected");
// return;
// Vector2 pos = new Vector2((float)Game1.random.NextDouble() * size, (float)Game1.random.NextDouble() * size);
// Location location =
// locations.Add(location);
//}
XDocument doc = new XDocument(new XElement((XName)name));
foreach (MapEntity e in MapEntity.mapEntityList)
{
e.Save(doc);
}
//for (int i = 0; i < 10; i++)
//{
mapHash = new MapHash(doc);
doc.Root.Add(new XAttribute("md5hash", mapHash.MD5Hash));
// int closestIndex = 0;
// float closestDistance = 0.0f;
// for (int j = 0; j<10; j++)
// {
// if (j == i) continue;
try
{
SaveUtil.CompressStringToFile(filePath, doc.ToString());
}
catch (Exception e)
{
DebugConsole.ThrowError("Saving map ''" + filePath + "'' failed!", e);
}
// //ignore if already connected
// bool alreadyConnected = false;
// foreach (LocationConnection connection in connections)
// {
// if (connection.Locations.Contains(locations[i]) && connection.Locations.Contains(locations[j]))
// {
// alreadyConnected = true;
// break;
// }
// }
// if (alreadyConnected) continue;
//doc.Save(filePath);
// float dist = Vector2.Distance(locations[i].MapPosition, locations[j].MapPosition);
// if (closestDistance > 0.0f && dist > closestDistance) continue;
// closestDistance = dist;
// closestIndex = j;
// }
// connections.Add(new LocationConnection(locations[i], locations[closestIndex], level));
//}
currentLocation = locations[0];
}
public static void SaveCurrent(string savePath)
private void GenerateLocations()
{
if (loaded==null)
Voronoi voronoi = new Voronoi(0.5f);
List<Vector2> sites = new List<Vector2>();
for (int i = 0; i < 50; i++)
{
loaded = new Map(savePath);
return;
sites.Add(new Vector2((float)Game1.random.NextDouble() * size, (float)Game1.random.NextDouble() * size));
}
loaded.SaveAs(savePath);
}
public static void PreloadMaps(string mapFolder)
{
MapFolder = mapFolder;
//string[] mapFilePaths;
Unload();
SavedMaps.Clear();
if (!Directory.Exists(MapFolder))
{
try
{
Directory.CreateDirectory(MapFolder);
}
catch
{
DebugConsole.ThrowError("Directory ''Content/SavedMaps'' not found and creating the directory failed.");
return;
}
}
string[] mapFilePaths;
try
{
mapFilePaths = Directory.GetFiles(MapFolder);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't open directory ''Content/SavedMaps''!", e);
return;
}
foreach (string mapPath in mapFilePaths)
{
//Map savedMap = new Map(mapPath);
SavedMaps.Add(new Map(mapPath));
}
}
public Map(string filePath, string mapHash="")
{
this.filePath = filePath;
try
{
name = Path.GetFileNameWithoutExtension(filePath);
}
catch (Exception e)
{
DebugConsole.ThrowError("Error loading map " + filePath + "!", e);
}
if (mapHash != "")
{
this.mapHash = new MapHash(mapHash);
}
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;
string extension = "";
try
{
extension = Path.GetExtension(file);
}
catch
{
DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)");
return null;
}
if (extension == ".gz")
{
Stream stream = SaveUtil.DecompressFiletoStream(file);
if (stream == null)
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return null;
}
try
{
stream.Position = 0;
doc = XDocument.Load(stream); //ToolBox.TryLoadXml(file);
stream.Close();
stream.Dispose();
}
catch
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return null;
}
}
else if (extension == ".xml")
{
try
{
doc = XDocument.Load(file);
}
catch
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return null;
}
}
else
{
DebugConsole.ThrowError("Couldn't load map ''" + file + "! (Unrecognized file extension)");
return null;
}
return doc;
}
public void Load()
{
//string file = filePath;
XDocument doc = OpenDoc(filePath);
if (doc == null) return;
foreach (XElement element in doc.Root.Elements())
{
string typeName = element.Name.ToString();
Type t;
try
{
// Get the type of a specified class.
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.");
continue;
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.", e);
continue;
}
try
{
MethodInfo loadMethod = t.GetMethod("Load");
loadMethod.Invoke(t, new object[] { element });
}
catch (Exception e)
{
DebugConsole.ThrowError("Could not find the method ''Load'' in " + t + ".", e);
}
}
borders = new Rectangle(0, 0, 1, 1);
foreach (Hull hull in Hull.hullList)
{
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);
}
MapEntity.LinkAll();
foreach (Item item in Item.itemList)
{
foreach (ItemComponent ic in item.components)
{
ic.OnMapLoaded();
}
}
loaded = this;
}
public static Map Load(string file)
{
Unload();
Map map = new Map(file);
map.Load();
return map;
List<GraphEdge> edges = voronoi.MakeVoronoiGraph(sites, size, size);
sites.Clear();
foreach (GraphEdge edge in edges)
{
if (edge.point1 == edge.point2) continue;
Location[] newLocations = new Location[2];
newLocations[0] = locations.Find(l => l.MapPosition == edge.point1 || l.MapPosition == edge.point2);
newLocations[1] = locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.point1 || l.MapPosition == edge.point2));
for (int i = 0; i < 2; i++)
{
if (newLocations[i] != null) continue;
Vector2[] points = new Vector2[] { edge.point1, edge.point2 };
int positionIndex = Game1.random.Next(0, 1);
Vector2 position = points[positionIndex];
if (newLocations[1 - i] != null && newLocations[1 - i].MapPosition == position) position = points[1 - positionIndex];
newLocations[i] = Location.CreateRandom(position);
locations.Add(newLocations[i]);
}
connections.Add(new LocationConnection(newLocations[0], newLocations[1], Level.CreateRandom()));
}
float minDistance = 50.0f;
for (int i = connections.Count - 1; i >= 0; i--)
{
LocationConnection connection = connections[i];
if (Vector2.Distance(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minDistance) continue;
locations.Remove(connection.Locations[0]);
connections.Remove(connection);
foreach (LocationConnection connection2 in connections)
{
if (connection2.Locations[0] == connection.Locations[0]) connection2.Locations[0] = connection.Locations[1];
if (connection2.Locations[1] == connection.Locations[0]) connection2.Locations[1] = connection.Locations[1];
}
}
}
public static void Unload()
public void Draw(SpriteBatch spriteBatch, Rectangle rect)
{
if (loaded == null) return;
loaded.Clear();
loaded = null;
}
GUI.DrawRectangle(spriteBatch, rect, Color.DarkBlue, true);
private void Clear()
Vector2 scale = new Vector2((float)rect.Width/ size, (float)rect.Height/size);
float maxDist = 20.0f;
float closestDist = 0.0f;
Location highlightedLocation = null;
foreach (Location location in locations)
{
Vector2 pos = location.MapPosition * scale;
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X, rect.Y + (int)pos.Y, 5, 5), Color.White, true);
if (currentLocation == location)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X - 4, rect.Y + (int)pos.Y - 4, 5+8, 5+8), Color.Red, false);
}
float dist = Vector2.Distance(PlayerInput.MousePosition, new Vector2(rect.X + pos.X, rect.Y + pos.Y));
if (dist < maxDist && (highlightedLocation == null || dist < closestDist))
{
closestDist = dist;
highlightedLocation = location;
}
}
if (highlightedLocation!=null)
{
Vector2 pos = highlightedLocation.MapPosition * scale;
spriteBatch.DrawString(GUI.font, highlightedLocation.Name, pos + new Vector2(rect.X - 50, rect.Y), Color.White);
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X - 4, rect.Y + (int)pos.Y - 4, 5 + 8, 5 + 8), Color.White, false);
}
if (selectedLocation != null)
{
Vector2 pos = selectedLocation.MapPosition * scale;
spriteBatch.DrawString(GUI.font, selectedLocation.Name, pos + new Vector2(rect.X - 50, rect.Y), Color.White);
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X - 4, rect.Y + (int)pos.Y - 4, 5 + 8, 5 + 8), Color.White, false);
}
Vector2 rectCorner = new Vector2(rect.X, rect.Y);
foreach (LocationConnection connection in connections)
{
GUI.DrawLine(spriteBatch,
connection.Locations[0].MapPosition * scale + rectCorner,
connection.Locations[1].MapPosition * scale + rectCorner, Color.LightGray);
if (highlightedLocation!=currentLocation &&
connection.Locations.Contains(highlightedLocation) && connection.Locations.Contains(currentLocation))
{
GUI.DrawLine(spriteBatch,
connection.Locations[0].MapPosition * scale + rectCorner +Vector2.One,
connection.Locations[1].MapPosition * scale + rectCorner + Vector2.One, Color.White);
if (PlayerInput.LeftButtonClicked())
if(selectedLocation!=highlightedLocation && highlightedLocation!=null)
{
//currentLocation = highlightedLocation;
Game1.LobbyScreen.SelectLocation(highlightedLocation, connection);
selectedLocation = highlightedLocation;
}
}
if (selectedLocation != currentLocation &&
(connection.Locations.Contains(selectedLocation) && connection.Locations.Contains(currentLocation)))
{
GUI.DrawLine(spriteBatch,
connection.Locations[0].MapPosition * scale + rectCorner + Vector2.One,
connection.Locations[1].MapPosition * scale + rectCorner + Vector2.One, Color.White);
}
}
}
}
class LocationConnection
{
Location[] locations;
Level level;
public Location[] Locations
{
if (Game1.GameScreen.Cam != null) Game1.GameScreen.Cam.TargetPos = Vector2.Zero;
Entity.RemoveAll();
PhysicsBody.list.Clear();
Ragdoll.list.Clear();
Game1.world.Clear();
get { return locations; }
}
public Level Level
{
get { return level; }
}
public LocationConnection(Location location1, Location location2, Level level)
{
locations = new Location[] { location1, location2 };
this.level = level;
}
}
}

View File

@@ -117,7 +117,7 @@ namespace Subsurface
public virtual bool Contains(Vector2 position)
{
return (Map.RectContains(rect, position));
return (Submarine.RectContains(rect, position));
}
public virtual void Draw(SpriteBatch spriteBatch, bool editing) {}
@@ -216,7 +216,7 @@ namespace Subsurface
//mouse released -> move the entities to the new position of the mouse
Vector2 moveAmount = position - startMovingPos;
moveAmount = Map.VectorToWorldGrid(moveAmount);
moveAmount = Submarine.VectorToWorldGrid(moveAmount);
if (moveAmount != Vector2.Zero)
{
@@ -235,7 +235,7 @@ namespace Subsurface
selectionSize.Y = selectionPos.Y - position.Y;
List<MapEntity> newSelection = new List<MapEntity>();// FindSelectedEntities(selectionPos, selectionSize);
if (Math.Abs(selectionSize.X) > Map.gridSize.X || Math.Abs(selectionSize.Y) > Map.gridSize.Y)
if (Math.Abs(selectionSize.X) > Submarine.gridSize.X || Math.Abs(selectionSize.Y) > Submarine.gridSize.Y)
{
newSelection = FindSelectedEntities(selectionPos, selectionSize);
}
@@ -315,7 +315,7 @@ namespace Subsurface
if (startMovingPos != Vector2.Zero)
{
Vector2 moveAmount = position - startMovingPos;
moveAmount = Map.VectorToWorldGrid(moveAmount);
moveAmount = Submarine.VectorToWorldGrid(moveAmount);
moveAmount.Y = -moveAmount.Y;
//started moving the selected entities
if (moveAmount != Vector2.Zero)
@@ -358,7 +358,7 @@ namespace Subsurface
List<MapEntity> foundEntities = new List<MapEntity>();
foreach (MapEntity e in mapEntityList)
{
if (Map.RectContains(e.rect, pos)) foundEntities.Add(e);
if (Submarine.RectContains(e.rect, pos)) foundEntities.Add(e);
}
return foundEntities;
}
@@ -367,7 +367,7 @@ namespace Subsurface
{
foreach (MapEntity e in mapEntityList)
{
if (Map.RectContains(e.rect, pos)) return e;
if (Submarine.RectContains(e.rect, pos)) return e;
}
return null;
}
@@ -379,11 +379,11 @@ namespace Subsurface
{
List<MapEntity> foundEntities = new List<MapEntity>();
Rectangle selectionRect = Map.AbsRect(pos, size);
Rectangle selectionRect = Submarine.AbsRect(pos, size);
foreach (MapEntity e in mapEntityList)
{
if (Map.RectsOverlap(selectionRect, e.rect))
if (Submarine.RectsOverlap(selectionRect, e.rect))
foundEntities.Add(e);
}

View File

@@ -73,23 +73,23 @@ namespace Subsurface
public virtual void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
Vector2 placeSize = Map.gridSize;
Vector2 placeSize = Submarine.gridSize;
if (placePosition == Vector2.Zero)
{
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed)
placePosition = Map.MouseToWorldGrid(cam);
placePosition = Submarine.MouseToWorldGrid(cam);
}
else
{
Vector2 position = Map.MouseToWorldGrid(cam);
Vector2 position = Submarine.MouseToWorldGrid(cam);
if (resizeHorizontal) placeSize.X = position.X - placePosition.X;
if (resizeVertical) placeSize.Y = placePosition.Y - position.Y;
Rectangle newRect = Map.AbsRect(placePosition, placeSize);
newRect.Width = (int)Math.Max(newRect.Width, Map.gridSize.X);
newRect.Height = (int)Math.Max(newRect.Height, Map.gridSize.Y);
Rectangle newRect = Submarine.AbsRect(placePosition, placeSize);
newRect.Width = (int)Math.Max(newRect.Width, Submarine.gridSize.X);
newRect.Height = (int)Math.Max(newRect.Height, Submarine.gridSize.Y);
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Released)
{

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace Subsurface
{
class MapHash
class Md5Hash
{
private string md5Hash;
private string shortHash;
@@ -29,14 +26,14 @@ namespace Subsurface
}
}
public MapHash(string md5Hash)
public Md5Hash(string md5Hash)
{
this.md5Hash = md5Hash;
shortHash = GetShortHash(md5Hash);
}
public MapHash(XDocument doc)
public Md5Hash(XDocument doc)
{
string docString = Regex.Replace(doc.ToString(), @"\s+", "");
// step 1, calculate MD5 hash from input

View File

@@ -111,7 +111,7 @@ namespace Subsurface
Vector2 simAmount = ConvertUnits.ToSimUnits(amount);
foreach (Body b in bodies)
{
b.SetTransform(b.Position + simAmount, 0.0f);
b.SetTransform(b.Position + simAmount, b.Rotation);
}
}
@@ -203,15 +203,15 @@ namespace Subsurface
bodies = new List<Body>();
Body newBody = BodyFactory.CreateRectangle(Game1.world,
ConvertUnits.ToSimUnits(rect.Width * Math.Sqrt(2.0) - Map.gridSize.X),
ConvertUnits.ToSimUnits(rect.Width * Math.Sqrt(2.0) - Submarine.gridSize.X),
ConvertUnits.ToSimUnits(10),
1.5f);
newBody.BodyType = BodyType.Static;
Vector2 stairPos = new Vector2(Position.X, rect.Y - rect.Height + rect.Width / 2.0f);
stairPos += new Vector2(
(StairDirection == Direction.Right) ? -Map.gridSize.X*1.5f : Map.gridSize.X*1.5f,
- Map.gridSize.Y*2.0f);
(StairDirection == Direction.Right) ? -Submarine.gridSize.X*1.5f : Submarine.gridSize.X*1.5f,
- Submarine.gridSize.Y*2.0f);
newBody.Position = ConvertUnits.ToSimUnits(stairPos);

View File

@@ -109,7 +109,7 @@ namespace Subsurface
public override void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
Vector2 position = Map.MouseToWorldGrid(cam);
Vector2 position = Submarine.MouseToWorldGrid(cam);
//Vector2 placeSize = size;
Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
@@ -118,7 +118,7 @@ namespace Subsurface
if (placePosition == Vector2.Zero)
{
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed)
placePosition = Map.MouseToWorldGrid(cam);
placePosition = Submarine.MouseToWorldGrid(cam);
newRect.X = (int)position.X;
newRect.Y = (int)position.Y;
@@ -131,7 +131,7 @@ namespace Subsurface
if (resizeHorizontal) placeSize.X = position.X - placePosition.X;
if (resizeVertical) placeSize.Y = placePosition.Y - position.Y;
newRect = Map.AbsRect(placePosition, placeSize);
newRect = Submarine.AbsRect(placePosition, placeSize);
//newRect.Width = (int)Math.Max(newRect.Width, Map.gridSize.X);
//newRect.Height = (int)Math.Max(newRect.Height, Map.gridSize.Y);

564
Subsurface/Map/Submarine.cs Normal file
View File

@@ -0,0 +1,564 @@
using FarseerPhysics;
using FarseerPhysics.Collision;
using FarseerPhysics.Dynamics;
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;
namespace Subsurface
{
public enum Direction : byte
{
None = 0, Left = 1, Right = 2
}
class Submarine
{
static string SaveFolder;
Md5Hash hash;
public static List<Submarine> SavedSubmarines = new List<Submarine>();
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;
private Rectangle borders;
private string filePath;
private string name;
public string Name
{
get { return name; }
}
public static Vector2 LastPickedPosition
{
get { return lastPickedPosition; }
}
public static float LastPickedFraction
{
get { return lastPickedFraction; }
}
public Md5Hash Hash
{
get
{
if (hash != null) return hash;
XDocument doc = OpenDoc(filePath);
hash = new Md5Hash(doc);
return hash;
}
}
public static Submarine Loaded
{
get { return loaded; }
}
public static Rectangle Borders
{
get
{
return (loaded==null) ? Rectangle.Empty : loaded.borders;
}
}
public Vector2 Center
{
get { return new Vector2(borders.X+borders.Width/2, borders.Y - borders.Height/2); }
}
public string FilePath
{
get { return filePath; }
}
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++ )
{
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawFront(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth < 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawBack(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth >= 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static Vector2 MouseToWorldGrid(Camera cam)
{
Vector2 position = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
position = cam.ScreenToWorld(position);
return VectorToWorldGrid(position);
}
public static Vector2 VectorToWorldGrid(Vector2 position)
{
position.X = (float)Math.Floor(Convert.ToDouble(position.X / gridSize.X)) * gridSize.X;
position.Y = (float)Math.Ceiling(Convert.ToDouble(position.Y / gridSize.Y)) * gridSize.Y;
return position;
}
public static Rectangle AbsRect(Vector2 pos, Vector2 size)
{
if (size.X < 0.0f)
{
pos.X += size.X;
size.X = -size.X;
}
if (size.Y < 0.0f)
{
pos.Y -= size.Y;
size.Y = -size.Y;
}
return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
}
public static bool RectContains(Rectangle rect, Vector2 pos)
{
return (pos.X > rect.X && pos.X < rect.X + rect.Width
&& pos.Y < rect.Y && pos.Y > rect.Y - rect.Height);
}
public static bool RectsOverlap(Rectangle rect1, Rectangle rect2, bool inclusive=true)
{
if (inclusive)
{
return !(rect1.X > rect2.X + rect2.Width || rect1.X + rect1.Width < rect2.X ||
rect1.Y < rect2.Y - rect2.Height || rect1.Y - rect1.Height > rect2.Y);
}
else
{
return !(rect1.X >= rect2.X + rect2.Width || rect1.X + rect1.Width <= rect2.X ||
rect1.Y <= rect2.Y - rect2.Height || rect1.Y - rect1.Height >= rect2.Y);
}
}
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<Body> ignoredBodies = null)
{
float closestFraction = 1.0f;
Body closestBody = null;
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories == Category.None) return -1;
if (ignoredBodies != null && ignoredBodies.Contains(fixture.Body)) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null && (structure.IsPlatform || !structure.HasBody)) return -1;
if (fraction < closestFraction)
{
closestFraction = fraction;
if (fixture.Body!=null) closestBody = fixture.Body;
}
return fraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestBody;
}
public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd)
{
Body closestBody = null;
float closestFraction = 1.0f;
if (Vector2.Distance(rayStart,rayEnd)<0.01f)
{
closestFraction = 0.01f;
return null;
}
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories != Physics.CollisionWall) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null)
{
if (structure.IsPlatform || structure.StairDirection != Direction.None) return -1;
int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(point));
if (sectionIndex > -1 && structure.SectionHasHole(sectionIndex)) return -1;
}
if (fraction < closestFraction)
{
closestBody = fixture.Body;
closestFraction = fraction;
}
return closestFraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestBody;
}
public static Body PickBody(Vector2 point)
{
Body foundBody = null;
AABB aabb = new AABB(point, point);
Game1.world.QueryAABB(p =>
{
foundBody = p.Body;
return true;
}, ref aabb);
return foundBody;
}
public static bool InsideWall(Vector2 point)
{
Body foundBody = PickBody(point);
if (foundBody==null) return false;
Structure wall = foundBody.UserData as Structure;
if (wall == null || wall.IsPlatform) return false;
return true;
}
public void Save()
{
SaveAs(filePath);
}
public void SaveAs(string filePath)
{
//if (filePath=="")
//{
// DebugConsole.ThrowError("No save file selected");
// return;
//}
XDocument doc = new XDocument(new XElement((XName)name));
foreach (MapEntity e in MapEntity.mapEntityList)
{
e.Save(doc);
}
hash = new Md5Hash(doc);
doc.Root.Add(new XAttribute("md5hash", hash.MD5Hash));
try
{
SaveUtil.CompressStringToFile(filePath, doc.ToString());
}
catch (Exception e)
{
DebugConsole.ThrowError("Saving submarine ''" + filePath + "'' failed!", e);
}
//doc.Save(filePath);
}
public static void SaveCurrent(string savePath)
{
if (loaded==null)
{
loaded = new Submarine(savePath);
return;
}
loaded.SaveAs(savePath);
}
public static void Preload(string folder)
{
SaveFolder = folder;
//string[] mapFilePaths;
Unload();
SavedSubmarines.Clear();
if (!Directory.Exists(SaveFolder))
{
try
{
Directory.CreateDirectory(SaveFolder);
}
catch
{
DebugConsole.ThrowError("Directory ''"+SaveFolder+"'' not found and creating the directory failed.");
return;
}
}
string[] filePaths;
try
{
filePaths = Directory.GetFiles(SaveFolder);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't open directory ''" + SaveFolder + "''!", e);
return;
}
foreach (string path in filePaths)
{
//Map savedMap = new Map(mapPath);
SavedSubmarines.Add(new Submarine(path));
}
}
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;
string extension = "";
try
{
extension = Path.GetExtension(file);
}
catch
{
DebugConsole.ThrowError("Couldn't load submarine ''" + file + "! (Unrecognized file extension)");
return null;
}
if (extension == ".gz")
{
Stream stream = SaveUtil.DecompressFiletoStream(file);
if (stream == null)
{
DebugConsole.ThrowError("Loading submarine ''" + file + "'' failed!");
return null;
}
try
{
stream.Position = 0;
doc = XDocument.Load(stream); //ToolBox.TryLoadXml(file);
stream.Close();
stream.Dispose();
}
catch
{
DebugConsole.ThrowError("Loading submarine ''" + file + "'' failed!");
return null;
}
}
else if (extension == ".xml")
{
try
{
doc = XDocument.Load(file);
}
catch
{
DebugConsole.ThrowError("Loading submarine ''" + file + "'' failed!");
return null;
}
}
else
{
DebugConsole.ThrowError("Couldn't load submarine ''" + file + "! (Unrecognized file extension)");
return null;
}
return doc;
}
public void Load()
{
//string file = filePath;
XDocument doc = OpenDoc(filePath);
if (doc == null) return;
foreach (XElement element in doc.Root.Elements())
{
string typeName = element.Name.ToString();
Type t;
try
{
// Get the type of a specified class.
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.");
continue;
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type ''" + typeName + "''.", e);
continue;
}
try
{
MethodInfo loadMethod = t.GetMethod("Load");
loadMethod.Invoke(t, new object[] { element });
}
catch (Exception e)
{
DebugConsole.ThrowError("Could not find the method ''Load'' in " + t + ".", e);
}
}
borders = new Rectangle(0, 0, 1, 1);
foreach (Hull hull in Hull.hullList)
{
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);
}
MapEntity.LinkAll();
foreach (Item item in Item.itemList)
{
foreach (ItemComponent ic in item.components)
{
ic.OnMapLoaded();
}
}
loaded = this;
}
public static Submarine Load(string file)
{
Unload();
Submarine sub = new Submarine(file);
sub.Load();
return sub;
}
public static void Unload()
{
if (loaded == null) return;
loaded.Clear();
loaded = null;
}
private void Clear()
{
if (Game1.GameScreen.Cam != null) Game1.GameScreen.Cam.TargetPos = Vector2.Zero;
Entity.RemoveAll();
PhysicsBody.list.Clear();
Ragdoll.list.Clear();
Game1.world.Clear();
}
}
}

View File

@@ -972,5 +972,17 @@ namespace Voronoi2
return true;
}
public List<GraphEdge> MakeVoronoiGraph(List<Vector2> sites, int width, int height)
{
double[] xVal = new double[sites.Count];
double[] yVal = new double[sites.Count];
for (int i = 0; i < sites.Count; i++)
{
xVal[i] = sites[i].X;
yVal[i] = sites[i].Y;
}
return generateVoronoi(xVal, yVal, 0, width, 0, height);
}
} // Voronoi Class End
} // namespace Voronoi2 End

View File

@@ -50,7 +50,9 @@
*/
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Subsurface;
using System;
using System.Collections.Generic;
@@ -119,6 +121,8 @@ namespace Voronoi2
public List<GraphEdge> edges;
public Site site;
public List<Body> bodies;
public Vector2 Center
{
get { return new Vector2((float)site.coord.x, (float)site.coord.y); }
@@ -127,6 +131,8 @@ namespace Voronoi2
public VoronoiCell(Site site)
{
edges = new List<GraphEdge>();
bodies = new List<Body>();
this.site = site;
}
}
@@ -135,6 +141,23 @@ namespace Voronoi2
{
public Vector2 point1, point2;
public Site site1, site2;
public VoronoiCell cell1, cell2;
public VoronoiCell AdjacentCell(VoronoiCell cell)
{
if (cell1==cell)
{
return cell2;
}
else if (cell2==cell)
{
return cell1;
}
else
{
return null;
}
}
}
// للترتيب

View File

@@ -68,7 +68,7 @@ namespace Subsurface
if (e.GetType()!=typeof(WayPoint)) continue;
if (e == this) continue;
if (!Map.RectContains(e.Rect, position)) continue;
if (!Submarine.RectContains(e.Rect, position)) continue;
linkedTo.Add(e);
e.linkedTo.Add(this);
@@ -123,7 +123,7 @@ namespace Subsurface
Rectangle rect = new Rectangle(
int.Parse(element.Attribute("x").Value),
int.Parse(element.Attribute("y").Value),
(int)Map.gridSize.X, (int)Map.gridSize.Y);
(int)Submarine.gridSize.X, (int)Submarine.gridSize.Y);
WayPoint w = new WayPoint(rect);

View File

@@ -240,7 +240,7 @@ namespace Subsurface.Networking
TimeSpan duration = new TimeSpan(0,(int)durationMinutes,0);
//int gameModeIndex = inc.ReadInt32();
Game1.GameSession = new GameSession(Map.Loaded);
Game1.GameSession = new GameSession(Submarine.Loaded);
Game1.GameSession.StartShift(duration, 1);
myCharacter = ReadCharacterData(inc);
@@ -323,7 +323,7 @@ namespace Subsurface.Networking
public void EndGame(string endMessage)
{
Map.Unload();
Submarine.Unload();
Game1.NetLobbyScreen.Select();

View File

@@ -270,7 +270,7 @@ namespace Subsurface.Networking
int seed = DateTime.Now.Millisecond;
Game1.random = new Random(seed);
Map selectedMap = Game1.NetLobbyScreen.SelectedMap as Map;
Submarine selectedMap = Game1.NetLobbyScreen.SelectedMap as Submarine;
//selectedMap.Load();
@@ -307,7 +307,7 @@ namespace Subsurface.Networking
msg.Write(seed);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Name);
msg.Write(Game1.NetLobbyScreen.SelectedMap.MapHash.MD5Hash);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Hash.MD5Hash);
msg.Write(Game1.NetLobbyScreen.GameDuration.TotalMinutes);
@@ -339,7 +339,7 @@ namespace Subsurface.Networking
public void EndGame(string endMessage)
{
Map.Unload();
Submarine.Unload();
gameStarted = false;

View File

@@ -66,7 +66,7 @@ namespace Subsurface.Particles
velocity = speed;
this.rotation = rotation + ToolBox.RandomFloat(prefab.startRotationMin, prefab.startRotationMax);
this.rotation = rotation + ToolBox.RandomFloatLocal(prefab.startRotationMin, prefab.startRotationMax);
prevRotation = rotation;
float rand = (float)Game1.localRandom.NextDouble();
@@ -132,7 +132,7 @@ namespace Subsurface.Particles
}
else
{
if (Map.InsideWall(new Vector2(drawPosition.X, -drawPosition.Y)))
if (Submarine.InsideWall(new Vector2(drawPosition.X, -drawPosition.Y)))
{
return false;
}

View File

@@ -61,7 +61,7 @@ namespace Subsurface.Particles
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation=0.0f)
{
if (!Map.RectContains(cam.WorldView, ConvertUnits.ToDisplayUnits(position))) return null;
if (!Submarine.RectContains(cam.WorldView, ConvertUnits.ToDisplayUnits(position))) return null;
if (particleCount >= MaxParticles) return null;
if (particles[particleCount] == null) particles[particleCount] = new Particle();

View File

@@ -23,7 +23,7 @@ namespace Subsurface
//Directory.CreateDirectory(Path.GetDirectoryName(filePath) + "\\temp");
Map.Loaded.SaveAs(tempPath + "\\map.gz");
Submarine.Loaded.SaveAs(tempPath + "\\map.gz");
Game1.GameSession.Save(tempPath + "\\gamesession.xml");
//Game1.GameSession.crewManager.Save(directory+"\\crew.xml");
@@ -39,7 +39,7 @@ namespace Subsurface
DecompressToDirectory(filePath, tempPath, null);
Map selectedMap = Map.Load(tempPath +"\\map.gz");
Submarine selectedMap = Submarine.Load(tempPath +"\\map.gz");
Game1.GameSession = new GameSession(selectedMap, filePath, tempPath + "\\gamesession.xml");
Directory.Delete(tempPath, true);

View File

@@ -140,7 +140,7 @@ namespace Subsurface
null, null, null, null,
cam.Transform);
Map.Draw(spriteBatch, true);
Submarine.Draw(spriteBatch, true);
spriteBatch.End();

View File

@@ -229,7 +229,7 @@ namespace Subsurface
graphics.Clear(new Color(0.051f, 0.149f, 0.271f, 1.0f));
Map.Draw(spriteBatch, true);
Submarine.Draw(spriteBatch, true);
if (!characterMode)
{

View File

@@ -57,16 +57,16 @@ namespace Subsurface
AmbientSoundManager.Update();
//Vector2 targetMovement = Vector2.Zero;
//if (PlayerInput.KeyDown(Keys.I)) targetMovement.Y += 1.0f;
//if (PlayerInput.KeyDown(Keys.K)) targetMovement.Y -= 1.0f;
//if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f;
//if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f;
if (Game1.GameSession.Level!=null)
{
Vector2 targetMovement = Vector2.Zero;
if (PlayerInput.KeyDown(Keys.I)) targetMovement.Y += 1.0f;
if (PlayerInput.KeyDown(Keys.K)) targetMovement.Y -= 1.0f;
if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f;
if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f;
//foreach (MapEntity e in Structure.mapEntityList)
//{
// e.Move(targetMovement);
//}
Game1.GameSession.Submarine.Move(targetMovement*1000.0f, (float)deltaTime);
}
if (Game1.GameSession!=null) Game1.GameSession.Update((float)deltaTime);
//EventManager.Update(gameTime);
@@ -170,8 +170,8 @@ namespace Subsurface
if (y<0)
{
backgroundTop.SourceRect = new Rectangle(x, y, 1024, 1024);
backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(Game1.GraphicsWidth, Math.Min(1024 - y, Game1.GraphicsHeight)),
backgroundTop.SourceRect = new Rectangle(x, y, 1024, Math.Min(-y,1024));
backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(Game1.GraphicsWidth, Math.Min(-y, Game1.GraphicsHeight)),
Vector2.Zero, Color.White);
}
}
@@ -183,10 +183,8 @@ namespace Subsurface
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
if (Game1.Level!=null) Game1.Level.Render(spriteBatch);
Map.DrawBack(spriteBatch);
Submarine.DrawBack(spriteBatch);
foreach (Character c in Character.characterList) c.Draw(spriteBatch);
@@ -257,10 +255,18 @@ namespace Subsurface
null, null, null, null,
cam.Transform);
Map.DrawFront(spriteBatch);
Submarine.DrawFront(spriteBatch);
spriteBatch.End();
if (Game1.GameSession != null && Game1.GameSession.Level != null)
{
Game1.GameSession.Level.Render(graphics, cam);
Game1.GameSession.Level.SetObserverPosition(cam.WorldViewCenter);
}
if (Game1.Level != null) Game1.Level.Render(graphics, cam);
LightManager.DrawFow(graphics,cam);
}
}

View File

@@ -9,10 +9,12 @@ namespace Subsurface
{
class LobbyScreen : Screen
{
enum PanelTab { Crew = 0, Map = 1, Hire = 2 }
GUIFrame leftPanel;
GUIFrame[] rightPanel;
GUIFrame shiftPanel;
GUIButton startButton;
int selectedRightPanel;
@@ -26,6 +28,8 @@ namespace Subsurface
Character previewCharacter;
Level selectedLevel;
public LobbyScreen()
{
Rectangle panelRect = new Rectangle(
@@ -44,62 +48,55 @@ namespace Subsurface
"", Color.Transparent, Color.White, Alignment.Left, leftPanel);
moneyText.TextGetter = GetMoney;
GUIButton button = new GUIButton(new Rectangle(0, 60, 100, 30), "Crew", GUI.style, Alignment.CenterX, leftPanel);
button.UserData = 0;
GUIButton button = new GUIButton(new Rectangle(0, 60, 100, 30), "Map", GUI.style, Alignment.Left, leftPanel);
button.UserData = PanelTab.Map;
button.OnClicked = SelectRightPanel;
button = new GUIButton(new Rectangle(0, 100, 100, 30), "Hire", GUI.style, Alignment.CenterX, leftPanel);
button.UserData = 1;
button = new GUIButton(new Rectangle(0, 100, 100, 30), "Crew", GUI.style, Alignment.Left, leftPanel);
button.UserData = PanelTab.Crew;
button.OnClicked = SelectRightPanel;
//--------------------------------------
button = new GUIButton(new Rectangle(0, 140, 100, 30), "Hire", GUI.style, Alignment.Left, leftPanel);
button.UserData = PanelTab.Hire;
button.OnClicked = SelectRightPanel;
//---------------------------------------------------------------
//---------------------------------------------------------------
panelRect = new Rectangle(
panelRect.X + panelRect.Width + (int)(GUI.style.largePadding.X),
panelRect.Y,
(int)GUI.style.largePadding.Y,
Game1.GraphicsWidth - panelRect.Width - (int)(GUI.style.largePadding.X * 3.0f),
(int)(Game1.GraphicsHeight * 0.3f) - (int)(GUI.style.largePadding.Y * 1.5f));
Game1.GraphicsHeight - (int)(GUI.style.largePadding.Y * 2));
shiftPanel = new GUIFrame(panelRect, GUI.style.backGroundColor);
shiftPanel.Padding = GUI.style.smallPadding;
rightPanel = new GUIFrame[3];
GUITextBlock dayText = new GUITextBlock(new Rectangle(0, 0, 200, 25),
"", Color.Transparent, Color.White, Alignment.Left, shiftPanel);
dayText.TextGetter = GetDay;
rightPanel[(int)PanelTab.Crew] = new GUIFrame(panelRect, GUI.style.backGroundColor);
rightPanel[(int)PanelTab.Crew].Padding = GUI.style.smallPadding;
GUIProgressBar progressBar = new GUIProgressBar(new Rectangle(0, 30, 200, 20), Color.Green, 0.0f, shiftPanel);
progressBar.ProgressGetter = GetWeekProgress;
new GUITextBlock(new Rectangle(0, 0, 200, 25), "Crew:", Color.Transparent, Color.White, Alignment.Left, rightPanel[(int)PanelTab.Crew]);
button = new GUIButton(new Rectangle(0,0,100,30), "Start", GUI.style,
(Alignment.Right | Alignment.Bottom), shiftPanel);
button.OnClicked = StartShift;
//---------------------------------------------------------------
//---------------------------------------------------------------
rightPanel = new GUIFrame[2];
panelRect = new Rectangle(
panelRect.X,
panelRect.Y + panelRect.Height + (int)(GUI.style.largePadding.Y),
panelRect.Width,
(int)(Game1.GraphicsHeight * 0.7f) - (int)(GUI.style.largePadding.Y * 1.5f));
rightPanel[0] = new GUIFrame(panelRect, GUI.style.backGroundColor);
rightPanel[0].Padding = GUI.style.smallPadding;
new GUITextBlock(new Rectangle(0, 0, 200, 25), "Crew:", Color.Transparent, Color.White, Alignment.Left, rightPanel[0]);
characterList = new GUIListBox(new Rectangle(0, 30, 300, 0), Color.White, rightPanel[0]);
characterList = new GUIListBox(new Rectangle(0, 30, 300, 0), Color.White, rightPanel[(int)PanelTab.Crew]);
characterList.OnSelected = SelectCharacter;
//---------------------------------------
rightPanel[1] = new GUIFrame(panelRect, GUI.style.backGroundColor);
rightPanel[1].Padding = GUI.style.smallPadding;
rightPanel[(int)PanelTab.Map] = new GUIFrame(panelRect, GUI.style.backGroundColor);
rightPanel[(int)PanelTab.Map].Padding = GUI.style.smallPadding;
hireList = new GUIListBox(new Rectangle(0, 30, 300, 0), Color.White, Alignment.Left, rightPanel[1]);
startButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", GUI.style,
Alignment.BottomRight, rightPanel[(int)PanelTab.Map]);
startButton.OnClicked = StartShift;
startButton.Enabled = false;
//---------------------------------------
rightPanel[(int)PanelTab.Hire] = new GUIFrame(panelRect, GUI.style.backGroundColor);
rightPanel[(int)PanelTab.Hire].Padding = GUI.style.smallPadding;
hireList = new GUIListBox(new Rectangle(0, 30, 300, 0), Color.White, Alignment.Left, rightPanel[(int)PanelTab.Hire]);
hireList.OnSelected = HireCharacter;
}
@@ -168,7 +165,22 @@ namespace Subsurface
previewCharacter.animController.UpdateAnim((float)Physics.step);
Game1.world.Step((float)Physics.step);
}
}
public void SelectLocation(Location location, LocationConnection connection)
{
GUIComponent locationPanel = rightPanel[(int)PanelTab.Map].GetChild("selectedlocation");
if (locationPanel != null) rightPanel[(int)PanelTab.Map].RemoveChild(locationPanel);
locationPanel = new GUIFrame(new Rectangle(0, 0, rightPanel[(int)PanelTab.Map].Rect.Width / 2 - 40, 190), Color.Transparent, rightPanel[(int)PanelTab.Map]);
locationPanel.UserData = "selectedlocation";
new GUITextBlock(new Rectangle(0,0,100,20), location.Name, Color.Transparent, Color.White, Alignment.TopLeft, locationPanel);
startButton.Enabled = true;
selectedLevel = connection.Level;
}
private void UpdateCharacterLists()
@@ -220,7 +232,7 @@ namespace Subsurface
leftPanel.Update((float)deltaTime);
rightPanel[selectedRightPanel].Update((float)deltaTime);
shiftPanel.Update((float)deltaTime);
//shiftPanel.Update((float)deltaTime);
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
@@ -239,10 +251,17 @@ namespace Subsurface
spriteBatch.Begin();
leftPanel.Draw(spriteBatch);
shiftPanel.Draw(spriteBatch);
rightPanel[selectedRightPanel].Draw(spriteBatch);
if (selectedRightPanel == (int)PanelTab.Map)
{
Game1.GameSession.map.Draw(spriteBatch, new Rectangle(
rightPanel[selectedRightPanel].Rect.Right - 20 - 400,
rightPanel[selectedRightPanel].Rect.Y + 20,
400, 400));
}
GUI.Draw((float)deltaTime, spriteBatch, null);
spriteBatch.End();
@@ -352,7 +371,7 @@ namespace Subsurface
private bool StartShift(GUIButton button, object selection)
{
Game1.GameSession.StartShift(TimeSpan.Zero);
Game1.GameSession.StartShift(TimeSpan.Zero, selectedLevel);
Game1.GameScreen.Select();
return true;

View File

@@ -64,7 +64,7 @@ namespace Subsurface
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, menuTabs[(int)Tabs.NewGame]);
mapList = new GUIListBox(new Rectangle(0, 60, 200, 400), Color.White, menuTabs[(int)Tabs.NewGame]);
foreach (Map map in Map.SavedMaps)
foreach (Submarine map in Submarine.SavedSubmarines)
{
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
@@ -76,7 +76,7 @@ namespace Subsurface
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = map;
}
if (Map.SavedMaps.Count > 0) mapList.Select(Map.SavedMaps[0]);
if (Submarine.SavedSubmarines.Count > 0) mapList.Select(Submarine.SavedSubmarines[0]);
button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start", GUI.style, Alignment.Right | Alignment.Bottom, menuTabs[(int)Tabs.NewGame]);
@@ -173,7 +173,7 @@ namespace Subsurface
private bool StartGame(GUIButton button, object obj)
{
Map selectedMap = mapList.SelectedData as Map;
Submarine selectedMap = mapList.SelectedData as Submarine;
if (selectedMap == null) return false;
Game1.GameSession = new GameSession(selectedMap, GameModePreset.list.Find(gm => gm.Name == "Single Player"));

View File

@@ -30,9 +30,9 @@ namespace Subsurface
public bool isServer;
public Map SelectedMap
public Submarine SelectedMap
{
get { return mapList.SelectedData as Map; }
get { return mapList.SelectedData as Submarine; }
}
@@ -135,9 +135,9 @@ namespace Subsurface
mapList.OnSelected = SelectMap;
mapList.Enabled = (Game1.Server!=null);
if (Map.SavedMaps.Count>0)
if (Submarine.SavedSubmarines.Count>0)
{
foreach (Map map in Map.SavedMaps)
foreach (Submarine map in Submarine.SavedSubmarines)
{
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
@@ -245,10 +245,10 @@ namespace Subsurface
{
if (Game1.Server != null) Game1.Server.UpdateNetLobby(obj);
Map map = (Map)obj;
Submarine map = (Submarine)obj;
//map already loaded
if (Map.Loaded!=null && map.FilePath == Map.Loaded.FilePath) return true;
if (Submarine.Loaded!=null && map.FilePath == Submarine.Loaded.FilePath) return true;
map.Load();
@@ -281,13 +281,13 @@ namespace Subsurface
Game1.GameScreen.Cam.MoveCamera((float)deltaTime);
Vector2 pos = new Vector2(
Map.Borders.X + Map.Borders.Width / 2,
Map.Borders.Y - Map.Borders.Height / 2);
Submarine.Borders.X + Submarine.Borders.Width / 2,
Submarine.Borders.Y - Submarine.Borders.Height / 2);
camAngle += (float)deltaTime / 10.0f;
Vector2 offset = (new Vector2(
(float)Math.Cos(camAngle) * (Map.Borders.Width / 2.0f),
(float)Math.Sin(camAngle) * (Map.Borders.Height / 2.0f)));
(float)Math.Cos(camAngle) * (Submarine.Borders.Width / 2.0f),
(float)Math.Sin(camAngle) * (Submarine.Borders.Height / 2.0f)));
pos += offset * 0.8f;
@@ -466,7 +466,7 @@ namespace Subsurface
public void WriteData(NetOutgoingMessage msg)
{
Map selectedMap = mapList.SelectedData as Map;
Submarine selectedMap = mapList.SelectedData as Submarine;
if (selectedMap==null)
{
@@ -476,7 +476,7 @@ namespace Subsurface
else
{
msg.Write(Path.GetFileName(selectedMap.Name));
msg.Write(selectedMap.MapHash.MD5Hash);
msg.Write(selectedMap.Hash.MD5Hash);
}
msg.Write(modeList.SelectedIndex);
@@ -486,7 +486,7 @@ namespace Subsurface
public bool TrySelectMap(string mapName, string md5Hash)
{
Map map = Map.SavedMaps.Find(m => m.Name == mapName);
Submarine map = Submarine.SavedSubmarines.Find(m => m.Name == mapName);
if (map==null)
{
DebugConsole.ThrowError("The map ''" + mapName + "'' has been selected by the server.");
@@ -495,10 +495,10 @@ namespace Subsurface
}
else
{
if (map.MapHash.MD5Hash!=md5Hash)
if (map.Hash.MD5Hash!=md5Hash)
{
DebugConsole.ThrowError("Your version of the map file ''"+map.Name+"'' doesn't match the server's version!");
DebugConsole.ThrowError("Your file: "+map.Name+"(MD5 hash : "+map.MapHash.MD5Hash+")");
DebugConsole.ThrowError("Your file: "+map.Name+"(MD5 hash : "+map.Hash.MD5Hash+")");
DebugConsole.ThrowError("Server's file: " + mapName + "(MD5 hash : " + md5Hash + ")");
return false;
}

View File

@@ -127,7 +127,9 @@
<Compile Include="Map\Level.cs" />
<Compile Include="Map\Lights\ConvexHull.cs" />
<Compile Include="Map\Lights\LightManager.cs" />
<Compile Include="Map\MapHash.cs" />
<Compile Include="Map\Location.cs" />
<Compile Include="Map\Map.cs" />
<Compile Include="Map\Md5Hash.cs" />
<Compile Include="Map\Voronoi.cs" />
<Compile Include="Map\VoronoiElements.cs" />
<Compile Include="Physics\PhysicsBody.cs" />
@@ -161,7 +163,7 @@
<Compile Include="Items\Components\Projectile.cs" />
<Compile Include="Map\MapEntity.cs" />
<Compile Include="Map\MapEntityPrefab.cs" />
<Compile Include="Map\Map.cs" />
<Compile Include="Map\Submarine.cs" />
<Compile Include="Map\Structure.cs" />
<Compile Include="Map\StructurePrefab.cs" />
<Compile Include="Map\WaterRenderer.cs" />

View File

@@ -25,10 +25,20 @@ namespace Subsurface
public static float RandomFloat(float minimum, float maximum)
{
return (float)Game1.localRandom.NextDouble() * (maximum - minimum) + minimum;
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;
}

Binary file not shown.