# Marching Squares

#### Difficulté: Avancé

Part 2 of 9: Marching Squares.

## Marching Squares

Avancé Procedural Cave Generation tutorial

### Code snippet

``````using UnityEngine;
using System.Collections;
using System;

public class MapGenerator : MonoBehaviour {

public int width;
public int height;

public string seed;
public bool useRandomSeed;

[Range(0,100)]
public int randomFillPercent;

int[,] map;

void Start() {
GenerateMap();
}

void Update() {
if (Input.GetMouseButtonDown(0)) {
GenerateMap();
}
}

void GenerateMap() {
map = new int[width,height];
RandomFillMap();

for (int i = 0; i < 5; i ++) {
SmoothMap();
}

MeshGenerator meshGen = GetComponent<MeshGenerator>();
meshGen.GenerateMesh(map, 1);
}

void RandomFillMap() {
if (useRandomSeed) {
seed = Time.time.ToString();
}

System.Random pseudoRandom = new System.Random(seed.GetHashCode());

for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
if (x == 0 || x == width-1 || y == 0 || y == height -1) {
map[x,y] = 1;
}
else {
map[x,y] = (pseudoRandom.Next(0,100) < randomFillPercent)? 1: 0;
}
}
}
}

void SmoothMap() {
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
int neighbourWallTiles = GetSurroundingWallCount(x,y);

if (neighbourWallTiles > 4)
map[x,y] = 1;
else if (neighbourWallTiles < 4)
map[x,y] = 0;

}
}
}

int GetSurroundingWallCount(int gridX, int gridY) {
int wallCount = 0;
for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX ++) {
for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY ++) {
if (neighbourX >= 0 && neighbourX < width && neighbourY >= 0 && neighbourY < height) {
if (neighbourX != gridX || neighbourY != gridY) {
wallCount += map[neighbourX,neighbourY];
}
}
else {
wallCount ++;
}
}
}

return wallCount;
}

void OnDrawGizmos() {
/*
if (map != null) {
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
Gizmos.color = (map[x,y] == 1)?Color.black:Color.white;
Vector3 pos = new Vector3(-width/2 + x + .5f,0, -height/2 + y+.5f);
Gizmos.DrawCube(pos,Vector3.one);
}
}
}
*/
}

}``````

### Code snippet

``````using UnityEngine;
using System.Collections;

public class MeshGenerator : MonoBehaviour {

public SquareGrid squareGrid;

public void GenerateMesh(int[,] map, float squareSize) {
squareGrid = new SquareGrid(map, squareSize);
}

void OnDrawGizmos() {
if (squareGrid != null) {
for (int x = 0; x < squareGrid.squares.GetLength(0); x ++) {
for (int y = 0; y < squareGrid.squares.GetLength(1); y ++) {

Gizmos.color = (squareGrid.squares[x,y].topLeft.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].topLeft.position, Vector3.one * .4f);

Gizmos.color = (squareGrid.squares[x,y].topRight.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].topRight.position, Vector3.one * .4f);

Gizmos.color = (squareGrid.squares[x,y].bottomRight.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].bottomRight.position, Vector3.one * .4f);

Gizmos.color = (squareGrid.squares[x,y].bottomLeft.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].bottomLeft.position, Vector3.one * .4f);

Gizmos.color = Color.grey;
Gizmos.DrawCube(squareGrid.squares[x,y].centreTop.position, Vector3.one * .15f);
Gizmos.DrawCube(squareGrid.squares[x,y].centreRight.position, Vector3.one * .15f);
Gizmos.DrawCube(squareGrid.squares[x,y].centreBottom.position, Vector3.one * .15f);
Gizmos.DrawCube(squareGrid.squares[x,y].centreLeft.position, Vector3.one * .15f);

}
}
}
}

public class SquareGrid {
public Square[,] squares;

public SquareGrid(int[,] map, float squareSize) {
int nodeCountX = map.GetLength(0);
int nodeCountY = map.GetLength(1);
float mapWidth = nodeCountX * squareSize;
float mapHeight = nodeCountY * squareSize;

ControlNode[,] controlNodes = new ControlNode[nodeCountX,nodeCountY];

for (int x = 0; x < nodeCountX; x ++) {
for (int y = 0; y < nodeCountY; y ++) {
Vector3 pos = new Vector3(-mapWidth/2 + x * squareSize + squareSize/2, 0, -mapHeight/2 + y * squareSize + squareSize/2);
controlNodes[x,y] = new ControlNode(pos,map[x,y] == 1, squareSize);
}
}

squares = new Square[nodeCountX -1,nodeCountY -1];
for (int x = 0; x < nodeCountX-1; x ++) {
for (int y = 0; y < nodeCountY-1; y ++) {
squares[x,y] = new Square(controlNodes[x,y+1], controlNodes[x+1,y+1], controlNodes[x+1,y], controlNodes[x,y]);
}
}

}
}

public class Square {

public ControlNode topLeft, topRight, bottomRight, bottomLeft;
public Node centreTop, centreRight, centreBottom, centreLeft;

public Square (ControlNode _topLeft, ControlNode _topRight, ControlNode _bottomRight, ControlNode _bottomLeft) {
topLeft = _topLeft;
topRight = _topRight;
bottomRight = _bottomRight;
bottomLeft = _bottomLeft;

centreTop = topLeft.right;
centreRight = bottomRight.above;
centreBottom = bottomLeft.right;
centreLeft = bottomLeft.above;
}
}

public class Node {
public Vector3 position;
public int vertexIndex = -1;

public Node(Vector3 _pos) {
position = _pos;
}
}

public class ControlNode : Node {

public bool active;
public Node above, right;

public ControlNode(Vector3 _pos, bool _active, float squareSize) : base(_pos) {
active = _active;
above = new Node(position + Vector3.forward * squareSize/2f);
right = new Node(position + Vector3.right * squareSize/2f);
}

}
}``````

#### Procedural Cave Generation tutorial

1. Cellular Automata
2. Marching Squares
3. Creating Meshes