add TileMap

This commit is contained in:
Gered 2013-08-25 18:49:14 -04:00
parent c9938b7805
commit e1b5cb9c0c
4 changed files with 274 additions and 6 deletions

View file

@ -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" />

View file

@ -0,0 +1,10 @@
using System;
namespace Blarg.GameFramework.TileMap.Lighting
{
public interface ITileMapLighter
{
void Light(TileMap tileMap);
}
}

View file

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

View file

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