public override void Draw(GraphicsDevice device, WorldState world)
{
var timer = new System.Diagnostics.Stopwatch();
timer.Start();
if (WallZBuffers == null) WallZBuffers = TextureGenerator.GetWallZBuffer(device);
var pxOffset = world.WorldSpace.GetScreenOffset();
var wallContent = Content.Content.Get().WorldWalls;
var floorContent = Content.Content.Get().WorldFloors;
//draw walls
for (sbyte level = 1; level <= world.Level; level++)
{
int off = 0;
bool canCut = !(level < world.Level);
GenerateWallData(blueprint.Walls[level-1], blueprint.WallsAt[level-1], canCut);
var rMap = blueprint.RoomMap[level - 1];
for (short y = 0; y < blueprint.Height; y++)
{ //ill decide on a reasonable system for components when it's finished ok pls :(
for (short x = 0; x < blueprint.Height; x++)
{
TileRoom = (rMap == null)?1:rMap[x + y * blueprint.Width];
var comp = blueprint.GetWall(x, y, level);
if (comp.Segments != 0)
{
comp = RotateWall(world.Rotation, comp, x, y, level);
var tilePosition = new Vector3(x, y, (level-1) * 2.95f);
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition));
world._2D.OffsetTile(tilePosition);
var myCuts = Cuts[off];
var cDown = canCut && WallsDownAt(x, y);
if ((byte)comp.Segments < 16) myCuts = RotateCuts(world.Rotation, myCuts, x, y);
else if ((int)world.Rotation > 1) //for diagonals, just flip cuts on two furthest rotations
{
if (myCuts.TLCut == WallCut.DownRightUpLeft) myCuts.TLCut = WallCut.DownLeftUpRight;
else if (myCuts.TLCut == WallCut.DownLeftUpRight) myCuts.TLCut = WallCut.DownRightUpLeft;
if (myCuts.TRCut == WallCut.DownRightUpLeft) myCuts.TRCut = WallCut.DownLeftUpRight;
else if (myCuts.TRCut == WallCut.DownLeftUpRight) myCuts.TRCut = WallCut.DownRightUpLeft;
}
if ((comp.Segments & WallSegments.TopLeft) == WallSegments.TopLeft && !(myCuts.TLCut > 0 && comp.TopLeftDoor))
{
//draw top left and top right relative to this rotation
var tlPattern = GetPattern(comp.TopLeftPattern);
ushort styleID = 1;
ushort overlayID = 0;
bool down = false;
switch (myCuts.TLCut)
{
case WallCut.Down:
styleID = comp.TopLeftStyle;
down = true; break;
case WallCut.DownLeftUpRight:
styleID = 7;
overlayID = 252; break;
case WallCut.DownRightUpLeft:
styleID = 8;
overlayID = 253; break;
default:
if (comp.TopLeftStyle != 1) styleID = comp.TopLeftStyle;
else if (comp.ObjSetTLStyle != 0) styleID = comp.ObjSetTLStyle; //use custom style set by object if no cut
else styleID = 1;
break;
}
var tlStyle = GetStyle(styleID);
var _Sprite = GetWallSprite(tlPattern, tlStyle, 0, down, world);
if (_Sprite.Pixel != null)
{
world._2D.Draw(_Sprite);
//draw overlay if exists
if (overlayID != 0) world._2D.Draw(GetWallSprite(GetPattern(overlayID), null, 0, down, world));
var contOff = tilePosition + RotateOffset(world.Rotation, new Vector3(0, -1, 0));
if (comp.TopLeftThick)
{
//check far side of wall for continuation. if there is none, round this part off
if (!comp.TopRightThick && OffsetValid(contOff, blueprint))
{
var comp2 = RotateWall(world.Rotation, blueprint.GetWall((short)(contOff.X), (short)(contOff.Y), level), (short)(contOff.X), (short)(contOff.Y), level);
if (!comp2.TopLeftThick)
{
_Sprite = CopySprite(world, _Sprite);
tlStyle = GetStyle(comp.TopLeftStyle); //return to normal if cutaway
var tilePosition2 = contOff;
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition2));
world._2D.OffsetTile(tilePosition2);
int newWidth = 0;
bool downAtCont = canCut && WallsDownAt((short)(contOff.X), (short)(contOff.Y));
SPR mask = null;
switch (world.Zoom)
{
case WorldZoom.Far:
newWidth = 3;
mask = downAtCont ? tlStyle.WallsDownFar : tlStyle.WallsUpFar;
break;
case WorldZoom.Medium:
newWidth = 6;
mask = downAtCont ? tlStyle.WallsDownMedium : tlStyle.WallsUpMedium;
break;
case WorldZoom.Near:
newWidth = 12;
mask = downAtCont ? tlStyle.WallsDownNear : tlStyle.WallsUpNear;
break;
}
if (mask != null) _Sprite.Mask = world._2D.GetTexture(mask.Frames[0]);
if (x > 0 && (blueprint.GetWall((short)(x - 1), (short)(y - 1), level).Segments & WallSegments.VerticalDiag) == WallSegments.VerticalDiag) newWidth = (newWidth * 2) / 3;
//if there is a diagonal behind the extension, make it a bit shorter.
_Sprite.SrcRect.Width = newWidth;
_Sprite.DestRect.Width = newWidth;
world._2D.Draw(_Sprite);
}
}
//check close side of wall for continuation
contOff = tilePosition + RotateOffset(world.Rotation, new Vector3(0, 1, 0)); //so we can check the most things with the least impact
var contOff2 = tilePosition + RotateOffset(world.Rotation, new Vector3(-1, 1, 0)); //last check, unfortunately required
if (OffsetValid(contOff, blueprint) && OffsetValid(contOff2, blueprint))
{
var comp2 = RotateWall(world.Rotation, blueprint.GetWall((short)(contOff.X), (short)(contOff.Y), level), (short)(contOff.X), (short)(contOff.Y), level);
if (!comp2.TopLeftThick && !comp2.TopRightThick)
{
var comp3 = RotateWall(world.Rotation, blueprint.GetWall((short)(contOff2.X), (short)(contOff2.Y), level), (short)(contOff2.X), (short)(contOff2.Y), level);
if (!comp3.TopRightThick)
{
_Sprite = GetWallSprite(tlPattern, tlStyle, 1, down, world);
var tilePosition2 = tilePosition + RotateOffset(world.Rotation, new Vector3(-1, 1, 0));
bool downAtCont = canCut && WallsDownAt((int)tilePosition.X, (int)tilePosition.Y) && styleID != 8;
tlStyle = GetStyle(comp.TopLeftStyle);
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition2));
world._2D.OffsetTile(tilePosition2);
int newWidth = 0;
SPR mask = null;
switch (world.Zoom)
{
case WorldZoom.Far:
newWidth = 3;
mask = downAtCont ? tlStyle.WallsDownFar : tlStyle.WallsUpFar;
break;
case WorldZoom.Medium:
newWidth = 6;
mask = downAtCont ? tlStyle.WallsDownMedium : tlStyle.WallsUpMedium;
break;
case WorldZoom.Near:
newWidth = 12;
mask = downAtCont ? tlStyle.WallsDownNear : tlStyle.WallsUpNear;
break;
}
if (mask != null) _Sprite.Mask = world._2D.GetTexture(mask.Frames[1]);
_Sprite.SrcRect.X += _Sprite.SrcRect.Width - newWidth;
_Sprite.DestRect.X += _Sprite.DestRect.Width - newWidth;
_Sprite.SrcRect.Width = newWidth;
_Sprite.DestRect.Width = newWidth;
world._2D.Draw(_Sprite);
}
}
}
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition));
world._2D.OffsetTile(tilePosition);
}
}
}
//top right
if ((comp.Segments & WallSegments.TopRight) == WallSegments.TopRight && !(myCuts.TRCut > 0 && comp.TopRightDoor))
{
var trPattern = GetPattern(comp.TopRightPattern);
ushort styleID = 1;
ushort overlayID = 0;
bool down = false;
switch (myCuts.TRCut)
{
case WallCut.Down:
styleID = comp.TopRightStyle;
down = true; break;
case WallCut.DownLeftUpRight:
styleID = 7;
overlayID = 252; break;
case WallCut.DownRightUpLeft:
styleID = 8;
overlayID = 253; break;
default:
if (comp.TopRightStyle != 1) styleID = comp.TopRightStyle;
else if (comp.ObjSetTRStyle != 0) styleID = comp.ObjSetTRStyle; //use custom style set by object if no cut
else styleID = 1;
break;
}
var trStyle = GetStyle(styleID);
var _Sprite = GetWallSprite(trPattern, trStyle, 1, down, world);
if (_Sprite.Pixel != null)
{
world._2D.Draw(_Sprite);
if (overlayID != 0) world._2D.Draw(GetWallSprite(GetPattern(overlayID), null, 1, down, world));
var contOff = tilePosition + RotateOffset(world.Rotation, new Vector3(-1, 0, 0));
if (comp.TopRightThick)
{
//check far side of wall for continuation. if there is none, round this part off
if (!comp.TopLeftThick && OffsetValid(contOff, blueprint))
{
var comp2 = RotateWall(world.Rotation, blueprint.GetWall((short)(contOff.X), (short)(contOff.Y), level), (short)(contOff.X), (short)(contOff.Y), level);
if (!comp2.TopRightThick)
{
_Sprite = CopySprite(world, _Sprite);
trStyle = GetStyle(comp.TopRightStyle); //return to normal if cutaway
var tilePosition2 = contOff;
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition2));
world._2D.OffsetTile(tilePosition2);
int newWidth = 0;
bool downAtCont = canCut && WallsDownAt((short)(contOff.X), (short)(contOff.Y));
SPR mask = null;
switch (world.Zoom)
{
case WorldZoom.Far:
newWidth = 3;
mask = downAtCont ? trStyle.WallsDownFar : trStyle.WallsUpFar;
break;
case WorldZoom.Medium:
newWidth = 6;
mask = downAtCont ? trStyle.WallsDownMedium : trStyle.WallsUpMedium;
break;
case WorldZoom.Near:
newWidth = 12;
mask = downAtCont ? trStyle.WallsDownNear : trStyle.WallsUpNear;
break;
}
if (mask != null) _Sprite.Mask = world._2D.GetTexture(mask.Frames[1]);
if (y > 0 && (blueprint.GetWall((short)(x - 1), (short)(y - 1), level).Segments & WallSegments.VerticalDiag) == WallSegments.VerticalDiag) newWidth = (newWidth * 2) / 3;
//if there is a diagonal behind the extension, make it a bit shorter.
_Sprite.SrcRect.X += _Sprite.SrcRect.Width - newWidth;
_Sprite.DestRect.X += _Sprite.DestRect.Width - newWidth;
_Sprite.SrcRect.Width = newWidth;
_Sprite.DestRect.Width = newWidth;
world._2D.Draw(_Sprite);
}
}
//check close side of wall for continuation
contOff = tilePosition + RotateOffset(world.Rotation, new Vector3(1, 0, 0)); //so we can check the most things with the least impact
var contOff2 = tilePosition + RotateOffset(world.Rotation, new Vector3(1, -1, 0)); //last check, unfortunately required
if (OffsetValid(contOff, blueprint) && OffsetValid(contOff2, blueprint))
{
var comp2 = RotateWall(world.Rotation, blueprint.GetWall((short)(contOff.X), (short)(contOff.Y), level), (short)(contOff.X), (short)(contOff.Y), level);
if (!comp2.TopLeftThick && !comp2.TopRightThick)
{
var comp3 = RotateWall(world.Rotation, blueprint.GetWall((short)(contOff2.X), (short)(contOff2.Y), level), (short)(contOff2.X), (short)(contOff2.Y), level);
if (!comp3.TopLeftThick)
{
_Sprite = GetWallSprite(trPattern, trStyle, 0, down, world);
var tilePosition2 = tilePosition + RotateOffset(world.Rotation, new Vector3(1, -1, 0));
bool downAtCont = canCut && WallsDownAt((int)tilePosition.X, (int)tilePosition.Y) && styleID != 8;
trStyle = GetStyle(comp.TopRightStyle);
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition2));
world._2D.OffsetTile(tilePosition2);
int newWidth = 0;
SPR mask = null;
switch (world.Zoom)
{
case WorldZoom.Far:
newWidth = 3;
mask = downAtCont ? trStyle.WallsDownFar : trStyle.WallsUpFar;
break;
case WorldZoom.Medium:
newWidth = 6;
mask = downAtCont ? trStyle.WallsDownMedium : trStyle.WallsUpMedium;
break;
case WorldZoom.Near:
newWidth = 12;
mask = downAtCont ? trStyle.WallsDownNear : trStyle.WallsUpNear;
break;
}
if (mask != null) _Sprite.Mask = world._2D.GetTexture(mask.Frames[0]);
_Sprite.SrcRect.Width = newWidth;
_Sprite.DestRect.Width = newWidth;
world._2D.Draw(_Sprite);
}
}
}
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition));
world._2D.OffsetTile(tilePosition);
}
}
}
//horizontal diag
if (comp.Segments == WallSegments.HorizontalDiag)
{
var trPattern = GetPattern(comp.BottomRightPattern); //bottom left is facing other way.
ushort styleID = 1;
ushort overlayID = 0;
bool down = false;
switch (myCuts.TRCut)
{
case WallCut.Down:
styleID = comp.TopRightStyle;
down = true; break;
case WallCut.DownLeftUpRight:
styleID = 7;
overlayID = 252; break;
case WallCut.DownRightUpLeft:
styleID = 8;
overlayID = 253; break;
default:
if (comp.TopRightStyle != 1) styleID = comp.TopRightStyle;
else if (comp.ObjSetTRStyle != 0) styleID = comp.ObjSetTRStyle; //use custom style set by object if no cut
else styleID = 1;
break;
}
var trStyle = GetStyle(styleID);
int roomSide = 16-((((int)world.Rotation+1)/2)%2) * 16;
var _Sprite = GetWallSprite(trPattern, trStyle, 2, down, world);
_Sprite.Room = (ushort)(TileRoom>>roomSide);
if (_Sprite.Pixel != null)
{
world._2D.Draw(_Sprite);
if (overlayID != 0) world._2D.Draw(GetWallSprite(GetPattern(overlayID), null, 2, down, world));
//draw diagonally cut floors
if (comp.TopLeftPattern != 0)
{
var floor = GetFloorSprite(floorContent.Get(comp.TopLeftPattern), 0, world, 3);
floor.Room = (ushort)(TileRoom >> roomSide);
if (floor.Pixel != null) world._2D.Draw(floor);
}
if (comp.TopLeftStyle != 0)
{
var floor = GetFloorSprite(floorContent.Get(comp.TopLeftStyle), 0, world, 2);
floor.Room = (ushort)(TileRoom >> (16-roomSide));
if (floor.Pixel != null) world._2D.Draw(floor);
}
}
}
if (comp.Segments == WallSegments.VerticalDiag)
{
var trPattern = GetPattern(comp.BottomRightPattern); //choose right one here, not sure which is chosen in real game
ushort styleID = 1;
ushort overlayID = 0;
bool down = false;
switch (myCuts.TRCut)
{
case WallCut.Down:
styleID = comp.TopRightStyle;
down = true; break;
case WallCut.DownLeftUpRight:
styleID = 7;
overlayID = 252; break;
case WallCut.DownRightUpLeft:
styleID = 8;
overlayID = 253; break;
default:
if (comp.TopRightStyle != 1) styleID = comp.TopRightStyle;
else if (comp.ObjSetTRStyle != 0) styleID = comp.ObjSetTRStyle; //use custom style set by object if no cut
else styleID = 1;
break;
}
var trStyle = GetStyle(styleID);
int roomSide = ((int)world.Rotation / 2) * 16;
var _Sprite = GetWallSprite(trPattern, trStyle, 3, down, world);
_Sprite.Room = (ushort)(TileRoom>>roomSide);
if (_Sprite.Pixel != null)
{
world._2D.Draw(_Sprite);
if (overlayID != 0) world._2D.Draw(GetWallSprite(GetPattern(overlayID), null, 3, down, world));
//draw diagonally cut floors
if (comp.TopLeftPattern != 0)
{
var floor = GetFloorSprite(floorContent.Get(comp.TopLeftPattern), 0, world, 1);
floor.Room = (ushort)(TileRoom >> roomSide);
if (floor.Pixel != null) world._2D.Draw(floor);
}
if (comp.TopLeftStyle != 0)
{
var floor = GetFloorSprite(floorContent.Get(comp.TopLeftStyle), 0, world, 0);
floor.Room = (ushort)(TileRoom >> (16-roomSide));
if (floor.Pixel != null) world._2D.Draw(floor);
}
}
}
}
//draw junctions (part of this iteration to simplify things)
JunctionFlags flags;
float yOff;
if (UpJunctions[off] == 0)
{
flags = DownJunctions[off];
yOff = 0.3f + (level - 1) * 2.95f; ;
}
else
{
flags = UpJunctions[off];
yOff = level * 2.95f;
}
if (flags > 0 && JunctionMap.ContainsKey(flags)) //there is a junction here! if the junction map contains the unrotated junction, it will contain the rotated junction.
{
flags = RotateJunction(world.Rotation, flags);
var tilePosition = new Vector3(x - 0.5f, y - 0.5f, yOff); //2.95 for walls up, 0.3 for walls down
world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition));
world._2D.OffsetTile(tilePosition);
var _Sprite = world._2D.NewSprite(_2DBatchRenderMode.Z_BUFFER);
var Junctions = wallContent.Junctions;
SPR sprite = null;
switch (world.Zoom)
{
case WorldZoom.Far:
sprite = Junctions.Far;
_Sprite.DestRect = JUNCDEST_FAR;
_Sprite.Depth = WallZBuffers[20];
break;
case WorldZoom.Medium:
sprite = Junctions.Medium;
_Sprite.DestRect = JUNCDEST_MED;
_Sprite.Depth = WallZBuffers[19];
break;
case WorldZoom.Near:
sprite = Junctions.Near;
_Sprite.DestRect = JUNCDEST_NEAR;
_Sprite.Depth = WallZBuffers[18];
break;
}
_Sprite.Pixel = world._2D.GetTexture(sprite.Frames[JunctionMap[flags]]);
_Sprite.SrcRect = new Microsoft.Xna.Framework.Rectangle(0, 0, _Sprite.Pixel.Width, _Sprite.Pixel.Height);
_Sprite.Room = 1;
world._2D.Draw(_Sprite);
}
off++;
}
}
}
timer.Stop();
//System.Diagnostics.Debug.WriteLine("Drawing walls took " + timer.ElapsedMilliseconds.ToString() + " ms");
}