Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using SFML.Graphics;
- using SFML.Window;
- using Test;
- namespace SFML.Utils
- {
- public delegate void TileProvider(int x, int y, int layer, out Color color, out IntRect rec);
- class MapRenderer : Drawable
- {
- private readonly float TileSize;
- public readonly int Layers;
- private int height;
- private int width;
- private Vector2i offset;
- private Vertex[] vertices;
- private TileProvider provider;
- private Texture texture;
- public MapRenderer(Texture texture, TileProvider provider, float tileSize = 16, int layers = 1)
- {
- if(provider == null || layers <= 0) throw new ArgumentException();
- this.provider = provider;
- TileSize = tileSize;
- Layers = layers;
- vertices = new Vertex[0];
- this.texture = texture;
- }
- public void Refresh()
- {
- RefreshLocal(0, 0, width, height);
- }
- private void RefreshLocal(int left, int top, int right, int bottom)
- {
- for (var y = top; y < bottom; y++)
- for (var x = left; x < right; x++)
- {
- Refresh(x+offset.X, y+offset.Y);
- }
- }
- private void SetSize(Vector2f v)
- {
- var w = (int) (v.X/TileSize) + 2;
- var h = (int) (v.Y/TileSize) + 2;
- if (w == width && h == height) return;
- width = w;
- height = h;
- vertices = new Vertex[width*height*4*Layers];
- Refresh();
- }
- private void SetCorner(Vector2f v)
- {
- var tile = GetTile(v);
- var dif = tile - offset;
- if (dif.X == 0 && dif.Y == 0) return;
- offset = tile;
- if (Math.Abs(dif.X) > width/4 || Math.Abs(dif.Y) > height/4)
- {
- Refresh();
- return;
- }
- if (dif.X > 0) RefreshLocal(width - dif.X, 0, width, height);
- else RefreshLocal(0, 0, -dif.X, height);
- if (dif.Y > 0) RefreshLocal(0, height - dif.Y, width, height);
- else RefreshLocal(0, 0, width, -dif.Y);
- }
- private Vector2i GetTile(Vector2f pos)
- {
- var x = (int) (pos.X/TileSize);
- var y = (int) (pos.Y/TileSize);
- if (pos.X < 0) x--;
- if (pos.Y < 0) y--;
- return new Vector2i(x, y);
- }
- public void Refresh(int x, int y)
- {
- if(x < offset.X || x >= offset.X + width || y < offset.Y || y >= offset.Y + height)
- return;
- var vx = x % width;
- var vy = y % height;
- if (vx < 0) vx += width;
- if (vy < 0) vy += height;
- var index = (vx+vy * width) * 4 * Layers;
- var rec = new FloatRect(x * TileSize, y * TileSize, TileSize, TileSize);
- for (int i = 0; i < Layers; i++)
- {
- Color color;
- IntRect src;
- provider(x, y, i, out color, out src);
- Draw(index, rec, src, color);
- index += 4;
- }
- }
- private unsafe void Draw(int index, FloatRect rec, IntRect src, Color color)
- {
- fixed (Vertex* fptr = vertices)
- {
- var ptr = fptr + index;
- ptr->Position.X = rec.Left;
- ptr->Position.Y = rec.Top;
- ptr->TexCoords.X = src.Left;
- ptr->TexCoords.Y = src.Top;
- ptr->Color = color;
- ptr++;
- ptr->Position.X = rec.Left + rec.Width;
- ptr->Position.Y = rec.Top;
- ptr->TexCoords.X = src.Left + src.Width;
- ptr->TexCoords.Y = src.Top;
- ptr->Color = color;
- ptr++;
- ptr->Position.X = rec.Left + rec.Width;
- ptr->Position.Y = rec.Top + rec.Height;
- ptr->TexCoords.X = src.Left + src.Width;
- ptr->TexCoords.Y = src.Top + src.Height;
- ptr->Color = color;
- ptr++;
- ptr->Position.X = rec.Left;
- ptr->Position.Y = rec.Top + rec.Height;
- ptr->TexCoords.X = src.Left;
- ptr->TexCoords.Y = src.Top + src.Height;
- ptr->Color = color;
- }
- }
- public void Draw(RenderTarget rt, RenderStates states)
- {
- var view = rt.GetView();
- states.Texture = texture;
- SetSize(view.Size);
- SetCorner(rt.MapPixelToCoords(new Vector2i()));
- rt.Draw(vertices, PrimitiveType.Quads, states);
- }
- }
- class MinimalTest
- {
- public static void Main()
- {
- var rw = new RenderWindow(new VideoMode(800, 600), "Game");
- rw.Closed += (s, a) => rw.Close();
- var renderer = new MapRenderer(null, Provider);
- while (rw.IsOpen())
- {
- rw.Clear();
- rw.Draw(renderer);
- rw.Display();
- rw.DispatchEvents();
- }
- }
- private static void Provider(int x, int y, int layer, out Color color, out IntRect rec)
- {
- color = new Color((byte)(x*5), 50,50);
- rec = new IntRect(0,0,1,1);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement