Guest User

Untitled

a guest
Dec 17th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.76 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. using Microsoft.Xna.Framework;
  6. using Microsoft.Xna.Framework.Graphics;
  7.  
  8. using SummerSkin.Graphics;
  9.  
  10. namespace SummerSkin.Logic {
  11. internal class Maze : SSModel {
  12. public static float unit = 1.5f;
  13. public static float hx, hy;
  14. public bool[] cells;
  15. public int[] distance;
  16. public int width, height;
  17. int pwidth;
  18. Graphics.Graphics graphics;
  19.  
  20. VertexBuffer vertBuffer;
  21. IndexBuffer indexBuffer;
  22.  
  23. Effect effect;
  24.  
  25. Random rnd;
  26.  
  27. public Maze(Graphics.Graphics graphics, int width, int height, string flag) {
  28. this.width = width;
  29. this.height = height;
  30. pwidth = (width + 1) * 2;
  31. hx = (float) width * unit / 2.0f;
  32. hy = (float) height * unit / 2.0f;
  33.  
  34. this.graphics = graphics;
  35. cells = new bool[width * height];
  36. distance = new int[width * height];
  37.  
  38. //seed = new Random().Next();
  39. rnd = new Random();
  40.  
  41. int res = 32;
  42. Color[] colors = new Color[res * res];
  43. Texture2D tex =
  44. new Texture2D(
  45. graphics.graphics.GraphicsDevice,
  46. res,
  47. res,
  48. 1,
  49. TextureUsage.None,
  50. SurfaceFormat.Color
  51. );
  52. for(int i = 0; i < res * res; ++i)
  53. colors[i] =
  54. new Color(
  55. new Vector3(
  56. (float) rnd.Next(1000) / 1000.0f,
  57. 0,
  58. 0
  59. )
  60. );
  61. tex.SetData(colors);
  62.  
  63. effect = SummerSkin.singleton.Content.Load<Effect>("Perlin");
  64.  
  65. effect.Parameters["World"].SetValue(Matrix.Identity);
  66. effect.Parameters["View"].SetValue(graphics.cameraView);
  67. effect.Parameters["Projection"].SetValue(graphics.cameraProjection);
  68. effect.Parameters["Noise"].SetValue(tex);
  69.  
  70. graphics.BaseModel = this;
  71.  
  72. Model model = SummerSkin.singleton.Content.Load<Model>(flag);
  73. model.Root.Transform =
  74. Matrix.CreateScale(1.2f) *
  75. Matrix.CreateTranslation(0.0f, 10.0f, 0.0f) *
  76. Matrix.CreateRotationX(MathHelper.ToRadians(90.0f));
  77. graphics.Models.Add(model);
  78. }
  79.  
  80. public void Generate(Player[] players) {
  81. float skew = 1.0f;
  82.  
  83. switch(0) { // rnd.Next(2)
  84. case 0:
  85. effect.CurrentTechnique = effect.Techniques["Wood"];
  86. break;
  87. case 1:
  88. effect.CurrentTechnique = effect.Techniques["Marker"];
  89. break;
  90. case 2:
  91. effect.CurrentTechnique = effect.Techniques["Hedge"];
  92. break;
  93. }
  94.  
  95. for(int i = 0; i < width * height; ++i)
  96. cells[i] = true;
  97.  
  98. GenerateMaze(width / 2, height / 2);
  99.  
  100. VertexPositionColorTexture[] verts = new VertexPositionColorTexture[2 * (width + 1) * (height + 1)]; // 2 points per cell
  101. int[] inds = new int[2 * 3 * 5 * width * height]; // 2 tris per face, 5 faces per cell
  102.  
  103. int ind = 0;
  104. for(int i = 0, x = 0, y = 0; i < (width + 1) * (height + 1); ++i) {
  105. float sx = (float) x * unit - hx;
  106. float sy = (float) y * unit - hy;
  107. float signx = (sx >= 0) ? 1.0f : -1.0f;
  108. float signy = (sy >= 0) ? 1.0f : -1.0f;
  109. verts[ind++] =
  110. new VertexPositionColorTexture(
  111. new Vector3(
  112. sx - signx * skew * (1.0f - Math.Abs(sx / hx) + 0.2f),
  113. sy - signy * skew * (1.0f - Math.Abs(sy / hy) + 0.2f),
  114. 0.0f
  115. ),
  116. Color.White,
  117. new Vector2((float) x / (float) width, (float) y / (float) height)
  118. );
  119. verts[ind++] =
  120. new VertexPositionColorTexture(
  121. new Vector3(
  122. sx,
  123. sy,
  124. unit
  125. ),
  126. Color.Black,
  127. new Vector2((float) x / (float) width, (float) y / (float) height)
  128. );
  129.  
  130. x = (x + 1) % (width + 1);
  131. if(x == 0)
  132. ++y;
  133. }
  134.  
  135. ind = 0;
  136. for(int i = 0, x = 0, y = 0; i < width * height; ++i) {
  137. int off = (i + y) * 2;
  138.  
  139. if(cells[i]) {
  140. int a = off;
  141. int A = off + 1;
  142. int b = off + 2;
  143. int B = off + 3;
  144. int c = off + pwidth;
  145. int C = off + pwidth + 1;
  146. int d = off + pwidth + 2;
  147. int D = off + pwidth + 3;
  148.  
  149. inds[ind++] = a;
  150. inds[ind++] = A;
  151. inds[ind++] = B;
  152.  
  153. inds[ind++] = B;
  154. inds[ind++] = b;
  155. inds[ind++] = a;
  156.  
  157. inds[ind++] = D;
  158. inds[ind++] = C;
  159. inds[ind++] = c;
  160.  
  161. inds[ind++] = D;
  162. inds[ind++] = d;
  163. inds[ind++] = c;
  164.  
  165. inds[ind++] = a;
  166. inds[ind++] = A;
  167. inds[ind++] = C;
  168.  
  169. inds[ind++] = C;
  170. inds[ind++] = c;
  171. inds[ind++] = a;
  172.  
  173. inds[ind++] = D;
  174. inds[ind++] = B;
  175. inds[ind++] = b;
  176.  
  177. inds[ind++] = D;
  178. inds[ind++] = d;
  179. inds[ind++] = b;
  180.  
  181. inds[ind++] = C;
  182. inds[ind++] = B;
  183. inds[ind++] = A;
  184.  
  185. inds[ind++] = B;
  186. inds[ind++] = D;
  187. inds[ind++] = C;
  188. } else {
  189. inds[ind++] = off + pwidth;
  190. inds[ind++] = off + 2;
  191. inds[ind++] = off;
  192.  
  193. inds[ind++] = off + pwidth;
  194. inds[ind++] = off + pwidth + 2;
  195. inds[ind++] = off + 2;
  196. }
  197.  
  198. x = (x + 1) % width;
  199. if(x == 0)
  200. ++y;
  201. }
  202.  
  203. vertBuffer =
  204. new VertexBuffer(
  205. graphics.graphics.GraphicsDevice,
  206. typeof(VertexPositionColorTexture),
  207. (width + 1) * (height + 1) * 2,
  208. BufferUsage.WriteOnly
  209. );
  210. vertBuffer.SetData<VertexPositionColorTexture>(
  211. verts,
  212. 0,
  213. (width + 1) * (height + 1) * 2
  214. );
  215.  
  216. indexBuffer =
  217. new IndexBuffer(
  218. graphics.graphics.GraphicsDevice,
  219. typeof(int),
  220. ind,
  221. BufferUsage.WriteOnly
  222. );
  223. indexBuffer.SetData<int>(
  224. inds,
  225. 0,
  226. ind
  227. );
  228.  
  229. Place(players, -1);
  230. }
  231.  
  232. public bool IsWall(int x, int y) {
  233. if(x < 0 || y < 0 || x >= width || y >= height)
  234. return false;
  235.  
  236. if(cells[width * y + x] == false)
  237. return false;
  238.  
  239. return true;
  240. }
  241.  
  242. bool SubShouldEat(int x, int y) {
  243. if(
  244. x == 0 || x == width - 1 ||
  245. y == 0 || y == height - 1
  246. )
  247. return false;
  248.  
  249. if(!IsWall(x, y))
  250. return false;
  251.  
  252. return CellBorders(x, y) >= 2;
  253. }
  254.  
  255. bool ShouldEat(int x, int y, bool recurse) {
  256. if(
  257. x == 0 || x == width - 1 ||
  258. y == 0 || y == height - 1
  259. )
  260. return false;
  261.  
  262. if(!IsWall(x, y))
  263. return false;
  264.  
  265. bool sA = IsWall(x - 1, y - 1);
  266. bool sC = IsWall(x + 1, y - 1);
  267. bool sF = IsWall(x - 1, y + 1);
  268. bool sH = IsWall(x + 1, y + 1);
  269.  
  270. bool sB = IsWall(x, y - 1);
  271. bool sD = IsWall(x - 1, y);
  272. bool sE = IsWall(x + 1, y);
  273. bool sG = IsWall(x, y + 1);
  274.  
  275. if(
  276. (sB && sE && !sC) ||
  277. (sE && sG && !sH) ||
  278. (sB && sD && !sA) ||
  279. (sD && sG && !sF)
  280. )
  281. return false;
  282.  
  283. int count = CellBorders(x, y);
  284.  
  285. if(
  286. count == 2 &&
  287. (
  288. (!sD && !sE) ||
  289. (!sB && !sG)
  290. ) &&
  291. rnd.Next(150) == 0
  292. )
  293. return true;
  294.  
  295. if(count < 3) return false;
  296.  
  297. return true;
  298. }
  299.  
  300. int CellBorders(int x, int y) {
  301. bool sB = IsWall(x, y - 1);
  302. bool sD = IsWall(x - 1, y);
  303. bool sE = IsWall(x + 1, y);
  304. bool sG = IsWall(x, y + 1);
  305.  
  306. int count = 0;
  307. if(sB) count++;
  308. if(sD) count++;
  309. if(sE) count++;
  310. if(sG) count++;
  311.  
  312. return count;
  313. }
  314.  
  315. void GenerateMaze(int x, int y) {
  316. int[] order = new int[4];
  317.  
  318. List<int[]> toWalk = new List<int[]>();
  319. toWalk.Add(new int[]{x, y, 0, 0});
  320.  
  321. while(toWalk.Count > 0) {
  322. int next = -1;
  323. for(int i = toWalk.Count-1; i >= 0; --i) {
  324. int tx = toWalk[i][0];
  325. int ty = toWalk[i][1];
  326.  
  327. if(
  328. (tx == 0 || tx == width - 1) ||
  329. (ty == 0 || ty == height - 1)
  330. )
  331. next = i;
  332. }
  333.  
  334. if(next == -1 && toWalk.Count > 20 && rnd.Next(3) != 0) {
  335. int low;
  336. int high;
  337.  
  338. switch(rnd.Next(6)) {
  339. case 0:
  340. case 1:
  341. case 2:
  342. high = (int) ((float) toWalk.Count * 0.70);
  343. low = toWalk.Count;
  344. break;
  345. case 3:
  346. case 4:
  347. high = (int) ((float) toWalk.Count * 0.40);
  348. low = (int) ((float) toWalk.Count * 0.60);
  349. break;
  350. default:
  351. high = (int) ((float) toWalk.Count * 0.30);
  352. low = (int) ((float) toWalk.Count * 0.40);
  353. break;
  354. }
  355. if(high - low > 4)
  356. next = rnd.Next(low, high);
  357. else
  358. next = rnd.Next(toWalk.Count - 5, toWalk.Count);
  359. } else if(next == -1)
  360. next = rnd.Next(toWalk.Count);
  361. int[] cell = toWalk[next];
  362. toWalk.RemoveAt(next);
  363. x = cell[0];
  364. y = cell[1];
  365. int dist = cell[2];
  366. int dir = cell[3];
  367.  
  368. if(!ShouldEat(x, y, true))
  369. continue;
  370. cells[width * y + x] = false;
  371. distance[width * y + x] = dist;
  372.  
  373. toWalk.Add(new int[] { x, y - 1, dist + 1, 0 });
  374. toWalk.Add(new int[] { x - 1, y, dist + 1, 1 });
  375. toWalk.Add(new int[] { x + 1, y, dist + 1, 2 });
  376. toWalk.Add(new int[] { x, y + 1, dist + 1, 3 });
  377.  
  378. switch(dir) {
  379. case 0:
  380. toWalk.Add(new int[] { x, y - 1, dist + 1, 0 });
  381. toWalk.Add(new int[] { x, y - 1, dist + 1, 0 });
  382. toWalk.Add(new int[] { x, y - 1, dist + 1, rnd.Next(2) == 0 ? 1 : 2 });
  383. break;
  384. case 1:
  385. toWalk.Add(new int[] { x - 1, y, dist + 1, 1 });
  386. toWalk.Add(new int[] { x - 1, y, dist + 1, 1 });
  387. toWalk.Add(new int[] { x - 1, y, dist + 1, rnd.Next(2) == 0 ? 0 : 3 });
  388. break;
  389. case 2:
  390. toWalk.Add(new int[] { x + 1, y, dist + 1, 2 });
  391. toWalk.Add(new int[] { x + 1, y, dist + 1, 2 });
  392. toWalk.Add(new int[] { x + 1, y, dist + 1, rnd.Next(2) == 0 ? 0 : 3 });
  393. break;
  394. case 3:
  395. toWalk.Add(new int[] { x, y + 1, dist + 1, 3 });
  396. toWalk.Add(new int[] { x, y + 1, dist + 1, 3 });
  397. toWalk.Add(new int[] { x, y + 1, dist + 1, rnd.Next(2) == 0 ? 1 : 2 });
  398. break;
  399. }
  400. }
  401.  
  402. /*
  403. // Remove single jutting cells
  404. x = y = 0;
  405. for(int i = 0; i < cells.Length; ++i, ++x) {
  406. if(x == width) {
  407. x = 0;
  408. ++y;
  409. }
  410.  
  411. if(IsWall(x, y))
  412. continue;
  413.  
  414. if(CellBorders(x, y) == 3) {
  415. if(
  416. (!IsWall(x, y - 1) && CellBorders(x, y - 1) < 2) ||
  417. (!IsWall(x + 1, y) && CellBorders(x + 1, y) < 2) ||
  418. (!IsWall(x, y + 1) && CellBorders(x, y + 1) < 2) ||
  419. (!IsWall(x - 1, y) && CellBorders(x - 1, y) < 2)
  420. )
  421. cells[i] = true;
  422. }
  423. }*/
  424. }
  425.  
  426. public int HowFar(int x, int y) {
  427. if(x == -1 && y == -1)
  428. return 0;
  429. else
  430. return distance[width * y + x];
  431. }
  432.  
  433. public void Place(Player[] players, int avg) {
  434. int i = 0;
  435. int[] sectors = new int[] {
  436. 0, height / 2,
  437. width / 2, 0,
  438. 0, 0,
  439. width / 2, height / 2
  440. };
  441. int[] dists = new int[players.Length];
  442. int average = avg;
  443. foreach(Player player in players) {
  444. int dist = -1;
  445. int sx = sectors[i*2], sy = sectors[i*2+1];
  446. int pos = width*sy + sx;
  447. for(int x = sx, y = sy; ; ++x, ++pos) {
  448. if(x == sx + (width / 2)) {
  449. x = sx;
  450. if(++y >= (sy + (height / 2)))
  451. break;
  452. pos = width*y + x;
  453. }
  454.  
  455. if(cells[pos])
  456. continue;
  457.  
  458. if(distance[pos] > dist && (average == -1 || distance[pos] <= average)) {
  459. dist = distance[pos];
  460. player.position[0] = x;
  461. player.position[1] = y;
  462. }
  463. }
  464.  
  465. dists[i] = dist;
  466.  
  467. ++i;
  468.  
  469. average = 0;
  470. for(int pl = 0; pl < i; ++pl)
  471. average += dists[pl];
  472. average = average / i;
  473. average += (int) ((float) average / 20.0f);
  474. }
  475.  
  476. if(avg != -1)
  477. Place(players, average);
  478. }
  479.  
  480. public void Draw() {
  481. GraphicsDevice device = graphics.graphics.GraphicsDevice;
  482.  
  483. device.VertexDeclaration =
  484. new VertexDeclaration(
  485. device,
  486. VertexPositionColorTexture.VertexElements
  487. );
  488.  
  489. device.Vertices[0].SetSource(
  490. vertBuffer,
  491. 0,
  492. VertexPositionColorTexture.SizeInBytes
  493. );
  494. device.Indices = indexBuffer;
  495.  
  496. effect.Begin();
  497.  
  498. foreach(EffectPass pass in effect.CurrentTechnique.Passes) {
  499. pass.Begin();
  500.  
  501. device.DrawIndexedPrimitives(
  502. PrimitiveType.TriangleList,
  503. 0,
  504. 0,
  505. vertBuffer.SizeInBytes / VertexPositionColorTexture.SizeInBytes,
  506. 0,
  507. indexBuffer.SizeInBytes / sizeof(int) / 3
  508. );
  509.  
  510. pass.End();
  511. }
  512.  
  513. effect.End();
  514. }
  515. }
  516. }
Add Comment
Please, Sign In to add comment