TiledMapRenderer.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Graphics;
  6. using MonoGame.Extended.Graphics;
  7. namespace MonoGame.Extended.Tiled.Renderers
  8. {
  9. public class TiledMapRenderer : IDisposable
  10. {
  11. private readonly TiledMapModelBuilder _mapModelBuilder;
  12. private readonly TiledMapEffect _defaultEffect;
  13. private readonly GraphicsDevice _graphicsDevice;
  14. private TiledMapModel _mapModel;
  15. private Matrix _worldMatrix = Matrix.Identity;
  16. public TiledMapRenderer(GraphicsDevice graphicsDevice, TiledMap map = null)
  17. {
  18. if (graphicsDevice == null) throw new ArgumentNullException(nameof(graphicsDevice));
  19. _graphicsDevice = graphicsDevice;
  20. _defaultEffect = new TiledMapEffect(graphicsDevice);
  21. _mapModelBuilder = new TiledMapModelBuilder(graphicsDevice);
  22. if(map != null)
  23. LoadMap(map);
  24. }
  25. public void Dispose()
  26. {
  27. _mapModel?.Dispose();
  28. _defaultEffect.Dispose();
  29. }
  30. public void LoadMap(TiledMap map)
  31. {
  32. _mapModel?.Dispose();
  33. _mapModel = map != null ? _mapModelBuilder.Build(map) : null;
  34. }
  35. public void Update(GameTime gameTime)
  36. {
  37. if(_mapModel == null)
  38. return;
  39. for (var tilesetIndex = 0; tilesetIndex < _mapModel.Tilesets.Count; tilesetIndex++)
  40. {
  41. foreach (var animatedTilesetTile in _mapModel.GetAnimatedTiles(tilesetIndex))
  42. animatedTilesetTile.Update(gameTime);
  43. }
  44. foreach(var layer in _mapModel.LayersOfLayerModels)
  45. UpdateAnimatedLayerModels(layer.Value.OfType<TiledMapAnimatedLayerModel>());
  46. }
  47. private static unsafe void UpdateAnimatedLayerModels(IEnumerable<TiledMapAnimatedLayerModel> animatedLayerModels)
  48. {
  49. foreach (var animatedModel in animatedLayerModels)
  50. {
  51. // update the texture coordinates for each animated tile
  52. fixed (VertexPositionTexture* fixedVerticesPointer = animatedModel.Vertices)
  53. {
  54. var verticesPointer = fixedVerticesPointer;
  55. for (int i = 0; i < animatedModel.AnimatedTilesetTiles.Length; i++)
  56. {
  57. var currentFrameTextureCoordinates = animatedModel.AnimatedTilesetTiles[i].CurrentAnimationFrame.GetTextureCoordinates(animatedModel.AnimatedTilesetFlipFlags[i]);
  58. // ReSharper disable ArrangeRedundantParentheses
  59. (*verticesPointer++).TextureCoordinate = currentFrameTextureCoordinates[0];
  60. (*verticesPointer++).TextureCoordinate = currentFrameTextureCoordinates[1];
  61. (*verticesPointer++).TextureCoordinate = currentFrameTextureCoordinates[2];
  62. (*verticesPointer++).TextureCoordinate = currentFrameTextureCoordinates[3];
  63. // ReSharper restore ArrangeRedundantParentheses
  64. }
  65. }
  66. // copy (upload) the updated vertices to the GPU's memory
  67. animatedModel.VertexBuffer.SetData(animatedModel.Vertices, 0, animatedModel.Vertices.Length);
  68. }
  69. }
  70. public void Draw(Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f)
  71. {
  72. var viewMatrix1 = viewMatrix ?? Matrix.Identity;
  73. var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, _graphicsDevice.Viewport.Width, _graphicsDevice.Viewport.Height, 0, 0, -1);
  74. Draw(ref viewMatrix1, ref projectionMatrix1, effect, depth);
  75. }
  76. public void Draw(ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f)
  77. {
  78. if (_mapModel == null)
  79. return;
  80. for (var index = 0; index < _mapModel.Layers.Count; index++)
  81. Draw(index, ref viewMatrix, ref projectionMatrix, effect, depth);
  82. }
  83. public void Draw(TiledMapLayer layer, Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f)
  84. {
  85. var viewMatrix1 = viewMatrix ?? Matrix.Identity;
  86. var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, _graphicsDevice.Viewport.Width, _graphicsDevice.Viewport.Height, 0, 0, -1);
  87. Draw(layer, ref viewMatrix1, ref projectionMatrix1, effect, depth);
  88. }
  89. public void Draw(int layerIndex, Matrix? viewMatrix = null, Matrix? projectionMatrix = null, Effect effect = null, float depth = 0.0f)
  90. {
  91. var viewMatrix1 = viewMatrix ?? Matrix.Identity;
  92. var projectionMatrix1 = projectionMatrix ?? Matrix.CreateOrthographicOffCenter(0, _graphicsDevice.Viewport.Width, _graphicsDevice.Viewport.Height, 0, 0, -1);
  93. Draw(layerIndex, ref viewMatrix1, ref projectionMatrix1, effect, depth);
  94. }
  95. public void Draw(int layerIndex, ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f)
  96. {
  97. var layer = _mapModel.Layers[layerIndex];
  98. Draw(layer, ref viewMatrix, ref projectionMatrix, effect, depth);
  99. }
  100. public void Draw(TiledMapLayer layer, ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect = null, float depth = 0.0f)
  101. {
  102. if (_mapModel == null)
  103. return;
  104. if (!layer.IsVisible)
  105. return;
  106. if (layer is TiledMapObjectLayer)
  107. return;
  108. Draw(layer, Vector2.Zero, Vector2.One, ref viewMatrix, ref projectionMatrix, effect, depth);
  109. }
  110. private void Draw(TiledMapLayer layer, Vector2 parentOffset, Vector2 parentParallaxFactor, ref Matrix viewMatrix, ref Matrix projectionMatrix, Effect effect, float depth)
  111. {
  112. var offset = parentOffset + layer.Offset;
  113. var parallaxFactor = parentParallaxFactor * layer.ParallaxFactor;
  114. if (layer is TiledMapGroupLayer groupLayer)
  115. {
  116. foreach (var subLayer in groupLayer.Layers)
  117. Draw(subLayer, offset, parallaxFactor, ref viewMatrix, ref projectionMatrix, effect, depth);
  118. }
  119. else
  120. {
  121. _worldMatrix.Translation = new Vector3(offset, depth);
  122. var effect1 = effect ?? _defaultEffect;
  123. var tiledMapEffect = effect1 as ITiledMapEffect;
  124. if (tiledMapEffect == null)
  125. return;
  126. // model-to-world transform
  127. tiledMapEffect.World = _worldMatrix;
  128. tiledMapEffect.View = parallaxFactor == Vector2.One ? viewMatrix : IncludeParallax(viewMatrix, parallaxFactor);
  129. tiledMapEffect.Projection = projectionMatrix;
  130. foreach (var layerModel in _mapModel.LayersOfLayerModels[layer])
  131. {
  132. // desired alpha
  133. tiledMapEffect.Alpha = layer.Opacity;
  134. // desired texture
  135. tiledMapEffect.Texture = layerModel.Texture;
  136. // bind the vertex and index buffer
  137. _graphicsDevice.SetVertexBuffer(layerModel.VertexBuffer);
  138. _graphicsDevice.Indices = layerModel.IndexBuffer;
  139. // for each pass in our effect
  140. foreach (var pass in effect1.CurrentTechnique.Passes)
  141. {
  142. // apply the pass, effectively choosing which vertex shader and fragment (pixel) shader to use
  143. pass.Apply();
  144. // draw the geometry from the vertex buffer / index buffer
  145. _graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, layerModel.TriangleCount);
  146. }
  147. }
  148. }
  149. }
  150. private Matrix IncludeParallax(Matrix viewMatrix, Vector2 parallaxFactor)
  151. {
  152. viewMatrix.Translation *=new Vector3(parallaxFactor, 1f);
  153. return viewMatrix;
  154. }
  155. }
  156. }