Improved background sprite placement logic: orientation of the cell edges determined by their normals instead of their position relative to the cell

This commit is contained in:
Regalis
2016-09-27 20:18:55 +03:00
parent 7f543c394a
commit 9b15d2f894
3 changed files with 59 additions and 37 deletions

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<backgroundsprites>
<hanging1 alignment="Bottom" minsize="0.5" maxsize="1.5" commonness="5">
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="0,0,242,543" origin="0.5,0.0"/>
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="0,0,242,543" origin="0.5,0.15"/>
</hanging1>
<hanging2 alignment="Bottom" minsize="0.5" maxsize="1.5" commonness="5">
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="241,0,322,720" origin="0.5,0.0"/>
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="241,0,322,720" origin="0.5,0.15"/>
</hanging2>
<kelp1 alignment="Top" minsize="0.5" maxsize="1.5" commonness="10">
@@ -35,9 +35,14 @@
<branches2 minsize="0.5" maxsize="2.0" alignwithsurface="true" swingamount="3" randomrotation="-20,20" commonness="4">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="255,0,246,479" origin="0.5,0.9"/>
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="247,0,278,479" origin="0.2,0.9"/>
</branches2>
<branches3 minsize="0.5" maxsize="2.0" alignwithsurface="true" swingamount="3" randomrotation="-20,20" commonness="4">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="526,0,245,479" origin="0.4,0.9"/>
</branches3>
<fungus minsize="0.5" maxsize="1.5" alignwithsurface="true" swingamount="1" commonness="3">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="0,681,442,343" origin="0.5,0.9"/>

View File

@@ -86,36 +86,35 @@ namespace Barotrauma
{
BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
GraphEdge selectedEdge = null;
Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge);
Vector2 edgeNormal = Vector2.One;
Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge, out edgeNormal);
if (pos == null) continue;
float rotation = 0.0f;
if (prefab.AlignWithSurface)
{
Vector2 leftPoint = selectedEdge.point2;
Vector2 rightPoint = selectedEdge.point1;
rotation = -MathUtils.VectorToAngle(rightPoint - leftPoint);
rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
}
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, false);
var newSprite = new BackgroundSprite(prefab,
(Vector2)pos, Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation);
int x = (int)Math.Floor(((Vector2)pos).X / GridSize);
if (x<0 || x >= sprites.GetLength(0)) continue;
if (x < 0 || x >= sprites.GetLength(0)) continue;
int y = (int)Math.Floor(((Vector2)pos).Y / GridSize);
if (y<0 || y >= sprites.GetLength(1)) continue;
if (y < 0 || y >= sprites.GetLength(1)) continue;
sprites[x,y].Add(newSprite);
}
}
private Vector2? FindSpritePosition(Level level, BackgroundSpritePrefab prefab, out GraphEdge closestEdge)
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),
@@ -127,43 +126,46 @@ namespace Barotrauma
VoronoiCell cell = cells[Rand.Int(cells.Count, false)];
List<GraphEdge> edges = new List<GraphEdge>();
List<Vector2> normals = new List<Vector2>();
foreach (GraphEdge edge in cell.edges)
{
if (!edge.isSolid || edge.OutsideLevel) continue;
Vector2 normal = edge.GetNormal(cell);
if (prefab.Alignment.HasFlag(Alignment.Bottom) &&
Math.Abs(edge.point1.X - edge.point2.X) < Math.Abs(edge.point1.Y - edge.point2.Y))
{
if (edge.Center.Y < cell.Center.Y) edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Top) &&
Math.Abs(edge.point1.X - edge.point2.X) < Math.Abs(edge.point1.Y - edge.point2.Y))
{
if (edge.Center.Y > cell.Center.Y) edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Left))
{
if (edge.Center.X < cell.Center.X) edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Right))
{
if (edge.Center.X > cell.Center.X) edges.Add(edge);
}
else
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);
}
if (!edges.Any()) return null;
closestEdge = edges[Rand.Int(edges.Count,false)];
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.Center;
pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false);
Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false);
return pos;
}

View File

@@ -218,10 +218,25 @@ namespace Voronoi2
{
return cell1;
}
else
return null;
}
/// <summary>
/// Returns the normal of the edge that points outwards from the specified cell
/// </summary>
public Vector2 GetNormal(VoronoiCell cell)
{
Vector2 dir = Vector2.Normalize(point1 - point2);
Vector2 normal = new Vector2(dir.Y, -dir.X);
if (cell != null && Vector2.Dot(normal, Vector2.Normalize(Center - cell.Center)) < 0)
{
return null;
normal = -normal;
}
return normal;
}
}