add TileMap
This commit is contained in:
parent
c9938b7805
commit
e1b5cb9c0c
|
@ -204,6 +204,7 @@
|
|||
<Compile Include="TileMap\TileMap.cs" />
|
||||
<Compile Include="TileMap\TileChunk.cs" />
|
||||
<Compile Include="TileMap\ChunkVertexGenerator.cs" />
|
||||
<Compile Include="TileMap\Lighting\ITileMapLighter.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
@ -230,6 +231,7 @@
|
|||
<Folder Include="Graphics\Atlas\" />
|
||||
<Folder Include="TileMap\" />
|
||||
<Folder Include="TileMap\Meshes\" />
|
||||
<Folder Include="TileMap\Lighting\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Fonts\Vera.ttf" />
|
||||
|
|
10
Blarg.GameFramework/TileMap/Lighting/ITileMapLighter.cs
Normal file
10
Blarg.GameFramework/TileMap/Lighting/ITileMapLighter.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
namespace Blarg.GameFramework.TileMap.Lighting
|
||||
{
|
||||
public interface ITileMapLighter
|
||||
{
|
||||
void Light(TileMap tileMap);
|
||||
}
|
||||
}
|
||||
|
|
@ -101,6 +101,7 @@ namespace Blarg.GameFramework.TileMap
|
|||
_height = height;
|
||||
_depth = depth;
|
||||
_position = new Vector3(x, y, z);
|
||||
_bounds = new BoundingBox();
|
||||
_bounds.Min.Set(x, y, z);
|
||||
_bounds.Max.Set(x + width, y + height, z + depth);
|
||||
|
||||
|
@ -158,6 +159,10 @@ namespace Blarg.GameFramework.TileMap
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Mesh != null)
|
||||
Mesh.Dispose();
|
||||
if (AlphaMesh != null)
|
||||
AlphaMesh.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,272 @@
|
|||
using System;
|
||||
using Blarg.GameFramework.TileMap.Lighting;
|
||||
using Blarg.GameFramework.TileMap.Meshes;
|
||||
|
||||
namespace Blarg.GameFramework.TileMap
|
||||
{
|
||||
public class TileMap
|
||||
public class TileMap : TileContainer, IDisposable
|
||||
{
|
||||
public TileMap()
|
||||
readonly Vector3 _position;
|
||||
readonly BoundingBox _bounds;
|
||||
|
||||
public readonly TileChunk[] Chunks;
|
||||
public readonly TileMeshCollection TileMeshes;
|
||||
public readonly ChunkVertexGenerator VertexGenerator;
|
||||
public readonly ITileMapLighter Lighter;
|
||||
public byte AmbientLightValue;
|
||||
public byte SkyLightValue;
|
||||
|
||||
public readonly int ChunkWidth;
|
||||
public readonly int ChunkHeight;
|
||||
public readonly int ChunkDepth;
|
||||
public readonly int WidthInChunks;
|
||||
public readonly int HeightInChunks;
|
||||
public readonly int DepthInChunks;
|
||||
|
||||
public override int Width
|
||||
{
|
||||
get { return ChunkWidth * WidthInChunks; }
|
||||
}
|
||||
|
||||
public Tile Get(int x, int y, int z)
|
||||
public override int Height
|
||||
{
|
||||
return null;
|
||||
get { return ChunkHeight * HeightInChunks; }
|
||||
}
|
||||
|
||||
public bool IsWithinBounds(int x, int y, int z)
|
||||
public override int Depth
|
||||
{
|
||||
return false;
|
||||
get { return ChunkDepth * DepthInChunks; }
|
||||
}
|
||||
|
||||
public override int MinX
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override int MinY
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override int MinZ
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override int MaxX
|
||||
{
|
||||
get { return Width - 1; }
|
||||
}
|
||||
|
||||
public override int MaxY
|
||||
{
|
||||
get { return Height - 1; }
|
||||
}
|
||||
|
||||
public override int MaxZ
|
||||
{
|
||||
get { return Depth - 1; }
|
||||
}
|
||||
|
||||
public override Vector3 Position
|
||||
{
|
||||
get { return _position; }
|
||||
}
|
||||
|
||||
public override BoundingBox Bounds
|
||||
{
|
||||
get { return _bounds; }
|
||||
}
|
||||
|
||||
public TileMap(int chunkWidth, int chunkHeight, int chunkDepth,
|
||||
int widthInChunks, int heightInChunks, int depthInChunks,
|
||||
TileMeshCollection tileMeshes,
|
||||
ChunkVertexGenerator vertexGenerator,
|
||||
ITileMapLighter lighter
|
||||
)
|
||||
{
|
||||
if (tileMeshes == null)
|
||||
throw new ArgumentNullException("tileMeshes");
|
||||
if (vertexGenerator == null)
|
||||
throw new ArgumentNullException("vertexGenerator");
|
||||
|
||||
TileMeshes = tileMeshes;
|
||||
VertexGenerator = vertexGenerator;
|
||||
Lighter = lighter;
|
||||
ChunkWidth = chunkWidth;
|
||||
ChunkHeight = chunkHeight;
|
||||
ChunkDepth = chunkDepth;
|
||||
WidthInChunks = widthInChunks;
|
||||
HeightInChunks = heightInChunks;
|
||||
DepthInChunks = depthInChunks;
|
||||
|
||||
AmbientLightValue = 0;
|
||||
SkyLightValue = Tile.LIGHT_VALUE_SKY;
|
||||
|
||||
int numChunks = widthInChunks * heightInChunks * depthInChunks;
|
||||
Chunks = new TileChunk[numChunks];
|
||||
|
||||
for (int y = 0; y < heightInChunks; ++y)
|
||||
{
|
||||
for (int z = 0; z < depthInChunks; ++z)
|
||||
{
|
||||
for (int x = 0; x < widthInChunks; ++x)
|
||||
{
|
||||
TileChunk chunk = new TileChunk(
|
||||
x * chunkWidth,
|
||||
y * chunkHeight,
|
||||
z * chunkDepth,
|
||||
chunkWidth,
|
||||
chunkHeight,
|
||||
chunkDepth,
|
||||
this
|
||||
);
|
||||
|
||||
int index = GetChunkIndex(x, y, z);
|
||||
Chunks[index] = chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_position = Vector3.Zero;
|
||||
_bounds = new BoundingBox();
|
||||
_bounds.Min = Vector3.Zero;
|
||||
_bounds.Max.Set(Width, Height, Depth);
|
||||
}
|
||||
|
||||
public void updateVertices()
|
||||
{
|
||||
for (int i = 0; i < Chunks.Length; ++i)
|
||||
UpdateChunkVertices(Chunks[i]);
|
||||
}
|
||||
|
||||
private void UpdateChunkVertices(TileChunk chunk)
|
||||
{
|
||||
chunk.UpdateVertices(VertexGenerator);
|
||||
}
|
||||
|
||||
public void UpdateLighting()
|
||||
{
|
||||
if (Lighter != null)
|
||||
Lighter.Light(this);
|
||||
}
|
||||
|
||||
public bool GetOverlappedChunks(BoundingBox box, Point3 min, Point3 max)
|
||||
{
|
||||
// make sure the given box actually intersects with the map in the first place
|
||||
var bounds = _bounds;
|
||||
if (!IntersectionTester.Test(ref bounds, ref box))
|
||||
return false;
|
||||
|
||||
// convert to tile coords. this is in "tilemap space" which is how we want it
|
||||
// HACK: ceil() calls and "-1"'s keep us from picking up too many/too few
|
||||
// blocks. these were arrived at through observation
|
||||
int minX = (int)box.Min.X;
|
||||
int minY = (int)box.Min.Y;
|
||||
int minZ = (int)box.Min.Z;
|
||||
int maxX = (int)Math.Ceiling(box.Max.X);
|
||||
int maxY = (int)Math.Ceiling(box.Max.Y - 1.0f);
|
||||
int maxZ = (int)Math.Ceiling(box.Max.Z);
|
||||
|
||||
// now convert to chunk coords
|
||||
int minChunkX = minX / ChunkWidth;
|
||||
int minChunkY = minY / ChunkHeight;
|
||||
int minChunkZ = minZ / ChunkDepth;
|
||||
int maxChunkX = maxX / ChunkWidth;
|
||||
int maxChunkY = maxY / ChunkHeight;
|
||||
int maxChunkZ = maxZ / ChunkDepth;
|
||||
|
||||
// trim off the excess bounds so that we end up with a min-to-max area
|
||||
// that is completely within the chunk bounds of the map
|
||||
// HACK: "-1"'s keep us from picking up too many chunks. these were arrived
|
||||
// at through observation
|
||||
minChunkX = MathHelpers.Clamp(minChunkX, 0, WidthInChunks);
|
||||
minChunkY = MathHelpers.Clamp(minChunkY, 0, (HeightInChunks - 1));
|
||||
minChunkZ = MathHelpers.Clamp(minChunkZ, 0, DepthInChunks);
|
||||
maxChunkX = MathHelpers.Clamp(maxChunkX, 0, WidthInChunks);
|
||||
maxChunkY = MathHelpers.Clamp(maxChunkY, 0, (HeightInChunks - 1));
|
||||
maxChunkZ = MathHelpers.Clamp(maxChunkZ, 0, DepthInChunks);
|
||||
|
||||
// return the leftover area
|
||||
min.X = minChunkX;
|
||||
min.Y = minChunkY;
|
||||
min.Z = minChunkZ;
|
||||
max.X = maxChunkX;
|
||||
max.Y = maxChunkY;
|
||||
max.Z = maxChunkZ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Tile Get(int x, int y, int z)
|
||||
{
|
||||
var chunk = GetChunkContaining(x, y, z);
|
||||
int chunkX = x - chunk.MinX;
|
||||
int chunkY = y - chunk.MinY;
|
||||
int chunkZ = z - chunk.MinZ;
|
||||
|
||||
return chunk.Get(chunkX, chunkY, chunkZ);
|
||||
}
|
||||
|
||||
public override Tile GetSafe(int x, int y, int z)
|
||||
{
|
||||
if (!IsWithinBounds(x, y, z))
|
||||
return null;
|
||||
else
|
||||
return Get(x, y, z);
|
||||
}
|
||||
|
||||
public TileChunk GetChunk(int chunkX, int chunkY, int chunkZ)
|
||||
{
|
||||
int index = GetChunkIndex(chunkX, chunkY, chunkZ);
|
||||
return Chunks[index];
|
||||
}
|
||||
|
||||
public TileChunk GetChunkSafe(int chunkX, int chunkY, int chunkZ)
|
||||
{
|
||||
if ((chunkX >= WidthInChunks) ||
|
||||
(chunkY >= HeightInChunks) ||
|
||||
(chunkZ >= DepthInChunks)
|
||||
)
|
||||
return null;
|
||||
else
|
||||
return GetChunk(chunkX, chunkY, chunkZ);
|
||||
}
|
||||
|
||||
public TileChunk GetChunkNextTo(TileChunk chunk, int chunkOffsetX, int chunkOffsetY, int chunkOffsetZ)
|
||||
{
|
||||
int checkX = chunk.MinX + chunkOffsetX;
|
||||
int checkY = chunk.MinY + chunkOffsetY;
|
||||
int checkZ = chunk.MinZ + chunkOffsetZ;
|
||||
|
||||
if ((checkX < 0 || checkX >= WidthInChunks) ||
|
||||
(checkY < 0 || checkY >= HeightInChunks) ||
|
||||
(checkZ < 0 || checkZ >= DepthInChunks)
|
||||
)
|
||||
return null;
|
||||
else
|
||||
return GetChunk(checkX, checkY, checkZ);
|
||||
}
|
||||
|
||||
public TileChunk GetChunkContaining(int x, int y, int z) {
|
||||
int index = GetChunkIndexAt(x, y, z);
|
||||
return Chunks[index];
|
||||
}
|
||||
|
||||
private int GetChunkIndexAt(int x, int y, int z)
|
||||
{
|
||||
return GetChunkIndex(x / ChunkWidth, y / ChunkHeight, z / ChunkDepth);
|
||||
}
|
||||
|
||||
private int GetChunkIndex(int chunkX, int chunkY, int chunkZ)
|
||||
{
|
||||
return (chunkY * WidthInChunks * DepthInChunks) + (chunkZ * WidthInChunks) + chunkX;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
for (int i = 0; i < Chunks.Length; ++i)
|
||||
Chunks[i].Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue