Renamed project folders from Subsurface to Barotrauma

This commit is contained in:
Regalis
2017-06-04 15:00:53 +03:00
parent ad03c8bf0d
commit 94c6a8ea1b
697 changed files with 157 additions and 211 deletions
@@ -0,0 +1,238 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundCreature : ISteerable
{
const float MaxDepth = 100.0f;
const float CheckWallsInterval = 5.0f;
public bool Enabled;
private BackgroundCreaturePrefab prefab;
private Vector2 position;
private Vector3 velocity;
private float depth;
private SteeringManager steeringManager;
private float checkWallsTimer;
public Swarm Swarm;
Vector2 drawPosition;
public Vector2 TransformedPosition
{
get { return drawPosition; }
}
public Vector2 SimPosition
{
get { return FarseerPhysics.ConvertUnits.ToSimUnits(position); }
}
public Vector2 WorldPosition
{
get { return position; }
}
public Vector2 Velocity
{
get { return new Vector2(velocity.X, velocity.Y); }
}
public Vector2 Steering
{
get;
set;
}
public BackgroundCreature(BackgroundCreaturePrefab prefab, Vector2 position)
{
this.prefab = prefab;
this.position = position;
drawPosition = position;
steeringManager = new SteeringManager(this);
velocity = new Vector3(
Rand.Range(-prefab.Speed, prefab.Speed),
Rand.Range(-prefab.Speed, prefab.Speed),
Rand.Range(0.0f, prefab.WanderZAmount));
checkWallsTimer = Rand.Range(0.0f, CheckWallsInterval);
}
float ang;
Vector2 obstacleDiff;
public void Update(float deltaTime)
{
position += new Vector2(velocity.X, velocity.Y) * deltaTime;
depth = MathHelper.Clamp(depth + velocity.Z * deltaTime, 0.0f, MaxDepth);
checkWallsTimer -= deltaTime;
if (checkWallsTimer <= 0.0f && Level.Loaded != null)
{
checkWallsTimer = CheckWallsInterval;
obstacleDiff = Vector2.Zero;
if (position.Y > Level.Loaded.Size.Y)
{
obstacleDiff = Vector2.UnitY;
}
else if (position.Y < 0.0f)
{
obstacleDiff = -Vector2.UnitY;
}
else if (position.X < 0.0f)
{
obstacleDiff = Vector2.UnitX;
}
else if (position.X > Level.Loaded.Size.X)
{
obstacleDiff = -Vector2.UnitX;
}
else
{
var cells = Level.Loaded.GetCells(position, 1);
if (cells.Count > 0)
{
foreach (Voronoi2.VoronoiCell cell in cells)
{
obstacleDiff += cell.Center - position;
}
obstacleDiff /= cells.Count;
obstacleDiff = Vector2.Normalize(obstacleDiff) * prefab.Speed;
}
}
}
if (Swarm!=null)
{
Vector2 midPoint = Swarm.MidPoint();
float midPointDist = Vector2.Distance(SimPosition, midPoint);
if (midPointDist > Swarm.MaxDistance)
{
steeringManager.SteeringSeek(midPoint, (midPointDist / Swarm.MaxDistance) * prefab.Speed);
}
}
if (prefab.WanderAmount > 0.0f)
{
steeringManager.SteeringWander(prefab.Speed);
}
//Level.Loaded.Size
if (obstacleDiff != Vector2.Zero)
{
steeringManager.SteeringSeek(SimPosition-obstacleDiff, prefab.Speed*2.0f);
}
steeringManager.Update(prefab.Speed);
if (prefab.WanderZAmount>0.0f)
{
ang += Rand.Range(-prefab.WanderZAmount, prefab.WanderZAmount);
velocity.Z = (float)Math.Sin(ang)*prefab.Speed;
}
velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);
}
public void Draw(SpriteBatch spriteBatch)
{
float rotation = 0.0f;
if (!prefab.DisableRotation)
{
rotation = MathUtils.VectorToAngle(new Vector2(velocity.X, -velocity.Y));
if (velocity.X < 0.0f) rotation -= MathHelper.Pi;
}
drawPosition = position;// +Level.Loaded.Position;
if (depth > 0.0f)
{
Vector2 camOffset = drawPosition - GameMain.GameScreen.Cam.WorldViewCenter;
drawPosition -= camOffset * (depth / MaxDepth) * 0.05f;
}
prefab.Sprite.Draw(spriteBatch, new Vector2(drawPosition.X, -drawPosition.Y), Color.Lerp(Color.White, Color.DarkBlue, (depth/MaxDepth)*0.3f),
rotation, 1.0f - (depth / MaxDepth) * 0.2f, velocity.X > 0.0f ? SpriteEffects.None : SpriteEffects.FlipHorizontally, (depth / MaxDepth));
}
}
class Swarm
{
public List<BackgroundCreature> Members;
public readonly float MaxDistance;
public Vector2 MidPoint()
{
if (Members.Count == 0) return Vector2.Zero;
Vector2 midPoint = Vector2.Zero;
foreach (BackgroundCreature member in Members)
{
midPoint += member.SimPosition;
}
midPoint /= Members.Count;
return midPoint;
}
public Vector2 AvgVelocity()
{
if (Members.Count == 0) return Vector2.Zero;
Vector2 avgVel = Vector2.Zero;
foreach (BackgroundCreature member in Members)
{
avgVel += member.Velocity;
}
avgVel /= Members.Count;
return avgVel;
}
public Swarm(List<BackgroundCreature> members, float maxDistance)
{
this.Members = members;
this.MaxDistance = maxDistance;
foreach (BackgroundCreature bgSprite in members)
{
bgSprite.Swarm = this;
}
}
}
}
@@ -0,0 +1,139 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundCreatureManager
{
const int MaxSprites = 100;
const float checkActiveInterval = 1.0f;
float checkActiveTimer;
private List<BackgroundCreaturePrefab> prefabs = new List<BackgroundCreaturePrefab>();
private List<BackgroundCreature> activeSprites = new List<BackgroundCreature>();
public BackgroundCreatureManager(string configPath)
{
LoadConfig(configPath);
}
public BackgroundCreatureManager(List<string> files)
{
foreach(var file in files)
{
LoadConfig(file);
}
}
private void LoadConfig(string configPath)
{
try
{
XDocument doc = ToolBox.TryLoadXml(configPath);
if (doc == null || doc.Root == null) return;
foreach (XElement element in doc.Root.Elements())
{
prefabs.Add(new BackgroundCreaturePrefab(element));
};
}
catch (Exception e)
{
DebugConsole.ThrowError(String.Format("Failed to load BackgroundCreatures from {0}", configPath), e);
}
}
public void SpawnSprites(int count, Vector2? position = null)
{
activeSprites.Clear();
if (prefabs.Count == 0) return;
count = Math.Min(count, MaxSprites);
for (int i = 0; i < count; i++ )
{
Vector2 pos = Vector2.Zero;
if (position == null)
{
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null);
if (wayPoints.Any())
{
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, false)];
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
pos += Rand.Vector(200.0f, false);
}
else
{
pos = Rand.Vector(2000.0f, false);
}
}
else
{
pos = (Vector2)position;
}
var prefab = prefabs[Rand.Int(prefabs.Count, false)];
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, false);
List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
for (int n = 0; n < amount; n++)
{
var newSprite = new BackgroundCreature(prefab, pos);
activeSprites.Add(newSprite);
swarmMembers.Add(newSprite);
}
if (amount > 0)
{
new Swarm(swarmMembers, prefab.SwarmRadius);
}
}
}
public void ClearSprites()
{
activeSprites.Clear();
}
public void Update(Camera cam, float deltaTime)
{
if (checkActiveTimer<0.0f)
{
foreach (BackgroundCreature sprite in activeSprites)
{
sprite.Enabled = (Math.Abs(sprite.TransformedPosition.X - cam.WorldViewCenter.X) < 4000.0f &&
Math.Abs(sprite.TransformedPosition.Y - cam.WorldViewCenter.Y) < 4000.0f);
}
checkActiveTimer = checkActiveInterval;
}
else
{
checkActiveTimer -= deltaTime;
}
foreach (BackgroundCreature sprite in activeSprites)
{
if (!sprite.Enabled) continue;
sprite.Update(deltaTime);
}
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (BackgroundCreature sprite in activeSprites)
{
if (!sprite.Enabled) continue;
sprite.Draw(spriteBatch);
}
}
}
}
@@ -0,0 +1,47 @@
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundCreaturePrefab
{
public readonly Sprite Sprite;
public readonly float Speed;
public readonly float WanderAmount;
public readonly float WanderZAmount;
public readonly int SwarmMin, SwarmMax;
public readonly float SwarmRadius;
public readonly bool DisableRotation;
public BackgroundCreaturePrefab(XElement element)
{
Speed = ToolBox.GetAttributeFloat(element, "speed", 1.0f);
WanderAmount = ToolBox.GetAttributeFloat(element, "wanderamount", 0.0f);
WanderZAmount = ToolBox.GetAttributeFloat(element, "wanderzamount", 0.0f);
SwarmMin = ToolBox.GetAttributeInt(element, "swarmmin", 1);
SwarmMax = ToolBox.GetAttributeInt(element, "swarmmax", 1);
SwarmRadius = ToolBox.GetAttributeFloat(element, "swarmradius", 200.0f);
DisableRotation = ToolBox.GetAttributeBool(element, "disablerotation", false);
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue;
Sprite = new Sprite(subElement);
break;
}
}
}
}
@@ -0,0 +1,349 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Voronoi2;
namespace Barotrauma
{
class BackgroundSprite
{
public readonly BackgroundSpritePrefab Prefab;
public Vector3 Position;
public float Scale;
public float Rotation;
//public Vector2[] spriteCorners;
public BackgroundSprite(BackgroundSpritePrefab prefab, Vector3 position, float scale, float rotation = 0.0f)
{
this.Prefab = prefab;
this.Position = position;
this.Scale = scale;
this.Rotation = rotation;
}
}
class BackgroundSpriteManager
{
const int GridSize = 1000;
private List<BackgroundSpritePrefab> prefabs = new List<BackgroundSpritePrefab>();
private List<BackgroundSprite>[,] sprites;
private float swingTimer;
public BackgroundSpriteManager(string configPath)
{
LoadConfig(configPath);
}
public BackgroundSpriteManager(List<string> files)
{
foreach (var file in files)
{
LoadConfig(file);
}
}
private void LoadConfig(string configPath)
{
try
{
XDocument doc = ToolBox.TryLoadXml(configPath);
if (doc == null || doc.Root == null) return;
foreach (XElement element in doc.Root.Elements())
{
prefabs.Add(new BackgroundSpritePrefab(element));
}
}
catch (Exception e)
{
DebugConsole.ThrowError(String.Format("Failed to load BackgroundSprites from {0}", configPath), e);
}
}
public void PlaceSprites(Level level, int amount)
{
sprites = new List<BackgroundSprite>[
(int)Math.Ceiling(level.Size.X / GridSize),
(int)Math.Ceiling(level.Size.Y / GridSize)];
for (int x = 0; x < sprites.GetLength(0); x++)
{
for (int y = 0; y < sprites.GetLength(1); y++)
{
sprites[x, y] = new List<BackgroundSprite>();
}
}
for (int i = 0 ; i < amount; i++)
{
BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
GraphEdge selectedEdge = null;
Vector2 edgeNormal = Vector2.One;
Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge, out edgeNormal);
if (pos == null) continue;
float rotation = 0.0f;
if (prefab.AlignWithSurface)
{
rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
}
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, false);
var newSprite = new BackgroundSprite(prefab,
new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, false)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation);
//calculate the positions of the corners of the rotated sprite
Vector2 halfSize = newSprite.Prefab.Sprite.size * newSprite.Scale / 2;
var spriteCorners = new Vector2[]
{
-halfSize, new Vector2(-halfSize.X, halfSize.Y),
halfSize, new Vector2(halfSize.X, -halfSize.Y)
};
Vector2 pivotOffset = newSprite.Prefab.Sprite.Origin * newSprite.Scale - halfSize;
pivotOffset.X = -pivotOffset.X;
pivotOffset = new Vector2(
(float)(pivotOffset.X * Math.Cos(-rotation) - pivotOffset.Y * Math.Sin(-rotation)),
(float)(pivotOffset.X * Math.Sin(-rotation) + pivotOffset.Y * Math.Cos(-rotation)));
for (int j = 0; j < 4; j++)
{
spriteCorners[j] = new Vector2(
(float)(spriteCorners[j].X * Math.Cos(-rotation) - spriteCorners[j].Y * Math.Sin(-rotation)),
(float)(spriteCorners[j].X * Math.Sin(-rotation) + spriteCorners[j].Y * Math.Cos(-rotation)));
spriteCorners[j] += (Vector2)pos + pivotOffset;
}
//newSprite.spriteCorners = spriteCorners;
int minX = (int)Math.Floor((spriteCorners.Min(c => c.X) - newSprite.Position.Z) / GridSize);
int maxX = (int)Math.Floor((spriteCorners.Max(c => c.X) + newSprite.Position.Z) / GridSize);
if (minX < 0 || maxX >= sprites.GetLength(0)) continue;
int minY = (int)Math.Floor((spriteCorners.Min(c => c.Y) - newSprite.Position.Z) / GridSize);
int maxY = (int)Math.Floor((spriteCorners.Max(c => c.Y) + newSprite.Position.Z) / GridSize);
if (minY < 0 || maxY >= sprites.GetLength(1)) continue;
for (int x = minX; x <= maxX; x++)
{
for (int y = minY; y <= maxY; y++)
{
sprites[x, y].Add(newSprite);
}
}
}
}
private Vector2? FindSpritePosition(Level level, BackgroundSpritePrefab prefab, out GraphEdge closestEdge, out Vector2 edgeNormal)
{
closestEdge = null;
edgeNormal = Vector2.One;
Vector2 randomPos = new Vector2(
Rand.Range(0.0f, level.Size.X, false),
Rand.Range(0.0f, level.Size.Y, false));
if (!prefab.SpawnOnWalls) return randomPos;
List<GraphEdge> edges = new List<GraphEdge>();
List<Vector2> normals = new List<Vector2>();
var cells = level.GetCells(randomPos);
if (cells.Any())
{
VoronoiCell cell = cells[Rand.Int(cells.Count, false)];
foreach (GraphEdge edge in cell.edges)
{
if (!edge.isSolid || edge.OutsideLevel) continue;
Vector2 normal = edge.GetNormal(cell);
if (prefab.Alignment.HasFlag(Alignment.Bottom) && normal.Y < -0.5f)
{
edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Top) && normal.Y > 0.5f)
{
edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Left) && normal.X < -0.5f)
{
edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Right) && normal.X > 0.5f)
{
edges.Add(edge);
}
else
{
continue;
}
normals.Add(normal);
}
}
foreach (RuinGeneration.Ruin ruin in Level.Loaded.Ruins)
{
Rectangle expandedArea = ruin.Area;
expandedArea.Inflate(ruin.Area.Width, ruin.Area.Height);
if (!expandedArea.Contains(randomPos)) continue;
foreach (var ruinShape in ruin.RuinShapes)
{
foreach (var wall in ruinShape.Walls)
{
if (!prefab.Alignment.HasFlag(ruinShape.GetLineAlignment(wall))) continue;
edges.Add(new GraphEdge(wall.A, wall.B));
normals.Add((wall.A + wall.B) / 2.0f - ruinShape.Center);
}
}
}
if (!edges.Any()) return null;
int index = Rand.Int(edges.Count, false);
closestEdge = edges[index];
edgeNormal = normals[index];
float length = Vector2.Distance(closestEdge.point1, closestEdge.point2);
Vector2 dir = (closestEdge.point1 - closestEdge.point2) / length;
Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false);
return pos;
}
public void Update(float deltaTime)
{
swingTimer += deltaTime;
}
public void DrawSprites(SpriteBatch spriteBatch, Camera cam)
{
Rectangle indices = Rectangle.Empty;
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize);
if (indices.X >= sprites.GetLength(0)) return;
indices.Y = (int)Math.Floor((cam.WorldView.Y - cam.WorldView.Height) / (float)GridSize);
if (indices.Y >= sprites.GetLength(1)) return;
indices.Width = (int)Math.Floor(cam.WorldView.Right / (float)GridSize)+1;
if (indices.Width < 0) return;
indices.Height = (int)Math.Floor(cam.WorldView.Y / (float)GridSize)+1;
if (indices.Height < 0) return;
indices.X = Math.Max(indices.X, 0);
indices.Y = Math.Max(indices.Y, 0);
indices.Width = Math.Min(indices.Width, sprites.GetLength(0)-1);
indices.Height = Math.Min(indices.Height, sprites.GetLength(1)-1);
float swingState = (float)Math.Sin(swingTimer * 0.1f);
List<BackgroundSprite> visibleSprites = new List<BackgroundSprite>();
float z = 0.0f;
for (int x = indices.X; x <= indices.Width; x++)
{
for (int y = indices.Y; y <= indices.Height; y++)
{
foreach (BackgroundSprite sprite in sprites[x, y])
{
int drawOrderIndex = 0;
for (int i = 0; i < visibleSprites.Count; i++)
{
if (visibleSprites[i] == sprite)
{
drawOrderIndex = -1;
break;
}
if (visibleSprites[i].Position.Z > sprite.Position.Z)
{
break;
}
else
{
drawOrderIndex = i + 1;
}
}
if (drawOrderIndex >= 0)
{
visibleSprites.Insert(drawOrderIndex, sprite);
}
}
}
}
foreach (BackgroundSprite sprite in visibleSprites)
{
Vector2 camDiff = new Vector2(sprite.Position.X, sprite.Position.Y) - cam.WorldViewCenter;
camDiff.Y = -camDiff.Y;
sprite.Prefab.Sprite.Draw(
spriteBatch,
new Vector2(sprite.Position.X, -sprite.Position.Y) - camDiff * sprite.Position.Z / 10000.0f,
Color.Lerp(Color.White, Level.Loaded.BackgroundColor, sprite.Position.Z / 5000.0f),
sprite.Rotation + swingState * sprite.Prefab.SwingAmount,
sprite.Scale,
SpriteEffects.None,
z);
/*for (int i = 0; i < 4; i++)
{
GUI.DrawLine(spriteBatch,
new Vector2(sprite.spriteCorners[i].X, -sprite.spriteCorners[i].Y),
new Vector2(sprite.spriteCorners[(i + 1) % 4].X, -sprite.spriteCorners[(i + 1) % 4].Y),
Color.White, 0, 5);
}*/
if (GameMain.DebugDraw)
{
GUI.DrawRectangle(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y), new Vector2(10.0f, 10.0f), Color.Red, true);
}
z += 0.0001f;
}
}
private BackgroundSpritePrefab GetRandomPrefab(string levelType)
{
int totalCommonness = 0;
foreach (BackgroundSpritePrefab prefab in prefabs)
{
totalCommonness += prefab.GetCommonness(levelType);
}
float randomNumber = Rand.Int(totalCommonness+1, false);
foreach (BackgroundSpritePrefab prefab in prefabs)
{
if (randomNumber <= prefab.GetCommonness(levelType))
{
return prefab;
}
randomNumber -= prefab.GetCommonness(levelType);
}
return null;
}
}
}
@@ -0,0 +1,89 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundSpritePrefab
{
public readonly Sprite Sprite;
public readonly Alignment Alignment;
public readonly Vector2 Scale;
public bool SpawnOnWalls;
public readonly bool AlignWithSurface;
public readonly Vector2 RandomRotation;
public readonly Vector2 DepthRange;
public readonly float SwingAmount;
public readonly int Commonness;
public Dictionary<string, int> OverrideCommonness;
public BackgroundSpritePrefab(XElement element)
{
string alignmentStr = ToolBox.GetAttributeString(element, "alignment", "");
if (string.IsNullOrEmpty(alignmentStr) || !Enum.TryParse(alignmentStr, out Alignment))
{
Alignment = Alignment.Top | Alignment.Bottom | Alignment.Left | Alignment.Right;
}
Commonness = ToolBox.GetAttributeInt(element, "commonness", 1);
SpawnOnWalls = ToolBox.GetAttributeBool(element, "spawnonwalls", true);
Scale.X = ToolBox.GetAttributeFloat(element, "minsize", 1.0f);
Scale.Y = ToolBox.GetAttributeFloat(element, "maxsize", 1.0f);
DepthRange = ToolBox.GetAttributeVector2(element, "depthrange", new Vector2(0.0f, 1.0f));
AlignWithSurface = ToolBox.GetAttributeBool(element, "alignwithsurface", false);
RandomRotation = ToolBox.GetAttributeVector2(element, "randomrotation", Vector2.Zero);
RandomRotation.X = MathHelper.ToRadians(RandomRotation.X);
RandomRotation.Y = MathHelper.ToRadians(RandomRotation.Y);
SwingAmount = MathHelper.ToRadians(ToolBox.GetAttributeFloat(element, "swingamount", 0.0f));
OverrideCommonness = new Dictionary<string, int>();
foreach (XElement subElement in element.Elements())
{
switch(subElement.Name.ToString().ToLowerInvariant())
{
case "sprite":
Sprite = new Sprite(subElement);
break;
case "overridecommonness":
string levelType = ToolBox.GetAttributeString(subElement, "leveltype", "");
if (!OverrideCommonness.ContainsKey(levelType))
{
OverrideCommonness.Add(levelType, ToolBox.GetAttributeInt(subElement, "commonness", 1));
}
break;
}
}
}
public int GetCommonness(string levelType)
{
int commonness = 0;
if (!OverrideCommonness.TryGetValue(levelType, out commonness))
{
return Commonness;
}
return commonness;
}
}
}