Advertisement
Guest User

tilemap.cs

a guest
Sep 15th, 2015
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.34 KB | None | 0 0
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Content;
  3. using Microsoft.Xna.Framework.Graphics;
  4. using System;
  5. using System.Collections.Generic;
  6.  
  7. namespace Project.TileMaps
  8. {
  9.     /// <summary>
  10.     /// Identifies rendering options for layers in a <see cref="TileMap"/>.
  11.     /// </summary>
  12.     [Flags] public enum LayerSettings : uint
  13.     {
  14.         Invisible = 0x0,
  15.  
  16.  
  17.         BG_Settings = 0xFFFF,
  18.         //--------------------------------------------------------------------
  19.  
  20.         BG_Opacity = 0x1F,
  21.         //---------------------------------
  22.         BG_OpacitySixteenth = 0x1,
  23.         BG_OpacityEighth = 0x2,
  24.         BG_OpacityQuarter = 0x4,
  25.         BG_OpacityHalf = 0x8,
  26.         BG_OpacityFull = 0x10,
  27.  
  28.         BG_BlendMode = 0x60,
  29.         //---------------------------------
  30.         BG_InvertBlending = 0x20,
  31.         BG_EnableBlending = 0x40,
  32.  
  33.         BG_UseLightingTileSet = 0x80,
  34.  
  35.         BG_DisableColorTransform = 0x100,
  36.  
  37.         OBJ_Settings = 0xFFFF0000,
  38.         //--------------------------------------------------------------------
  39.  
  40.         OBJ_Opacity = 0x1F0000,
  41.         //---------------------------------
  42.         OBJ_OpacitySixteenth = 0x10000,
  43.         OBJ_OpacityEighth = 0x20000,
  44.         OBJ_OpacityQuarter = 0x40000,
  45.         OBJ_OpacityHalf = 0x80000,
  46.         OBJ_OpacityFull = 0x100000,
  47.  
  48.         OBJ_BlendMode = 0x600000,
  49.         //---------------------------------
  50.         OBJ_InvertBlending = 0x200000,
  51.         OBJ_EnableBlending = 0x400000,
  52.  
  53.         OBJ_DisableColorTransform = 0x1000000,
  54.     }
  55.  
  56.     public class Entity
  57.     {
  58.         public Vector2 WorldPosition;
  59.     }
  60.  
  61.     /// <summary>
  62.     /// Represents the drawable aspect of an entity in the game world.
  63.     /// </summary>
  64.     public class SpriteComponent
  65.     {
  66.         public Entity Master;
  67.  
  68.         public int Layer;
  69.         public Texture2D Texture;
  70.         public Rectangle[] Frames;
  71.         public int FrameIndex;
  72.     }
  73.  
  74.     public class AnimationSequence
  75.     {
  76.         public int[] Animations;
  77.         public int Progress;
  78.     }
  79.  
  80.     public struct SpriteAnimation
  81.     {
  82.         public int[] FrameIndices;
  83.         public TimeSpan[] FrameDurations;
  84.         public Vector2[] FramePositions;
  85.     }
  86.  
  87.     public class AnimationComponent
  88.     {
  89.         public SpriteComponent Target;
  90.  
  91.         public int CompletedFrameCount;
  92.         public TimeSpan Progress;
  93.         public SpriteAnimation[] AnimationDefinitions;
  94.         public int CurrentDefinitonIndex;
  95.  
  96.         public AnimationSequence ActiveSequence;
  97.         public AnimationSequence DefaultSequence;
  98.     }
  99.  
  100.     /// <summary>
  101.     /// Represents a game level constructed from square tiles.
  102.     /// </summary>
  103.     public class TileMap
  104.     {
  105.         #region Constants
  106.  
  107.         /// <summary>
  108.         /// Interpolates between source and destination color, without blending alpha. The destination alpha is used instead.
  109.         /// </summary>
  110.         public static readonly BlendState AlphaBlend = new BlendState()
  111.         {
  112.             ColorSourceBlend = Blend.SourceAlpha,
  113.             ColorDestinationBlend = Blend.InverseSourceAlpha,
  114.             ColorBlendFunction = BlendFunction.Add,
  115.  
  116.             AlphaSourceBlend = Blend.Zero,
  117.             AlphaDestinationBlend = Blend.One,
  118.             AlphaBlendFunction = BlendFunction.Add
  119.         };
  120.  
  121.         /// <summary>
  122.         /// Adds the source color to the destination color, without blending alpha. The destination alpha is used instead.
  123.         /// </summary>
  124.         public static readonly BlendState AdditiveBlend = new BlendState()
  125.         {
  126.             ColorSourceBlend = Blend.SourceAlpha,
  127.             ColorDestinationBlend = Blend.One,
  128.             ColorBlendFunction = BlendFunction.Add,
  129.  
  130.             AlphaSourceBlend = Blend.Zero,
  131.             AlphaDestinationBlend = Blend.One,
  132.             AlphaBlendFunction = BlendFunction.Add
  133.         };
  134.  
  135.         /// <summary>
  136.         /// Subtracts the source color from the destination color, without blending alpha. The destination alpha is used instead.
  137.         /// </summary>
  138.         public static readonly BlendState SubtractiveBlend = new BlendState()
  139.         {
  140.             ColorSourceBlend = Blend.SourceAlpha,
  141.             ColorDestinationBlend = Blend.One,
  142.             ColorBlendFunction = BlendFunction.ReverseSubtract,
  143.            
  144.             AlphaSourceBlend = Blend.Zero,
  145.             AlphaDestinationBlend = Blend.One,
  146.             AlphaBlendFunction = BlendFunction.Add
  147.         };
  148.  
  149.         static readonly BlendState[] BlendModes =
  150.         {
  151.             AlphaBlend,
  152.             AlphaBlend,
  153.             AdditiveBlend,
  154.             SubtractiveBlend
  155.         };
  156.  
  157.         /// <summary>
  158.         /// Stores eight bit values for construction of tinting colors when blending layers.
  159.         /// </summary>
  160.         static readonly byte[] OpacityMultipliers =
  161.         {
  162.             0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
  163.             0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
  164.             // Indices 16..31 refer to full opacity
  165.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  166.             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  167.         };
  168.  
  169.         /// <summary>
  170.         /// Stores the four major angles of rotation in radians.
  171.         /// </summary>
  172.         static readonly float[] Rotations =
  173.         {
  174.             0f,
  175.             MathHelper.PiOver2,
  176.             MathHelper.Pi,
  177.             MathHelper.PiOver2 * 3
  178.         };
  179.  
  180.         #endregion
  181.  
  182.         /// <summary>
  183.         /// Constructs an empty map. For use by the ContentSerializer.
  184.         /// Textures are initialized to null, so a failed texture load crashes the program.
  185.         /// Arrays are initialized as empty, so if the map does not render or animate, one of those failed.
  186.         /// </summary>
  187.         public TileMap()
  188.         {
  189.             tileAliases = new Dictionary<ushort, ushort>();
  190.            
  191.             background = null;
  192.             lighting = null;
  193.             parallax = null;
  194.            
  195.             layers = new LayerSettings[0];
  196.             blocks = new ushort[0, 0, 0];
  197.             animDefinitions = new TileAnimation[0];
  198.         }
  199.  
  200.         public TileMap(Texture2D tileset, Texture2D backdrop)
  201.         {
  202.             background = tileset;
  203.             lighting = null;
  204.             // parallax = backdrop;
  205.             parallaxSpeed = new Vector2(.5f);
  206.  
  207.             layers = new LayerSettings[]
  208.             {
  209.                 LayerSettings.BG_OpacityFull,
  210.                 LayerSettings.BG_OpacityFull,
  211.                 /*LayerSettings.DisableColorTransform |*/ LayerSettings.BG_EnableBlending | LayerSettings.BG_OpacityHalf,
  212.                 LayerSettings.BG_OpacityFull | LayerSettings.OBJ_OpacityFull,
  213.             };
  214.             animDefinitions = new TileAnimation[] {
  215.                 new TileAnimation(TileMapView.MakeTileID(14, 26),
  216.                     new ushort[] { TileMapView.MakeTileID(14, 26), TileMapView.MakeTileID(15, 26) },
  217.                     new TimeSpan[] { TimeSpan.FromMilliseconds(125) })
  218.             };
  219.             tileAliases = new Dictionary<ushort, ushort>();
  220.  
  221.             blocks = new ushort[4, 32, 18];
  222.             for (int x = 0; x < 32; x++)
  223.                 for (int y = 0; y < 18; y++)
  224.                 {
  225.                     blocks[0, x, y] = 0x485;
  226.                     blocks[1, x, y] = blocks[2, x, y] = blocks[3, x, y] = 0xFFF;
  227.                 }
  228.  
  229.             blocks[1, 7, 9] = TileMapView.MakeTileID(14, 26);
  230.             blocks[2, 6, 8] = TileMapView.MakeTileID(0, 49);
  231.             blocks[2, 6, 9] = TileMapView.MakeTileID(0, 50);
  232.             blocks[2, 6, 10] = TileMapView.MakeTileID(0, 51);
  233.             blocks[2, 7, 8] = TileMapView.MakeTileID(1, 49);
  234.             blocks[2, 7, 9] = TileMapView.MakeTileID(1, 50);
  235.             blocks[2, 7, 10] = TileMapView.MakeTileID(1, 51);
  236.             blocks[2, 8, 8] = TileMapView.MakeTileID(2, 49);
  237.             blocks[2, 8, 9] = TileMapView.MakeTileID(2, 50);
  238.             blocks[2, 8, 10] = TileMapView.MakeTileID(2, 51);
  239.  
  240.             blocks[0, 1, 2] = TileMapView.MakeTileID(3, 25, SpriteEffects.None, 2);
  241.  
  242.             border = new ushort[1, 2, 2] {
  243.                 {
  244.                     { TileMapView.MakeTileID(3, 19), TileMapView.MakeTileID(1, 11) },
  245.                     { TileMapView.MakeTileID(1, 11), TileMapView.MakeTileID(3, 19) }
  246.                 }
  247.             };
  248.             //border = new ushort[0, 0, 0];
  249.            
  250.             sprites = new List<SpriteComponent>(3);
  251.             sprites.Add(new SpriteComponent());
  252.             sprites.Add(new SpriteComponent());
  253.             sprites.Add(new SpriteComponent());
  254.  
  255.             sprites[0].Texture = tileset;
  256.             sprites[0].Frames = new Rectangle[] { new Rectangle(48, 0, 16, 32), new Rectangle(64, 0, 16, 32), new Rectangle(80, 0, 16, 32) };
  257.             sprites[0].Master = new Entity();
  258.             sprites[0].Master.WorldPosition = new Vector2(0.5f, 1.5f);
  259.             sprites[0].Layer = 3;
  260.  
  261.             sprites[1].Texture = tileset;
  262.             sprites[1].Frames = new Rectangle[] { new Rectangle(64, 0, 16, 32) };
  263.             sprites[1].Master = new Entity();
  264.             sprites[1].Master.WorldPosition = new Vector2(1.0f, 1.0f);
  265.             sprites[1].Layer = 0;
  266.  
  267.             sprites[2].Texture = tileset;
  268.             sprites[2].Frames = new Rectangle[] { new Rectangle(80, 0, 16, 32) };
  269.             sprites[2].Master = new Entity();
  270.             sprites[2].Master.WorldPosition = new Vector2(1.5f, 0.5f);
  271.             sprites[2].Layer = 0;
  272.  
  273.             spriteAnimations = new List<AnimationComponent>(1);
  274.             spriteAnimations.Add(new AnimationComponent());
  275.             spriteAnimations[0].Target = sprites[0];
  276.             spriteAnimations[0].AnimationDefinitions = new SpriteAnimation[]
  277.             {
  278.                 new SpriteAnimation()
  279.                 {
  280.                     FrameDurations = new TimeSpan[] { TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11) },
  281.                     FrameIndices = new int[] { 0, 1, 2 },
  282.                     FramePositions = new Vector2[] { new Vector2(0.33f, 0), new Vector2(0.34f, 0), new Vector2(0.33f, 0) },                  
  283.                 },
  284.                 new SpriteAnimation()
  285.                 {
  286.                     FrameDurations = new TimeSpan[] { TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11) },
  287.                     FrameIndices = new int[] { 0, 1, 2 },
  288.                     FramePositions = new Vector2[] { new Vector2(0, 0.33f), new Vector2(0, 0.34f), new Vector2(0, 0.33f) },
  289.                 },
  290.                 new SpriteAnimation()
  291.                 {
  292.                     FrameDurations = new TimeSpan[] { TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11) },
  293.                     FrameIndices = new int[] { 0, 1, 2 },
  294.                     FramePositions = new Vector2[] { new Vector2(-0.33f, 0), new Vector2(-0.34f, 0), new Vector2(-0.33f, 0) },
  295.                 },
  296.                 new SpriteAnimation()
  297.                 {
  298.                     FrameDurations = new TimeSpan[] { TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11), TimeSpan.FromSeconds(0.11) },
  299.                     FrameIndices = new int[] { 0, 1, 2 },
  300.                     FramePositions = new Vector2[] { new Vector2(0, -0.33f), new Vector2(0, -0.34f), new Vector2(0, -0.33f) },
  301.                 },
  302.             };
  303.             spriteAnimations[0].ActiveSequence = new AnimationSequence();
  304.             spriteAnimations[0].ActiveSequence.Animations = new int[] { 0, 1, 2, 3 };
  305.             spriteAnimations[0].DefaultSequence = spriteAnimations[0].ActiveSequence;
  306.         }
  307.  
  308.         [ContentSerializer] Texture2D parallax;
  309.         [ContentSerializer] Vector2 parallaxSpeed;
  310.  
  311.         [ContentSerializer] Texture2D background;
  312.         [ContentSerializer] Texture2D lighting;
  313.  
  314.         [ContentSerializer] LayerSettings[] layers;
  315.         [ContentSerializer] ushort[,,] blocks;
  316.         [ContentSerializer] ushort[,,] border;
  317.         [ContentSerializer] TileAnimation[] animDefinitions;
  318.  
  319.         [ContentSerializer] List<SpriteComponent> sprites;
  320.         [ContentSerializer] List<AnimationComponent> spriteAnimations;
  321.  
  322.         Dictionary<ushort, ushort> tileAliases;
  323.  
  324.         #region Properties
  325.  
  326.         /// <summary>
  327.         /// Gets the rendering options for all individual layers of the TileMap.
  328.         /// </summary>
  329.         public LayerSettings[] Layers { get { return layers; } }
  330.  
  331.         /// <summary>
  332.         /// Gets the bock data of the TileMap.
  333.         /// </summary>
  334.         public ushort[,,] Blocks { get { return blocks; } }
  335.  
  336.         /// <summary>
  337.         /// Gets the width of the map in tiles.
  338.         /// </summary>
  339.         public int Width
  340.         {
  341.             get { return blocks.GetLength(1); }
  342.         }
  343.  
  344.         /// <summary>
  345.         /// Gets the height of the map in tiles.
  346.         /// </summary>
  347.         public int Height
  348.         {
  349.             get { return blocks.GetLength(2); }
  350.         }
  351.  
  352.         #endregion
  353.         #region Methods
  354.  
  355.         /// <summary>
  356.         /// Updates animation and map object logic.
  357.         /// </summary>
  358.         public void Update(TimeSpan worldTimeDelta, Profiler profiler)
  359.         {
  360.             profiler.BeginOperation("Update Tile Map Animation Timers ({0})", animDefinitions.Length);
  361.  
  362.             for (int i = 0; i < animDefinitions.Length; i++)
  363.                 tileAliases[animDefinitions[i].TileID] = animDefinitions[i].Update(worldTimeDelta);
  364.  
  365.             profiler.EndOperation();
  366.             profiler.BeginOperation("Update Sprite Animation Timers ({0})", spriteAnimations.Count);
  367.  
  368.             foreach (AnimationComponent nextTimer in spriteAnimations)
  369.             {
  370.                 if (nextTimer != null && nextTimer.CurrentDefinitonIndex >= 0)
  371.                 {
  372.                     nextTimer.Progress += worldTimeDelta;
  373.  
  374.                     TimeSpan curFrameDuration = nextTimer
  375.                         .AnimationDefinitions[nextTimer.CurrentDefinitonIndex]
  376.                         .FrameDurations[nextTimer.CompletedFrameCount];
  377.  
  378.                     float delta = (float)worldTimeDelta.Ticks / curFrameDuration.Ticks; // TODO: Don't divide by zero!
  379.                     Vector2 positionOffset = delta * nextTimer
  380.                         .AnimationDefinitions[nextTimer.CurrentDefinitonIndex]
  381.                         .FramePositions[nextTimer.CompletedFrameCount];
  382.                     nextTimer.Target.Master.WorldPosition += positionOffset;
  383.  
  384.                     if (nextTimer.Progress >= curFrameDuration)
  385.                     {
  386.                         nextTimer.Progress -= curFrameDuration;
  387.                         nextTimer.CompletedFrameCount++;
  388.  
  389.                         if (nextTimer.CompletedFrameCount >= nextTimer.AnimationDefinitions[nextTimer.CurrentDefinitonIndex].FrameIndices.Length)
  390.                         {
  391.                             if (nextTimer.ActiveSequence != null)
  392.                             {
  393.                                 nextTimer.ActiveSequence.Progress++;
  394.                                 if (nextTimer.ActiveSequence.Progress >= nextTimer.ActiveSequence.Animations.Length)
  395.                                 {
  396.                                     if (nextTimer.ActiveSequence == nextTimer.DefaultSequence)
  397.                                         nextTimer.ActiveSequence.Progress = 0;
  398.                                     else
  399.                                         nextTimer.ActiveSequence = nextTimer.DefaultSequence;
  400.                                 }
  401.  
  402.                                 nextTimer.CurrentDefinitonIndex = nextTimer.ActiveSequence.Animations[nextTimer.ActiveSequence.Progress];
  403.                             }
  404.                             else
  405.                                 nextTimer.CurrentDefinitonIndex = -1;
  406.  
  407.                             nextTimer.Progress = TimeSpan.Zero;
  408.                             nextTimer.CompletedFrameCount = 0;
  409.                         }
  410.                         else
  411.                         {
  412.                             nextTimer.Target.FrameIndex = nextTimer
  413.                                 .AnimationDefinitions[nextTimer.CurrentDefinitonIndex]
  414.                                 .FrameIndices[nextTimer.CompletedFrameCount];
  415.                         }
  416.                     }
  417.                 }
  418.             }
  419.  
  420.             profiler.EndOperation();
  421.         }
  422.  
  423.         /// <summary>
  424.         /// Renders the tile map and all objects on it.
  425.         /// </summary>
  426.         public void Draw(Effect effect, SpriteBatch spriteBatch, TopDownCamera camera, VirtualScreen screen, Profiler profiler)
  427.         {
  428.             profiler.BeginOperation("Draw Tile Map");
  429.            
  430.             if (parallax != null)
  431.             {
  432.                 effect.Parameters["cameraTransform"].SetValue(camera.CreateParallaxView(parallaxSpeed) * screen.CreateSpriteBatchCompatibilityMatrix());
  433.                 spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null, effect);
  434.                 spriteBatch.Draw(parallax, Vector2.Zero, Color.White);
  435.                 spriteBatch.End();
  436.             }
  437.            
  438.             profiler.BeginOperation("Sort {0} sprites", sprites.Count);
  439.             // Sort sprites by their Y position
  440.             // TODO: Look into getting this to work with SpriteSortMode.FrontToBack, currently it doesn't seem to render anything.
  441.             // TODO: This doesn't support NULLs either. Fix this maybe?
  442.             effect.Parameters["cameraTransform"].SetValue(camera.Transform * screen.CreateSpriteBatchCompatibilityMatrix());
  443.             sprites.Sort((a, b) => Comparer<float>.Default.Compare(a.Master.WorldPosition.Y, b.Master.WorldPosition.Y));
  444.             profiler.EndOperation();
  445.  
  446.             for (int i = 0; i < blocks.GetLength(0); i++)
  447.             {
  448.                 LayerSettings Background = layers[i] & LayerSettings.BG_Settings;
  449.                 LayerSettings Objects = layers[i] & LayerSettings.OBJ_Settings;
  450.  
  451.                 if (Background != LayerSettings.Invisible)
  452.                 {
  453.                     profiler.BeginOperation("Draw Tile Map Layer {0}", i);
  454.  
  455.                     int multiplier = OpacityMultipliers[(int)(Background & LayerSettings.BG_Opacity)];
  456.  
  457.                     DrawBackgroundLayer(spriteBatch, camera, i,
  458.                         Background.HasFlag(LayerSettings.BG_DisableColorTransform) ? null : effect,
  459.                         Background.HasFlag(LayerSettings.BG_UseLightingTileSet) ? lighting : background,
  460.                         BlendModes[(int)(Background & LayerSettings.BG_BlendMode) >> 5],
  461.                         Background.HasFlag(LayerSettings.BG_EnableBlending) ?
  462.                             new Color(multiplier, multiplier, multiplier) : // Multiply RGB values for additive and subtractive blending
  463.                             new Color(0xFF, 0xFF, 0xFF, multiplier)         // Multiply Alpha for alpha blending
  464.                         );
  465.  
  466.                     profiler.EndOperation();
  467.                 }
  468.                 if (Objects != LayerSettings.Invisible)
  469.                 {
  470.                     profiler.BeginOperation("Draw Sprite Layer {0}", i);
  471.  
  472.                     int multiplier = OpacityMultipliers[(int)(Objects & LayerSettings.OBJ_Opacity) >> 16];
  473.  
  474.                     DrawSpriteLayer(spriteBatch, camera, i,
  475.                         Objects.HasFlag(LayerSettings.OBJ_DisableColorTransform) ? null : effect,
  476.                         BlendModes[(int)(Objects & LayerSettings.OBJ_BlendMode) >> 21],
  477.                         Objects.HasFlag(LayerSettings.OBJ_EnableBlending) ?
  478.                             new Color(multiplier, multiplier, multiplier) : // Multiply RGB values for additive and subtractive blending
  479.                             new Color(0xFF, 0xFF, 0xFF, multiplier)         // Multiply Alpha for alpha blending
  480.                             );
  481.  
  482.                     profiler.EndOperation();
  483.                 }
  484.             }
  485.  
  486.             profiler.EndOperation();
  487.         }
  488.  
  489.         void DrawBackgroundLayer(SpriteBatch spriteBatch, TopDownCamera camera, int layerIndex, Effect effect, Texture2D tileset, BlendState blending, Color tint)
  490.         {
  491.             spriteBatch.Begin(SpriteSortMode.Deferred, blending, SamplerState.PointClamp, null, null, effect, camera.Transform);
  492.  
  493.             if (effect != null) effect.CurrentTechnique.Passes[0].Apply();
  494.  
  495.             // NOTE: The lo values have to be one less than they theoretically should. Is the math off?
  496.             Vector4 viewport = camera.Viewport;
  497.             int x_lo = (int)viewport.X - 2;
  498.             int x_hi = (int)viewport.Z + 1;
  499.             int y_lo = (int)viewport.Y - 2;
  500.             int y_hi = (int)viewport.W + 1;
  501.  
  502.             int borderLayers = border.GetLength(0);
  503.             int borderWidth = border.GetLength(1);
  504.             int borderHeight = border.GetLength(2);
  505.  
  506.             Rectangle destination = new Rectangle(0, 0, 1, 1);
  507.             Rectangle source = new Rectangle(0, 0, 16, 16);
  508.  
  509.             int angle = 0;
  510.             SpriteEffects effects = SpriteEffects.None;
  511.             ushort id = 0;
  512.  
  513.             for (int x = x_lo; x <= x_hi; x++)
  514.             {
  515.                 for (int y = y_lo; y <= y_hi; y++)
  516.                 {
  517.                     if (x < 0 || x >= Width || y < 0 || y >= Height)
  518.                     {
  519.                         if (layerIndex >= borderLayers)
  520.                             continue;
  521.  
  522.                         id = border[layerIndex,
  523.                             ((x % borderWidth) + borderWidth) % borderWidth,
  524.                             ((y % borderHeight) + borderHeight) % borderHeight];
  525.                     }
  526.                     else
  527.                         id = blocks[layerIndex, x, y];
  528.  
  529.                     angle = (id >> 12) & 3;
  530.                     effects = (SpriteEffects)((id >> 14) & 3);
  531.  
  532.                     destination.X = x + ((angle & 1) ^ (angle >> 1));
  533.                     destination.Y = y + (angle >> 1);
  534.  
  535.                     id &= 0xFFF;
  536.                     if (tileAliases.ContainsKey(id))
  537.                         id = tileAliases[id];
  538.  
  539.                     source.X = (id & 63) * 16;
  540.                     source.Y = (id >> 6) * 16;
  541.  
  542.                     spriteBatch.Draw(tileset, destination, source, tint, Rotations[angle], Vector2.Zero, effects, 0);
  543.                 }
  544.             }
  545.  
  546.             spriteBatch.End();
  547.         }
  548.  
  549.         void DrawSpriteLayer(SpriteBatch spriteBatch, TopDownCamera camera, int layerIndex, Effect effect, BlendState blending, Color tint)
  550.         {
  551.             spriteBatch.Begin(SpriteSortMode.Deferred, blending, SamplerState.PointClamp, null, null, effect, camera.Transform);
  552.  
  553.             foreach (SpriteComponent nextSprite in sprites)
  554.             {
  555.                 if (nextSprite == null)
  556.                     continue;
  557.  
  558.                 if (nextSprite.Layer == layerIndex)
  559.                 {
  560.                     Rectangle source = nextSprite.Frames[nextSprite.FrameIndex];
  561.  
  562.                     Vector2 position = nextSprite.Master.WorldPosition;
  563.                     position.X -= source.Width / 32f;
  564.                     position.Y -= source.Height / 16f - 0.5f;
  565.                    
  566.                     spriteBatch.Draw(nextSprite.Texture, position, source, tint, 0, Vector2.Zero, 1 / 16f, SpriteEffects.None, 0f);
  567.                    
  568.                 }
  569.             }
  570.  
  571.             spriteBatch.End();
  572.         }
  573.  
  574.         #endregion
  575.     }
  576. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement