public void Draw(_2DSprite sprite) { sprite.AbsoluteDestRect = new Rectangle((int)(sprite.DestRect.X + PxOffset.X), (int)(sprite.DestRect.Y + PxOffset.Y), sprite.DestRect.Width, sprite.DestRect.Height); sprite.AbsoluteWorldPosition = sprite.WorldPosition + WorldOffset; sprite.AbsoluteTilePosition = sprite.TilePosition + TileOffset; sprite.ObjectID = ObjectID; sprite.DrawOrder = DrawOrder; bool added = false; int i = 0; while (!added) { if (i >= Sprites.Count) { Sprites.Add(new _2DSpriteGroup(FSOEnvironment.SoftwareDepth)); } if (FSOEnvironment.SoftwareDepth && Sprites[i].SprRectangles.SearchForIntersect(sprite.AbsoluteDestRect)) { i++; //intersects with a sprite in this list. advance to next. } else { if (FSOEnvironment.SoftwareDepth) { Sprites[i].SprRectangles.Add(sprite.AbsoluteDestRect); } Sprites[i].Sprites[sprite.RenderMode].Add(sprite); added = true; } } DrawOrder++; }
public void DrawScrollBuffer(ScrollBuffer buffer, Vector2 offset, Vector3 tileOffset, WorldState state) { var offsetDiff = buffer.PxOffset - offset; var tOff = buffer.WorldPosition - tileOffset; var spr = new _2DSprite { RenderMode = (buffer.Depth == null) ? _2DBatchRenderMode.NO_DEPTH : _2DBatchRenderMode.RESTORE_DEPTH, Pixel = buffer.Pixel, Depth = buffer.Depth, SrcRect = new Rectangle(0, 0, buffer.Pixel.Width, buffer.Pixel.Height), DestRect = new Rectangle((int)offsetDiff.X - 2, (int)offsetDiff.Y, buffer.Pixel.Width, buffer.Pixel.Height), }; this.Draw(spr); spr.AbsoluteWorldPosition = tOff * new Vector3(1, 1.23f, 1) * WorldSpace.WorldUnitsPerTile; if (state.Rotation == WorldRotation.TopRight || state.Rotation == WorldRotation.BottomRight) { spr.AbsoluteWorldPosition.Y *= -1; } //why does this even work??? //i added the 1.23 scaling factor on the y direction because at 1 it was shifting slightly //it's still not perfect, which leads me to believe there is a bigger problem... //after that I flip the offset if we're looking at it the other way, which inverts the z offset and corrects it somehow... //i mean, techically this should work with NO multipliers at all! }
public void Draw(_2DSprite sprite) { sprite.AbsoluteDestRect = new Rectangle((int)(sprite.DestRect.X + PxOffset.X), (int)(sprite.DestRect.Y + PxOffset.Y), sprite.DestRect.Width, sprite.DestRect.Height); sprite.AbsoluteWorldPosition = sprite.WorldPosition + WorldOffset; sprite.AbsoluteTilePosition = sprite.TilePosition + TileOffset; sprite.ObjectID = ObjectID; sprite.DrawOrder = DrawOrder; Sprites[sprite.RenderMode].Add(sprite); DrawOrder++; }
public _2DSprite NewSprite(_2DBatchRenderMode mode) { if (SpriteIndex >= SpritePool.Count) { var spr = new _2DSprite() { RenderMode = mode }; SpritePool.Add(spr); SpriteIndex++; return(spr); } else { var spr = SpritePool[SpriteIndex++]; spr.Repurpose(); spr.RenderMode = mode; return(spr); } }
public void DrawScrollBuffer(ScrollBuffer buffer, Vector2 offset, Vector3 tileOffset, WorldState state) { var offsetDiff = (buffer.PxOffset - offset) * state.PreciseZoom; var tOff = buffer.WorldPosition - tileOffset; var spr = new _2DSprite { RenderMode = (buffer.Depth == null) ? _2DBatchRenderMode.NO_DEPTH : _2DBatchRenderMode.RESTORE_DEPTH, Pixel = buffer.Pixel, Depth = buffer.Depth, SrcRect = new Rectangle(0, 0, buffer.Pixel.Width, buffer.Pixel.Height), DestRect = new Rectangle((int)offsetDiff.X - 2, (int)offsetDiff.Y, buffer.Pixel.Width, buffer.Pixel.Height), }; this.Draw(spr); spr.AbsoluteWorldPosition = tOff * WorldSpace.WorldUnitsPerTile; var y = spr.AbsoluteWorldPosition.Z; spr.AbsoluteWorldPosition.Z = spr.AbsoluteWorldPosition.Y; spr.AbsoluteWorldPosition.Y = y; }
public virtual void ValidateSprite(WorldState world) { if (DrawGroup == null) { return; } if (_Dirty) { if (_TextureDirty) { Items.Clear(); var direction = (uint)_Direction; /** Compute the direction **/ var image = DrawGroup.GetImage(direction, (uint)world.Zoom, (uint)world.Rotation); if (image != null) { foreach (var sprite in image.Sprites) { if (sprite == null) { continue; } var texture = world._2D.GetWorldTexture(sprite); if (texture == null || texture.ZBuffer == null) { continue; } var isDynamic = sprite.SpriteID >= DynamicSpriteBaseID && sprite.SpriteID < (DynamicSpriteBaseID + NumDynamicSprites); if (isDynamic) { var dynamicIndex = (ushort)(sprite.SpriteID - DynamicSpriteBaseID); var isVisible = (dynamicIndex > 63) ? ((DynamicSpriteFlags2 & ((ulong)0x1 << (dynamicIndex - 64))) > 0): ((DynamicSpriteFlags & ((ulong)0x1 << dynamicIndex)) > 0); if (!isVisible) { continue; } } var item = new _2DSprite(); //do not use sprite pool for DGRP, since we can reliably remember our own sprites. item.Pixel = texture.Pixel; item.Depth = texture.ZBuffer; if (texture.ZBuffer != null) { item.RenderMode = _2DBatchRenderMode.Z_BUFFER; item.WorldPosition = sprite.ObjectOffset; } else { item.RenderMode = _2DBatchRenderMode.NO_DEPTH; } var pt = ((TextureInfo)item.Pixel.Tag).Size; item.SrcRect = new Rectangle(0, 0, pt.X, pt.Y); item.DestRect = new Rectangle(0, 0, pt.X, pt.Y); item.FlipHorizontally = sprite.Flip; Items.Add(new DGRPRendererItem { Sprite = item, DGRPSprite = sprite }); } } _TextureDirty = false; } int maxX = int.MinValue, maxY = int.MinValue; int minX = int.MaxValue, minY = int.MaxValue; foreach (var item in Items) { var sprite = item.Sprite; var dgrpSprite = item.DGRPSprite; var pxX = (world.WorldSpace.CadgeWidth / 2.0f) + dgrpSprite.SpriteOffset.X; var pxY = (world.WorldSpace.CadgeBaseLine - item.Sprite.DestRect.Height) + dgrpSprite.SpriteOffset.Y; if (dgrpSprite.ObjectOffset != Vector3.Zero) { } var centerRelative = dgrpSprite.ObjectOffset * new Vector3(1f / 16f, 1f / 16f, 1f / 5f); centerRelative = Vector3.Transform(centerRelative, Matrix.CreateRotationZ(RadianDirection)); var pxOff = world.WorldSpace.GetScreenFromTile(centerRelative); sprite.DestRect.X = (int)(pxX + pxOff.X); sprite.DestRect.Y = (int)(pxY + pxOff.Y); if (sprite.DestRect.X < minX) { minX = sprite.DestRect.X; } if (sprite.DestRect.Y < minY) { minY = sprite.DestRect.Y; } if (sprite.DestRect.X + sprite.Pixel.Width > maxX) { maxX = sprite.DestRect.X + sprite.Pixel.Width; } if (sprite.DestRect.Y + sprite.Pixel.Height > maxY) { maxY = sprite.DestRect.Y + sprite.Pixel.Height; } sprite.WorldPosition = centerRelative * 3f; var y = sprite.WorldPosition.Z; sprite.WorldPosition.Z = sprite.WorldPosition.Y; sprite.WorldPosition.Y = y; sprite.Room = ((dgrpSprite.Flags & DGRPSpriteFlags.Luminous) > 0 && Room != 65534 && Room != 65533)?(ushort)65535:Room; sprite.Floor = Level; } Bounding = new Rectangle(minX, minY, maxX - minX, maxY - minY); _Dirty = false; } }
private _2DSprite GetWallSprite(Wall pattern, WallStyle style, int rotation, bool down, WorldState world) { var _Sprite = new _2DSprite() { RenderMode = _2DBatchRenderMode.WALL }; SPR sprite = null; SPR mask = null; switch (world.Zoom) { case WorldZoom.Far: sprite = pattern.Far; if (style != null) mask = (down) ? style.WallsDownFar : style.WallsUpFar; _Sprite.DestRect = DESTINATION_FAR[rotation]; _Sprite.Depth = WallZBuffers[rotation+8]; break; case WorldZoom.Medium: sprite = pattern.Medium; if (style != null) mask = (down) ? style.WallsDownMedium : style.WallsUpMedium; _Sprite.DestRect = DESTINATION_MED[rotation]; _Sprite.Depth = WallZBuffers[rotation+4]; break; case WorldZoom.Near: sprite = pattern.Near; if (style != null) mask = (down) ? style.WallsDownNear : style.WallsUpNear; _Sprite.DestRect = DESTINATION_NEAR[rotation]; _Sprite.Depth = WallZBuffers[rotation]; break; } if (sprite != null) { if (mask == null) mask = sprite; _Sprite.Pixel = world._2D.GetTexture(sprite.Frames[rotation]); _Sprite.Mask = world._2D.GetTexture(mask.Frames[rotation]); _Sprite.SrcRect = new Microsoft.Xna.Framework.Rectangle(0, 0, _Sprite.Pixel.Width, _Sprite.Pixel.Height); } return _Sprite; }
//Gets a floor sprite. Used to draw floors cut in half by walls. private _2DSprite GetFloorSprite(Floor pattern, int rotation, WorldState world, byte cut) { var _Sprite = new _2DSprite() { RenderMode = _2DBatchRenderMode.Z_BUFFER }; if (pattern == null) return _Sprite; SPR2 sprite = null; switch (world.Zoom) { case WorldZoom.Far: sprite = pattern.Far; _Sprite.DestRect = FLRDEST_FAR; _Sprite.Depth = WallZBuffers[14]; break; case WorldZoom.Medium: sprite = pattern.Medium; _Sprite.DestRect = FLRDEST_MED; _Sprite.Depth = WallZBuffers[13]; break; case WorldZoom.Near: sprite = pattern.Near; _Sprite.DestRect = FLRDEST_NEAR; _Sprite.Depth = WallZBuffers[12]; break; } if (sprite != null) { _Sprite.Pixel = world._2D.GetTexture(sprite.Frames[rotation]); _Sprite.SrcRect = new Microsoft.Xna.Framework.Rectangle(0, 0, _Sprite.Pixel.Width, _Sprite.Pixel.Height); } switch (cut) { case 0: //vertical cut, left side _Sprite.DestRect.Width /= 2; _Sprite.SrcRect.Width /= 2; break; case 1: //vertical cut, right side _Sprite.DestRect.X += _Sprite.DestRect.Width / 2; _Sprite.DestRect.Width /= 2; _Sprite.SrcRect.X += _Sprite.SrcRect.Width / 2; _Sprite.SrcRect.Width /= 2; break; case 2: //horizontal cut, top side _Sprite.DestRect.Height /= 2; _Sprite.SrcRect.Height /= 2; break; case 3: _Sprite.DestRect.Y += _Sprite.DestRect.Height / 2; _Sprite.DestRect.Height /= 2; _Sprite.SrcRect.Y += _Sprite.SrcRect.Height / 2; _Sprite.SrcRect.Height /= 2; break; } return _Sprite; }
private _2DSprite CopySprite(_2DSprite _Sprite) { return new _2DSprite() { DestRect = _Sprite.DestRect, SrcRect = _Sprite.SrcRect, RenderMode = _2DBatchRenderMode.WALL, Pixel = _Sprite.Pixel, Depth = _Sprite.Depth }; }
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); 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++) { 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) + pxOffset); 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(_Sprite); tlStyle = GetStyle(comp.TopLeftStyle); //return to normal if cutaway var tilePosition2 = contOff; world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition2) + pxOffset); 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) + pxOffset); 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) + pxOffset); 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(_Sprite); trStyle = GetStyle(comp.TopRightStyle); //return to normal if cutaway var tilePosition2 = contOff; world._2D.OffsetPixel(world.WorldSpace.GetScreenFromTile(tilePosition2) + pxOffset); 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) + pxOffset); 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) + pxOffset); 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); var _Sprite = GetWallSprite(trPattern, trStyle, 2, down, world); 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); if (floor.Pixel != null) world._2D.Draw(floor); } if (comp.TopLeftStyle != 0) { var floor = GetFloorSprite(floorContent.Get(comp.TopLeftStyle), 0, world, 2); 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); var _Sprite = GetWallSprite(trPattern, trStyle, 3, down, world); 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); if (floor.Pixel != null) world._2D.Draw(floor); } if (comp.TopLeftStyle != 0) { var floor = GetFloorSprite(floorContent.Get(comp.TopLeftStyle), 0, world, 0); 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) + pxOffset); world._2D.OffsetTile(tilePosition); var _Sprite = new _2DSprite() { RenderMode = _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); world._2D.Draw(_Sprite); } off++; } } } timer.Stop(); //System.Diagnostics.Debug.WriteLine("Drawing walls took " + timer.ElapsedMilliseconds.ToString() + " ms"); }
private _2DSprite GetAirSprite(WorldState world) { var _Sprite = new _2DSprite() { RenderMode = _2DBatchRenderMode.Z_BUFFER }; var airTiles = TextureGenerator.GetAirTiles(world.Device); Texture2D sprite = null; switch (world.Zoom) { case WorldZoom.Far: sprite = airTiles[2]; _Sprite.DestRect = FLOORDEST_FAR; _Sprite.Depth = ArchZBuffers[14]; break; case WorldZoom.Medium: sprite = airTiles[1]; _Sprite.DestRect = FLOORDEST_MED; _Sprite.Depth = ArchZBuffers[13]; break; case WorldZoom.Near: sprite = airTiles[0]; _Sprite.DestRect = FLOORDEST_NEAR; _Sprite.Depth = ArchZBuffers[12]; break; } _Sprite.Pixel = sprite; _Sprite.SrcRect = new Microsoft.Xna.Framework.Rectangle(0, 0, _Sprite.Pixel.Width, _Sprite.Pixel.Height); return _Sprite; }
private _2DSprite GetFloorSprite(Floor pattern, int rotation, WorldState world) { var _Sprite = new _2DSprite() { RenderMode = _2DBatchRenderMode.Z_BUFFER }; if (pattern == null) return _Sprite; SPR2 sprite = null; bool vertFlip = world.Rotation == WorldRotation.TopRight || world.Rotation == WorldRotation.BottomRight; int bufOff = (vertFlip) ? 3 : 0; switch (world.Zoom) { case WorldZoom.Far: sprite = pattern.Far; _Sprite.DestRect = FLOORDEST_FAR; _Sprite.Depth = ArchZBuffers[14+bufOff]; break; case WorldZoom.Medium: sprite = pattern.Medium; _Sprite.DestRect = FLOORDEST_MED; _Sprite.Depth = ArchZBuffers[13 + bufOff]; break; case WorldZoom.Near: sprite = pattern.Near; _Sprite.DestRect = FLOORDEST_NEAR; _Sprite.Depth = ArchZBuffers[12 + bufOff]; break; } if (sprite != null) { _Sprite.Pixel = world._2D.GetTexture(sprite.Frames[rotation]); _Sprite.SrcRect = new Microsoft.Xna.Framework.Rectangle(0, 0, _Sprite.Pixel.Width, _Sprite.Pixel.Height); if (vertFlip) _Sprite.FlipVertically = true; if ((int)world.Rotation > 1) _Sprite.FlipHorizontally = true; } return _Sprite; }
public void ValidateSprite(WorldState world) { if (DrawGroup == null) return; if (_Dirty) { if (_TextureDirty) { Items.Clear(); var direction = (uint)_Direction; /** Compute the direction **/ var image = DrawGroup.GetImage(direction, (uint)world.Zoom, (uint)world.Rotation); if (image != null) { foreach (var sprite in image.Sprites) { if (sprite == null) continue; var texture = world._2D.GetWorldTexture(sprite); if (texture == null || texture.ZBuffer == null) { continue; } var isDynamic = sprite.SpriteID >= DynamicSpriteBaseID && sprite.SpriteID < (DynamicSpriteBaseID + NumDynamicSprites); if (isDynamic) { var dynamicIndex = (ushort)(sprite.SpriteID - DynamicSpriteBaseID); var isVisible = (dynamicIndex > 63) ? ((DynamicSpriteFlags2 & ((ulong)0x1 << (dynamicIndex-64))) > 0): ((DynamicSpriteFlags & ((ulong)0x1 << dynamicIndex)) > 0); if (!isVisible) { continue; } } var item = new _2DSprite(); //do not use sprite pool for DGRP, since we can reliably remember our own sprites. item.Pixel = texture.Pixel; item.Depth = texture.ZBuffer; if (texture.ZBuffer != null) { item.RenderMode = _2DBatchRenderMode.Z_BUFFER; item.WorldPosition = sprite.ObjectOffset; } else { item.RenderMode = _2DBatchRenderMode.NO_DEPTH; } item.SrcRect = new Rectangle(0, 0, item.Pixel.Width, item.Pixel.Height); item.DestRect = new Rectangle(0, 0, item.Pixel.Width, item.Pixel.Height); item.FlipHorizontally = sprite.Flip; Items.Add(new DGRPRendererItem { Sprite = item, DGRPSprite = sprite }); } } _TextureDirty = false; } int maxX = int.MinValue, maxY = int.MinValue; int minX = int.MaxValue, minY = int.MaxValue; foreach (var item in Items) { var sprite = item.Sprite; var dgrpSprite = item.DGRPSprite; var pxX = (world.WorldSpace.CadgeWidth / 2.0f) + dgrpSprite.SpriteOffset.X; var pxY = (world.WorldSpace.CadgeBaseLine - sprite.Pixel.Height) + dgrpSprite.SpriteOffset.Y; var centerRelative = dgrpSprite.ObjectOffset * new Vector3(1f / 16f, 1f / 16f, 1f / 5f); centerRelative = Vector3.Transform(centerRelative, Matrix.CreateRotationZ(RadianDirection)); var pxOff = world.WorldSpace.GetScreenFromTile(centerRelative); sprite.DestRect.X = (int)(pxX + pxOff.X); sprite.DestRect.Y = (int)(pxY + pxOff.Y); if (sprite.DestRect.X < minX) minX = sprite.DestRect.X; if (sprite.DestRect.Y < minY) minY = sprite.DestRect.Y; if (sprite.DestRect.X + sprite.Pixel.Width > maxX) maxX = sprite.DestRect.X + sprite.Pixel.Width; if (sprite.DestRect.Y + sprite.Pixel.Height > maxY) maxY = sprite.DestRect.Y + sprite.Pixel.Height; sprite.WorldPosition = centerRelative * 3f; sprite.Room = Room; } Bounding = new Rectangle(minX, minY, maxX - minX, maxY - minY); _Dirty = false; } }
public void Draw(WorldState world) { if (_Dirty) { if (_TextureDirty) { Items.Clear(); var direction = (uint)_Direction; /** Compute the direction **/ var image = DrawGroup.GetImage(direction, (uint)world.Zoom, (uint)world.Rotation); if (image != null) { foreach (var sprite in image.Sprites) { var texture = world._2D.GetWorldTexture(sprite); if (texture == null || texture.ZBuffer == null) { continue; } var isDynamic = sprite.SpriteID >= DynamicSpriteBaseID && sprite.SpriteID < (DynamicSpriteBaseID + NumDynamicSprites); if (isDynamic){ var dynamicIndex = (ushort)(sprite.SpriteID - DynamicSpriteBaseID); var isVisible = (DynamicSpriteFlags & (0x1 << dynamicIndex)) > 0; if (!isVisible){ continue; } } var item = new _2DSprite(); item.Pixel = texture.Pixel; item.Depth = texture.ZBuffer; if (texture.ZBuffer != null){ item.RenderMode = _2DBatchRenderMode.Z_BUFFER; item.WorldPosition = sprite.ObjectOffset; }else{ item.RenderMode = _2DBatchRenderMode.NO_DEPTH; } item.SrcRect = new Rectangle(0, 0, item.Pixel.Width, item.Pixel.Height); item.DestRect = new Rectangle(0, 0, item.Pixel.Width, item.Pixel.Height); item.FlipHorizontally = sprite.Flip; Items.Add(new DGRPRendererItem { Sprite = item, DGRPSprite = sprite }); } } _TextureDirty = false; } foreach (var item in Items) { var sprite = item.Sprite; var dgrpSprite = item.DGRPSprite; var pxX = (world.WorldSpace.CadgeWidth / 2.0f) + dgrpSprite.SpriteOffset.X; var pxY = (world.WorldSpace.CadgeBaseLine - sprite.Pixel.Height) + dgrpSprite.SpriteOffset.Y; var centerRelative = dgrpSprite.ObjectOffset * new Vector3(1f/16f, 1f/16f, 1f/5f); centerRelative = Vector3.Transform(centerRelative, Matrix.CreateRotationZ(RadianDirection)); var pxOff = world.WorldSpace.GetScreenFromTile(centerRelative); sprite.DestRect.X = (int)(pxX+pxOff.X); sprite.DestRect.Y = (int)(pxY+pxOff.Y); sprite.WorldPosition = centerRelative * 3f; } _Dirty = false; } foreach (var item in Items) { world._2D.Draw(item.Sprite); } }
private _2DSprite CopySprite(WorldState world, _2DSprite _Sprite) { var spr = world._2D.NewSprite(_2DBatchRenderMode.WALL); spr.DestRect = _Sprite.DestRect; spr.SrcRect = _Sprite.SrcRect; spr.Pixel = _Sprite.Pixel; spr.Depth = _Sprite.Depth; spr.Room = _Sprite.Room; return spr; }
public void ValidateSprite(WorldState world) { if (DrawGroup == null) { return; } if (_Dirty) { if (_TextureDirty) { Items.Clear(); var direction = (uint)_Direction; /** Compute the direction **/ var image = DrawGroup.GetImage(direction, (uint)world.Zoom, (uint)world.Rotation); if (image != null) { foreach (var sprite in image.Sprites) { if (sprite == null) { continue; } var texture = world._2D.GetWorldTexture(sprite); if (texture == null || texture.ZBuffer == null) { continue; } var isDynamic = sprite.SpriteID >= DynamicSpriteBaseID && sprite.SpriteID < (DynamicSpriteBaseID + NumDynamicSprites); if (isDynamic) { var dynamicIndex = (ushort)(sprite.SpriteID - DynamicSpriteBaseID); var isVisible = (DynamicSpriteFlags & (0x1 << dynamicIndex)) > 0; if (!isVisible) { continue; } } var item = new _2DSprite(); item.Pixel = texture.Pixel; item.Depth = texture.ZBuffer; if (texture.ZBuffer != null) { item.RenderMode = _2DBatchRenderMode.Z_BUFFER; item.WorldPosition = sprite.ObjectOffset; } else { item.RenderMode = _2DBatchRenderMode.NO_DEPTH; } item.SrcRect = new Rectangle(0, 0, item.Pixel.Width, item.Pixel.Height); item.DestRect = new Rectangle(0, 0, item.Pixel.Width, item.Pixel.Height); item.FlipHorizontally = sprite.Flip; Items.Add(new DGRPRendererItem { Sprite = item, DGRPSprite = sprite }); } } _TextureDirty = false; } int maxX = int.MinValue, maxY = int.MinValue; int minX = int.MaxValue, minY = int.MaxValue; foreach (var item in Items) { var sprite = item.Sprite; var dgrpSprite = item.DGRPSprite; var pxX = (world.WorldSpace.CadgeWidth / 2.0f) + dgrpSprite.SpriteOffset.X; var pxY = (world.WorldSpace.CadgeBaseLine - sprite.Pixel.Height) + dgrpSprite.SpriteOffset.Y; var centerRelative = dgrpSprite.ObjectOffset * new Vector3(1f / 16f, 1f / 16f, 1f / 5f); centerRelative = Vector3.Transform(centerRelative, Matrix.CreateRotationZ(RadianDirection)); var pxOff = world.WorldSpace.GetScreenFromTile(centerRelative); sprite.DestRect.X = (int)(pxX + pxOff.X); sprite.DestRect.Y = (int)(pxY + pxOff.Y); if (sprite.DestRect.X < minX) { minX = sprite.DestRect.X; } if (sprite.DestRect.Y < minY) { minY = sprite.DestRect.Y; } if (sprite.DestRect.X + sprite.Pixel.Width > maxX) { maxX = sprite.DestRect.X + sprite.Pixel.Width; } if (sprite.DestRect.Y + sprite.Pixel.Height > maxY) { maxY = sprite.DestRect.Y + sprite.Pixel.Height; } sprite.WorldPosition = centerRelative * 3f; sprite.Room = Room; } Bounding = new Rectangle(minX, minY, maxX - minX, maxY - minY); _Dirty = false; } }