Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using SummerSkin.Graphics;
- namespace SummerSkin.Logic {
- internal class Maze : SSModel {
- public static float unit = 1.5f;
- public static float hx, hy;
- public bool[] cells;
- public int[] distance;
- public int width, height;
- int pwidth;
- Graphics.Graphics graphics;
- VertexBuffer vertBuffer;
- IndexBuffer indexBuffer;
- Effect effect;
- Random rnd;
- public Maze(Graphics.Graphics graphics, int width, int height, string flag) {
- this.width = width;
- this.height = height;
- pwidth = (width + 1) * 2;
- hx = (float) width * unit / 2.0f;
- hy = (float) height * unit / 2.0f;
- this.graphics = graphics;
- cells = new bool[width * height];
- distance = new int[width * height];
- //seed = new Random().Next();
- rnd = new Random();
- int res = 32;
- Color[] colors = new Color[res * res];
- Texture2D tex =
- new Texture2D(
- graphics.graphics.GraphicsDevice,
- res,
- res,
- 1,
- TextureUsage.None,
- SurfaceFormat.Color
- );
- for(int i = 0; i < res * res; ++i)
- colors[i] =
- new Color(
- new Vector3(
- (float) rnd.Next(1000) / 1000.0f,
- 0,
- 0
- )
- );
- tex.SetData(colors);
- effect = SummerSkin.singleton.Content.Load<Effect>("Perlin");
- effect.Parameters["World"].SetValue(Matrix.Identity);
- effect.Parameters["View"].SetValue(graphics.cameraView);
- effect.Parameters["Projection"].SetValue(graphics.cameraProjection);
- effect.Parameters["Noise"].SetValue(tex);
- graphics.BaseModel = this;
- Model model = SummerSkin.singleton.Content.Load<Model>(flag);
- model.Root.Transform =
- Matrix.CreateScale(1.2f) *
- Matrix.CreateTranslation(0.0f, 10.0f, 0.0f) *
- Matrix.CreateRotationX(MathHelper.ToRadians(90.0f));
- graphics.Models.Add(model);
- }
- public void Generate(Player[] players) {
- float skew = 1.0f;
- switch(0) { // rnd.Next(2)
- case 0:
- effect.CurrentTechnique = effect.Techniques["Wood"];
- break;
- case 1:
- effect.CurrentTechnique = effect.Techniques["Marker"];
- break;
- case 2:
- effect.CurrentTechnique = effect.Techniques["Hedge"];
- break;
- }
- for(int i = 0; i < width * height; ++i)
- cells[i] = true;
- GenerateMaze(width / 2, height / 2);
- VertexPositionColorTexture[] verts = new VertexPositionColorTexture[2 * (width + 1) * (height + 1)]; // 2 points per cell
- int[] inds = new int[2 * 3 * 5 * width * height]; // 2 tris per face, 5 faces per cell
- int ind = 0;
- for(int i = 0, x = 0, y = 0; i < (width + 1) * (height + 1); ++i) {
- float sx = (float) x * unit - hx;
- float sy = (float) y * unit - hy;
- float signx = (sx >= 0) ? 1.0f : -1.0f;
- float signy = (sy >= 0) ? 1.0f : -1.0f;
- verts[ind++] =
- new VertexPositionColorTexture(
- new Vector3(
- sx - signx * skew * (1.0f - Math.Abs(sx / hx) + 0.2f),
- sy - signy * skew * (1.0f - Math.Abs(sy / hy) + 0.2f),
- 0.0f
- ),
- Color.White,
- new Vector2((float) x / (float) width, (float) y / (float) height)
- );
- verts[ind++] =
- new VertexPositionColorTexture(
- new Vector3(
- sx,
- sy,
- unit
- ),
- Color.Black,
- new Vector2((float) x / (float) width, (float) y / (float) height)
- );
- x = (x + 1) % (width + 1);
- if(x == 0)
- ++y;
- }
- ind = 0;
- for(int i = 0, x = 0, y = 0; i < width * height; ++i) {
- int off = (i + y) * 2;
- if(cells[i]) {
- int a = off;
- int A = off + 1;
- int b = off + 2;
- int B = off + 3;
- int c = off + pwidth;
- int C = off + pwidth + 1;
- int d = off + pwidth + 2;
- int D = off + pwidth + 3;
- inds[ind++] = a;
- inds[ind++] = A;
- inds[ind++] = B;
- inds[ind++] = B;
- inds[ind++] = b;
- inds[ind++] = a;
- inds[ind++] = D;
- inds[ind++] = C;
- inds[ind++] = c;
- inds[ind++] = D;
- inds[ind++] = d;
- inds[ind++] = c;
- inds[ind++] = a;
- inds[ind++] = A;
- inds[ind++] = C;
- inds[ind++] = C;
- inds[ind++] = c;
- inds[ind++] = a;
- inds[ind++] = D;
- inds[ind++] = B;
- inds[ind++] = b;
- inds[ind++] = D;
- inds[ind++] = d;
- inds[ind++] = b;
- inds[ind++] = C;
- inds[ind++] = B;
- inds[ind++] = A;
- inds[ind++] = B;
- inds[ind++] = D;
- inds[ind++] = C;
- } else {
- inds[ind++] = off + pwidth;
- inds[ind++] = off + 2;
- inds[ind++] = off;
- inds[ind++] = off + pwidth;
- inds[ind++] = off + pwidth + 2;
- inds[ind++] = off + 2;
- }
- x = (x + 1) % width;
- if(x == 0)
- ++y;
- }
- vertBuffer =
- new VertexBuffer(
- graphics.graphics.GraphicsDevice,
- typeof(VertexPositionColorTexture),
- (width + 1) * (height + 1) * 2,
- BufferUsage.WriteOnly
- );
- vertBuffer.SetData<VertexPositionColorTexture>(
- verts,
- 0,
- (width + 1) * (height + 1) * 2
- );
- indexBuffer =
- new IndexBuffer(
- graphics.graphics.GraphicsDevice,
- typeof(int),
- ind,
- BufferUsage.WriteOnly
- );
- indexBuffer.SetData<int>(
- inds,
- 0,
- ind
- );
- Place(players, -1);
- }
- public bool IsWall(int x, int y) {
- if(x < 0 || y < 0 || x >= width || y >= height)
- return false;
- if(cells[width * y + x] == false)
- return false;
- return true;
- }
- bool SubShouldEat(int x, int y) {
- if(
- x == 0 || x == width - 1 ||
- y == 0 || y == height - 1
- )
- return false;
- if(!IsWall(x, y))
- return false;
- return CellBorders(x, y) >= 2;
- }
- bool ShouldEat(int x, int y, bool recurse) {
- if(
- x == 0 || x == width - 1 ||
- y == 0 || y == height - 1
- )
- return false;
- if(!IsWall(x, y))
- return false;
- bool sA = IsWall(x - 1, y - 1);
- bool sC = IsWall(x + 1, y - 1);
- bool sF = IsWall(x - 1, y + 1);
- bool sH = IsWall(x + 1, y + 1);
- bool sB = IsWall(x, y - 1);
- bool sD = IsWall(x - 1, y);
- bool sE = IsWall(x + 1, y);
- bool sG = IsWall(x, y + 1);
- if(
- (sB && sE && !sC) ||
- (sE && sG && !sH) ||
- (sB && sD && !sA) ||
- (sD && sG && !sF)
- )
- return false;
- int count = CellBorders(x, y);
- if(
- count == 2 &&
- (
- (!sD && !sE) ||
- (!sB && !sG)
- ) &&
- rnd.Next(150) == 0
- )
- return true;
- if(count < 3) return false;
- return true;
- }
- int CellBorders(int x, int y) {
- bool sB = IsWall(x, y - 1);
- bool sD = IsWall(x - 1, y);
- bool sE = IsWall(x + 1, y);
- bool sG = IsWall(x, y + 1);
- int count = 0;
- if(sB) count++;
- if(sD) count++;
- if(sE) count++;
- if(sG) count++;
- return count;
- }
- void GenerateMaze(int x, int y) {
- int[] order = new int[4];
- List<int[]> toWalk = new List<int[]>();
- toWalk.Add(new int[]{x, y, 0, 0});
- while(toWalk.Count > 0) {
- int next = -1;
- for(int i = toWalk.Count-1; i >= 0; --i) {
- int tx = toWalk[i][0];
- int ty = toWalk[i][1];
- if(
- (tx == 0 || tx == width - 1) ||
- (ty == 0 || ty == height - 1)
- )
- next = i;
- }
- if(next == -1 && toWalk.Count > 20 && rnd.Next(3) != 0) {
- int low;
- int high;
- switch(rnd.Next(6)) {
- case 0:
- case 1:
- case 2:
- high = (int) ((float) toWalk.Count * 0.70);
- low = toWalk.Count;
- break;
- case 3:
- case 4:
- high = (int) ((float) toWalk.Count * 0.40);
- low = (int) ((float) toWalk.Count * 0.60);
- break;
- default:
- high = (int) ((float) toWalk.Count * 0.30);
- low = (int) ((float) toWalk.Count * 0.40);
- break;
- }
- if(high - low > 4)
- next = rnd.Next(low, high);
- else
- next = rnd.Next(toWalk.Count - 5, toWalk.Count);
- } else if(next == -1)
- next = rnd.Next(toWalk.Count);
- int[] cell = toWalk[next];
- toWalk.RemoveAt(next);
- x = cell[0];
- y = cell[1];
- int dist = cell[2];
- int dir = cell[3];
- if(!ShouldEat(x, y, true))
- continue;
- cells[width * y + x] = false;
- distance[width * y + x] = dist;
- toWalk.Add(new int[] { x, y - 1, dist + 1, 0 });
- toWalk.Add(new int[] { x - 1, y, dist + 1, 1 });
- toWalk.Add(new int[] { x + 1, y, dist + 1, 2 });
- toWalk.Add(new int[] { x, y + 1, dist + 1, 3 });
- switch(dir) {
- case 0:
- toWalk.Add(new int[] { x, y - 1, dist + 1, 0 });
- toWalk.Add(new int[] { x, y - 1, dist + 1, 0 });
- toWalk.Add(new int[] { x, y - 1, dist + 1, rnd.Next(2) == 0 ? 1 : 2 });
- break;
- case 1:
- toWalk.Add(new int[] { x - 1, y, dist + 1, 1 });
- toWalk.Add(new int[] { x - 1, y, dist + 1, 1 });
- toWalk.Add(new int[] { x - 1, y, dist + 1, rnd.Next(2) == 0 ? 0 : 3 });
- break;
- case 2:
- toWalk.Add(new int[] { x + 1, y, dist + 1, 2 });
- toWalk.Add(new int[] { x + 1, y, dist + 1, 2 });
- toWalk.Add(new int[] { x + 1, y, dist + 1, rnd.Next(2) == 0 ? 0 : 3 });
- break;
- case 3:
- toWalk.Add(new int[] { x, y + 1, dist + 1, 3 });
- toWalk.Add(new int[] { x, y + 1, dist + 1, 3 });
- toWalk.Add(new int[] { x, y + 1, dist + 1, rnd.Next(2) == 0 ? 1 : 2 });
- break;
- }
- }
- /*
- // Remove single jutting cells
- x = y = 0;
- for(int i = 0; i < cells.Length; ++i, ++x) {
- if(x == width) {
- x = 0;
- ++y;
- }
- if(IsWall(x, y))
- continue;
- if(CellBorders(x, y) == 3) {
- if(
- (!IsWall(x, y - 1) && CellBorders(x, y - 1) < 2) ||
- (!IsWall(x + 1, y) && CellBorders(x + 1, y) < 2) ||
- (!IsWall(x, y + 1) && CellBorders(x, y + 1) < 2) ||
- (!IsWall(x - 1, y) && CellBorders(x - 1, y) < 2)
- )
- cells[i] = true;
- }
- }*/
- }
- public int HowFar(int x, int y) {
- if(x == -1 && y == -1)
- return 0;
- else
- return distance[width * y + x];
- }
- public void Place(Player[] players, int avg) {
- int i = 0;
- int[] sectors = new int[] {
- 0, height / 2,
- width / 2, 0,
- 0, 0,
- width / 2, height / 2
- };
- int[] dists = new int[players.Length];
- int average = avg;
- foreach(Player player in players) {
- int dist = -1;
- int sx = sectors[i*2], sy = sectors[i*2+1];
- int pos = width*sy + sx;
- for(int x = sx, y = sy; ; ++x, ++pos) {
- if(x == sx + (width / 2)) {
- x = sx;
- if(++y >= (sy + (height / 2)))
- break;
- pos = width*y + x;
- }
- if(cells[pos])
- continue;
- if(distance[pos] > dist && (average == -1 || distance[pos] <= average)) {
- dist = distance[pos];
- player.position[0] = x;
- player.position[1] = y;
- }
- }
- dists[i] = dist;
- ++i;
- average = 0;
- for(int pl = 0; pl < i; ++pl)
- average += dists[pl];
- average = average / i;
- average += (int) ((float) average / 20.0f);
- }
- if(avg != -1)
- Place(players, average);
- }
- public void Draw() {
- GraphicsDevice device = graphics.graphics.GraphicsDevice;
- device.VertexDeclaration =
- new VertexDeclaration(
- device,
- VertexPositionColorTexture.VertexElements
- );
- device.Vertices[0].SetSource(
- vertBuffer,
- 0,
- VertexPositionColorTexture.SizeInBytes
- );
- device.Indices = indexBuffer;
- effect.Begin();
- foreach(EffectPass pass in effect.CurrentTechnique.Passes) {
- pass.Begin();
- device.DrawIndexedPrimitives(
- PrimitiveType.TriangleList,
- 0,
- 0,
- vertBuffer.SizeInBytes / VertexPositionColorTexture.SizeInBytes,
- 0,
- indexBuffer.SizeInBytes / sizeof(int) / 3
- );
- pass.End();
- }
- effect.End();
- }
- }
- }
Add Comment
Please, Sign In to add comment