refactored the tiled map draw methods to allow using your own spritebatch

This commit is contained in:
Dylan Wilson
2016-02-10 21:27:05 +10:00
parent 78b4b01c1f
commit bfa26bf370
8 changed files with 103 additions and 52 deletions
@@ -0,0 +1,18 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended.Maps.Tiled
{
public static class SpriteBatchExtensions
{
public static void Draw(this SpriteBatch spriteBatch, TiledMap tiledMap, Camera2D camera, bool useMapBackgroundColor = false)
{
tiledMap.Draw(spriteBatch, camera, useMapBackgroundColor);
}
public static void Draw(this SpriteBatch spriteBatch, TiledTileLayer tileLayer, Rectangle visibleRectangle)
{
tileLayer.Draw(spriteBatch, visibleRectangle);
}
}
}
@@ -26,7 +26,7 @@ namespace MonoGame.Extended.Maps.Tiled
public Vector2 Position { get; set; }
public override void Draw(RectangleF visibleRectangle)
public override void Draw(Rectangle visibleRectangle)
{
_spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp);
_spriteBatch.Draw(_texture, Position, Color.White);
@@ -1,6 +1,5 @@
using System;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.Shapes;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Maps.Tiled
{
@@ -17,6 +16,6 @@ namespace MonoGame.Extended.Maps.Tiled
public string Name { get; private set; }
public TiledProperties Properties { get; private set; }
public abstract void Draw(RectangleF visibleRectangle);
public abstract void Draw(Rectangle visibleRectangle);
}
}
+14 -22
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.Shapes;
using MonoGame.Extended.TextureAtlases;
namespace MonoGame.Extended.Maps.Tiled
@@ -14,7 +15,6 @@ namespace MonoGame.Extended.Maps.Tiled
{
_graphicsDevice = graphicsDevice;
_renderTarget = new RenderTarget2D(graphicsDevice, width*tileWidth, height*tileHeight);
//_spriteBatch = new SpriteBatch(graphicsDevice);
_layers = new List<TiledLayer>();
_tilesets = new List<TiledTileset>();
@@ -36,7 +36,6 @@ namespace MonoGame.Extended.Maps.Tiled
private readonly GraphicsDevice _graphicsDevice;
private readonly List<TiledLayer> _layers;
private readonly RenderTarget2D _renderTarget;
//private readonly SpriteBatch _spriteBatch;
public int Width { get; }
public int Height { get; }
@@ -85,32 +84,25 @@ namespace MonoGame.Extended.Maps.Tiled
return (T) GetLayer(name);
}
public void Draw(SpriteBatch spriteBatch, Camera2D camera, bool useMapBackgroundColor = false)
public void Draw(SpriteBatch spriteBatch, Rectangle visibleRectangle, bool useMapBackgroundColor = false)
{
// it's important to get the camera state before setting the render target
// because the render target changes the size of the viewport
var boundingRectangle = camera.GetBoundingRectangle();
var viewport = _graphicsDevice.Viewport;
var previousRenderTargetUsage = _graphicsDevice.PresentationParameters.RenderTargetUsage;
var backgroundColor = useMapBackgroundColor && BackgroundColor.HasValue ? BackgroundColor.Value : Color.Transparent;
_graphicsDevice.PresentationParameters.RenderTargetUsage = RenderTargetUsage.PreserveContents;
_graphicsDevice.SetRenderTarget(_renderTarget);
if (useMapBackgroundColor && BackgroundColor.HasValue)
_graphicsDevice.Clear(BackgroundColor.Value);
else
_graphicsDevice.Clear(Color.Transparent);
foreach (var layer in _layers)
layer.Draw(boundingRectangle);
_graphicsDevice.SetRenderTarget(null);
_graphicsDevice.PresentationParameters.RenderTargetUsage = previousRenderTargetUsage;
_graphicsDevice.Viewport = viewport;
using (_renderTarget.BeginDraw(_graphicsDevice, backgroundColor))
{
foreach (var layer in _layers)
layer.Draw(visibleRectangle);
}
spriteBatch.Draw(_renderTarget, Vector2.Zero, Color.White);
}
public void Draw(SpriteBatch spriteBatch, Camera2D camera, bool useMapBackgroundColor = false)
{
var visibleRectangle = camera.GetBoundingRectangle().ToRectangle();
Draw(spriteBatch, visibleRectangle, useMapBackgroundColor);
}
public TextureRegion2D GetTileRegion(int id)
{
if (id == 0)
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.Shapes;
using MonoGame.Extended.TextureAtlases;
namespace MonoGame.Extended.Maps.Tiled
@@ -25,27 +24,17 @@ namespace MonoGame.Extended.Maps.Tiled
_spriteBatch.Dispose();
}
public int Width { get; private set; }
public int Height { get; private set; }
public int Width { get; }
public int Height { get; }
private readonly TiledMap _map;
private readonly TiledTile[] _tiles;
private readonly SpriteBatch _spriteBatch;
private RenderTarget2D _renderTarget;
public IEnumerable<TiledTile> Tiles
{
get { return _tiles; }
}
public int TileWidth
{
get { return _map.TileWidth; }
}
public int TileHeight
{
get { return _map.TileHeight; }
}
public IEnumerable<TiledTile> Tiles => _tiles;
public int TileWidth => _map.TileWidth;
public int TileHeight => _map.TileHeight;
private TiledTile[] CreateTiles(int[] data)
{
@@ -64,16 +53,16 @@ namespace MonoGame.Extended.Maps.Tiled
return tiles;
}
public override void Draw(RectangleF visibleRectangle)
public override void Draw(Rectangle visibleRectangle)
{
var renderOrderFunction = GetRenderOrderFunction();
var tileLocationFunction = GetTileLocationFunction();
var firstCol = (int)Math.Floor(visibleRectangle.Left / _map.TileWidth);
var firstRow = (int)Math.Floor(visibleRectangle.Top / _map.TileHeight);
var firstCol = (int)Math.Floor(visibleRectangle.Left / (float)_map.TileWidth);
var firstRow = (int)Math.Floor(visibleRectangle.Top / (float)_map.TileHeight);
// +3 to cover any gaps
var columns = Math.Min(_map.Width, (int)visibleRectangle.Width / _map.TileWidth) + 3;
var rows = Math.Min(_map.Height, (int)visibleRectangle.Height / _map.TileHeight) + 3;
var columns = Math.Min(_map.Width, visibleRectangle.Width / _map.TileWidth) + 3;
var rows = Math.Min(_map.Height, visibleRectangle.Height / _map.TileHeight) + 3;
_spriteBatch.Begin(blendState: BlendState.AlphaBlend, samplerState: SamplerState.PointClamp);
@@ -92,6 +81,17 @@ namespace MonoGame.Extended.Maps.Tiled
_spriteBatch.End();
}
public void Draw(SpriteBatch spriteBatch, Rectangle visibleRectangle)
{
if(_renderTarget == null)
_renderTarget = new RenderTarget2D(_spriteBatch.GraphicsDevice, Width * TileWidth, Height * TileHeight);
using (_renderTarget.BeginDraw(_spriteBatch.GraphicsDevice, Color.Transparent))
{
Draw(visibleRectangle);
}
}
private Func<TiledTile, Point> GetTileLocationFunction()
{
switch (_map.Orientation)
@@ -103,7 +103,7 @@ namespace MonoGame.Extended.Maps.Tiled
case TiledMapOrientation.Staggered:
throw new NotImplementedException("Staggered maps are not yet implemented");
default:
throw new NotSupportedException(string.Format("{0} is not supported", _map.Orientation));
throw new NotSupportedException($"{_map.Orientation} is not supported");
}
}
@@ -142,7 +142,7 @@ namespace MonoGame.Extended.Maps.Tiled
case TiledRenderOrder.RightUp:
return GetTilesRightUp;
default:
throw new NotSupportedException(string.Format("{0} is not supported", _map.RenderOrder));
throw new NotSupportedException($"{_map.RenderOrder} is not supported");
}
}
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.TextureAtlases;
@@ -8,8 +9,8 @@ namespace MonoGame.Extended.Maps.Tiled
{
public TiledTileset(Texture2D texture, int firstId, int tileWidth, int tileHeight, int spacing = 2, int margin = 2)
{
if (texture.Width % tileWidth != 0 || texture.Height % tileHeight != 0)
throw new System.InvalidOperationException("The tileset file size is not multiple of the tile size. Make sure the tile grid is correct.");
//if (texture.Width % tileWidth != 0 || texture.Height % tileHeight != 0)
// throw new InvalidOperationException("The tileset texture must be an exact multiple of the tile size");
Texture = texture;
FirstId = firstId;
@@ -75,6 +75,8 @@
<Compile Include="IScalable.cs" />
<Compile Include="IUpdate.cs" />
<Compile Include="Maps\Tiled\CollisionWorldExtensions.cs" />
<Compile Include="RenderTarget2DExtensions.cs" />
<Compile Include="Maps\Tiled\SpriteBatchExtensions.cs" />
<Compile Include="Maps\Tiled\TiledMapOrientation.cs" />
<Compile Include="Shapes\SpriteBatchExtensions.cs" />
<Compile Include="Shapes\CircleF.cs" />
@@ -0,0 +1,39 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGame.Extended
{
public static class RenderTarget2DExtensions
{
public static IDisposable BeginDraw(this RenderTarget2D renderTarget, GraphicsDevice graphicsDevice, Color backgroundColor)
{
return new RenderTargetOperation(renderTarget, graphicsDevice, backgroundColor);
}
private class RenderTargetOperation : IDisposable
{
private readonly GraphicsDevice _graphicsDevice;
private readonly Viewport _viewport;
private readonly RenderTargetUsage _previousRenderTargetUsage;
public RenderTargetOperation(RenderTarget2D renderTarget, GraphicsDevice graphicsDevice, Color backgroundColor)
{
_graphicsDevice = graphicsDevice;
_viewport = _graphicsDevice.Viewport;
_previousRenderTargetUsage = _graphicsDevice.PresentationParameters.RenderTargetUsage;
_graphicsDevice.PresentationParameters.RenderTargetUsage = RenderTargetUsage.PreserveContents;
_graphicsDevice.SetRenderTarget(renderTarget);
_graphicsDevice.Clear(backgroundColor);
}
public void Dispose()
{
_graphicsDevice.SetRenderTarget(null);
_graphicsDevice.PresentationParameters.RenderTargetUsage = _previousRenderTargetUsage;
_graphicsDevice.Viewport = _viewport;
}
}
}
}