Use CellLayers for ResourceLayer.

This commit is contained in:
Paul Chote
2014-05-17 01:09:42 +12:00
parent 5a00757eab
commit 295af5741f
2 changed files with 79 additions and 87 deletions

View File

@@ -22,89 +22,78 @@ namespace OpenRA.Traits
static readonly CellContents EmptyCell = new CellContents(); static readonly CellContents EmptyCell = new CellContents();
World world; World world;
protected CellContents[,] content; protected CellLayer<CellContents> content;
protected CellContents[,] render; protected CellLayer<CellContents> render;
List<CPos> dirty; List<CPos> dirty;
public void Render(WorldRenderer wr) public void Render(WorldRenderer wr)
{ {
var clip = wr.Viewport.CellBounds; foreach (var cell in wr.Viewport.VisibleCells)
for (var x = clip.Left; x < clip.Right; x++)
{ {
for (var y = clip.Top; y < clip.Bottom; y++) if (world.ShroudObscures(cell))
{ continue;
var pos = new CPos(x, y);
if (world.ShroudObscures(pos))
continue;
var c = render[x, y]; var c = render[cell];
if (c.Sprite != null) if (c.Sprite != null)
new SpriteRenderable(c.Sprite, pos.CenterPosition, new SpriteRenderable(c.Sprite, cell.CenterPosition,
WVec.Zero, -511, c.Type.Palette, 1f, true).Render(wr); WVec.Zero, -511, c.Type.Palette, 1f, true).Render(wr);
}
} }
} }
int GetAdjacentCellsWith(ResourceType t, int i, int j) int GetAdjacentCellsWith(ResourceType t, CPos cell)
{ {
var sum = 0; var sum = 0;
for (var u = -1; u < 2; u++) for (var u = -1; u < 2; u++)
for (var v = -1; v < 2; v++) for (var v = -1; v < 2; v++)
if (content[i + u, j + v].Type == t) if (content[cell + new CVec(u, v)].Type == t)
++sum; ++sum;
return sum; return sum;
} }
public void WorldLoaded(World w, WorldRenderer wr) public void WorldLoaded(World w, WorldRenderer wr)
{ {
this.world = w; this.world = w;
content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y]; content = new CellLayer<CellContents>(w.Map);
render = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y]; render = new CellLayer<CellContents>(w.Map);
dirty = new List<CPos>(); dirty = new List<CPos>();
var resources = w.WorldActor.TraitsImplementing<ResourceType>() var resources = w.WorldActor.TraitsImplementing<ResourceType>()
.ToDictionary(r => r.Info.ResourceType, r => r); .ToDictionary(r => r.Info.ResourceType, r => r);
var map = w.Map; foreach (var cell in w.Map.Cells)
for (var x = map.Bounds.Left; x < map.Bounds.Right; x++)
{ {
for (var y = map.Bounds.Top; y < map.Bounds.Bottom; y++) ResourceType t;
{ if (!resources.TryGetValue(w.Map.MapResources.Value[cell.X, cell.Y].Type, out t))
var cell = new CPos(x, y); continue;
ResourceType t;
if (!resources.TryGetValue(w.Map.MapResources.Value[x, y].Type, out t))
continue;
if (!AllowResourceAt(t, cell)) if (!AllowResourceAt(t, cell))
continue; continue;
content[x, y] = CreateResourceCell(t, cell); content[cell] = CreateResourceCell(t, cell);
}
} }
// Set initial density based on the number of neighboring resources // Set initial density based on the number of neighboring resources
for (var x = map.Bounds.Left; x < map.Bounds.Right; x++) foreach (var cell in w.Map.Cells)
{ {
for (var y = map.Bounds.Top; y < map.Bounds.Bottom; y++) var type = content[cell].Type;
if (type != null)
{ {
var type = content[x, y].Type; // Adjacent includes the current cell, so is always >= 1
if (type != null) var adjacent = GetAdjacentCellsWith(type, cell);
{ var density = int2.Lerp(0, type.Info.MaxDensity, adjacent, 9);
// Adjacent includes the current cell, so is always >= 1 var temp = content[cell];
var adjacent = GetAdjacentCellsWith(type, x, y); temp.Density = Math.Max(density, 1);
var density = int2.Lerp(0, type.Info.MaxDensity, adjacent, 9);
content[x, y].Density = Math.Max(density, 1);
render[x, y] = content[x, y]; render[cell] = content[cell] = temp;
UpdateRenderedSprite(new CPos(x, y)); UpdateRenderedSprite(cell);
}
} }
} }
} }
protected virtual void UpdateRenderedSprite(CPos p) protected virtual void UpdateRenderedSprite(CPos cell)
{ {
var t = render[p.X, p.Y]; var t = render[cell];
if (t.Density > 0) if (t.Density > 0)
{ {
var sprites = t.Type.Variants[t.Variant]; var sprites = t.Type.Variants[t.Variant];
@@ -114,7 +103,7 @@ namespace OpenRA.Traits
else else
t.Sprite = null; t.Sprite = null;
render[p.X, p.Y] = t; render[cell] = t;
} }
protected virtual string ChooseRandomVariant(ResourceType t) protected virtual string ChooseRandomVariant(ResourceType t)
@@ -129,7 +118,7 @@ namespace OpenRA.Traits
{ {
if (!self.World.FogObscures(c)) if (!self.World.FogObscures(c))
{ {
render[c.X, c.Y] = content[c.X, c.Y]; render[c] = content[c];
UpdateRenderedSprite(c); UpdateRenderedSprite(c);
remove.Add(c); remove.Add(c);
} }
@@ -139,15 +128,15 @@ namespace OpenRA.Traits
dirty.Remove(r); dirty.Remove(r);
} }
public bool AllowResourceAt(ResourceType rt, CPos a) public bool AllowResourceAt(ResourceType rt, CPos cell)
{ {
if (!world.Map.IsInMap(a.X, a.Y)) if (!world.Map.IsInMap(cell))
return false; return false;
if (!rt.Info.AllowedTerrainTypes.Contains(world.Map.GetTerrainInfo(a).Type)) if (!rt.Info.AllowedTerrainTypes.Contains(world.Map.GetTerrainInfo(cell).Type))
return false; return false;
if (!rt.Info.AllowUnderActors && world.ActorMap.AnyUnitsAt(a)) if (!rt.Info.AllowUnderActors && world.ActorMap.AnyUnitsAt(cell))
return false; return false;
return true; return true;
@@ -160,9 +149,10 @@ namespace OpenRA.Traits
|| (currentResourceType == null && AllowResourceAt(newResourceType, cell)); || (currentResourceType == null && AllowResourceAt(newResourceType, cell));
} }
CellContents CreateResourceCell(ResourceType t, CPos p) CellContents CreateResourceCell(ResourceType t, CPos cell)
{ {
world.Map.CustomTerrain[p.X, p.Y] = world.TileSet.GetTerrainIndex(t.Info.TerrainType); world.Map.CustomTerrain[cell.X, cell.Y] = world.TileSet.GetTerrainIndex(t.Info.TerrainType);
return new CellContents return new CellContents
{ {
Type = t, Type = t,
@@ -172,7 +162,7 @@ namespace OpenRA.Traits
public void AddResource(ResourceType t, CPos p, int n) public void AddResource(ResourceType t, CPos p, int n)
{ {
var cell = content[p.X, p.Y]; var cell = content[p];
if (cell.Type == null) if (cell.Type == null)
cell = CreateResourceCell(t, p); cell = CreateResourceCell(t, p);
@@ -180,58 +170,60 @@ namespace OpenRA.Traits
return; return;
cell.Density = Math.Min(cell.Type.Info.MaxDensity, cell.Density + n); cell.Density = Math.Min(cell.Type.Info.MaxDensity, cell.Density + n);
content[p.X, p.Y] = cell; content[p] = cell;
if (!dirty.Contains(p)) if (!dirty.Contains(p))
dirty.Add(p); dirty.Add(p);
} }
public bool IsFull(CPos c) public bool IsFull(CPos cell)
{ {
return content[c.X, c.Y].Density == content[c.X, c.Y].Type.Info.MaxDensity; return content[cell].Density == content[cell].Type.Info.MaxDensity;
} }
public ResourceType Harvest(CPos p) public ResourceType Harvest(CPos cell)
{ {
var type = content[p.X, p.Y].Type; var c = content[cell];
if (type == null) if (c.Type == null)
return null; return null;
if (--content[p.X, p.Y].Density < 0) if (--c.Density < 0)
{ {
content[p.X, p.Y] = EmptyCell; content[cell] = EmptyCell;
world.Map.CustomTerrain[p.X, p.Y] = -1; world.Map.CustomTerrain[cell.X, cell.Y] = -1;
} }
else
content[cell] = c;
if (!dirty.Contains(p)) if (!dirty.Contains(cell))
dirty.Add(p); dirty.Add(cell);
return type; return c.Type;
} }
public void Destroy(CPos p) public void Destroy(CPos cell)
{ {
// Don't break other users of CustomTerrain if there are no resources // Don't break other users of CustomTerrain if there are no resources
if (content[p.X, p.Y].Type == null) if (content[cell].Type == null)
return; return;
// Clear cell // Clear cell
content[p.X, p.Y] = EmptyCell; content[cell] = EmptyCell;
world.Map.CustomTerrain[p.X, p.Y] = -1; world.Map.CustomTerrain[cell.X, cell.Y] = -1;
if (!dirty.Contains(p)) if (!dirty.Contains(cell))
dirty.Add(p); dirty.Add(cell);
} }
public ResourceType GetResource(CPos p) { return content[p.X, p.Y].Type; } public ResourceType GetResource(CPos cell) { return content[cell].Type; }
public ResourceType GetRenderedResource(CPos p) { return render[p.X, p.Y].Type; } public ResourceType GetRenderedResource(CPos cell) { return render[cell].Type; }
public int GetResourceDensity(CPos p) { return content[p.X, p.Y].Density; } public int GetResourceDensity(CPos cell) { return content[cell].Density; }
public int GetMaxResourceDensity(CPos p) public int GetMaxResourceDensity(CPos cell)
{ {
if (content[p.X, p.Y].Type == null) if (content[cell].Type == null)
return 0; return 0;
return content[p.X, p.Y].Type.Info.MaxDensity; return content[cell].Type.Info.MaxDensity;
} }
public struct CellContents public struct CellContents

View File

@@ -97,28 +97,28 @@ namespace OpenRA.Traits
ClearSides FindClearSides(ResourceType t, CPos p) ClearSides FindClearSides(ResourceType t, CPos p)
{ {
var ret = ClearSides.None; var ret = ClearSides.None;
if (render[p.X, p.Y - 1].Type != t) if (render[p + new CVec(0, -1)].Type != t)
ret |= ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight; ret |= ClearSides.Top | ClearSides.TopLeft | ClearSides.TopRight;
if (render[p.X - 1, p.Y].Type != t) if (render[p + new CVec(-1, 0)].Type != t)
ret |= ClearSides.Left | ClearSides.TopLeft | ClearSides.BottomLeft; ret |= ClearSides.Left | ClearSides.TopLeft | ClearSides.BottomLeft;
if (render[p.X + 1, p.Y].Type != t) if (render[p + new CVec(1, 0)].Type != t)
ret |= ClearSides.Right | ClearSides.TopRight | ClearSides.BottomRight; ret |= ClearSides.Right | ClearSides.TopRight | ClearSides.BottomRight;
if (render[p.X, p.Y + 1].Type != t) if (render[p + new CVec(0, 1)].Type != t)
ret |= ClearSides.Bottom | ClearSides.BottomLeft | ClearSides.BottomRight; ret |= ClearSides.Bottom | ClearSides.BottomLeft | ClearSides.BottomRight;
if (render[p.X - 1, p.Y - 1].Type != t) if (render[p + new CVec(-1, -1)].Type != t)
ret |= ClearSides.TopLeft; ret |= ClearSides.TopLeft;
if (render[p.X + 1, p.Y - 1].Type != t) if (render[p + new CVec(1, -1)].Type != t)
ret |= ClearSides.TopRight; ret |= ClearSides.TopRight;
if (render[p.X - 1, p.Y + 1].Type != t) if (render[p + new CVec(-1, 1)].Type != t)
ret |= ClearSides.BottomLeft; ret |= ClearSides.BottomLeft;
if (render[p.X + 1, p.Y + 1].Type != t) if (render[p + new CVec(1, 1)].Type != t)
ret |= ClearSides.BottomRight; ret |= ClearSides.BottomRight;
return ret; return ret;
@@ -126,7 +126,7 @@ namespace OpenRA.Traits
void UpdateRenderedTileInner(CPos p) void UpdateRenderedTileInner(CPos p)
{ {
var t = render[p.X, p.Y]; var t = render[p];
if (t.Density > 0) if (t.Density > 0)
{ {
var clear = FindClearSides(t.Type, p); var clear = FindClearSides(t.Type, p);
@@ -146,7 +146,7 @@ namespace OpenRA.Traits
else else
t.Sprite = null; t.Sprite = null;
render[p.X, p.Y] = t; render[p] = t;
} }
protected override void UpdateRenderedSprite(CPos p) protected override void UpdateRenderedSprite(CPos p)