This is a version of the game Pipes with a mayan theme.
[button url=”https://gamelogic.co.za/examples/grids/jungle-altar/” size=”medium”]PLAY GAME[/button]
Note: You need the Unity Web Plugin to play this example.
Main Game Logic
public class Pipes : CSMonoBehaviour { private readonly PointyHexPoint offset = new PointyHexPoint(1, 1); /* In this example each tile image has a binary presentation with six digits that correponds to the six edges of the hex and indicate whether edges have pipes through them or not. This arrays maps the image number to the sprite frame index. */ private int[] frameIndices = { 0, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, -1, -1, 7, -1, -1, -1, 8, -1, 9, -1, 10, -1, -1, -1, 11, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13 }; public PipesCell cellPrefab; public GameObject root; private Vector2 hexDimensions = new Vector2(74, 65); private PointyHexGrid grid; private IMap3D map; private Rect screenRect; private int screenshotCount; public void Start() { UnityEngine.Random.seed = 5; BuildGrid(); RandomRotateCells(); UpdateHighlights(); } private void BuildGrid() { grid = PointyHexGrid.Hexagon(width); map = new PointyHexMap(hexDimensions) .WithWindow(ExampleUtils.ScreenRect) .AlignMiddelCenter(grid) .AnchorCellMiddelCenter() .To3DXY(); var edgeGrid = grid.MakeEdgeGrid(); foreach(PointyRhombPoint point in edgeGrid) { edgeGrid[point] = UnityEngine.Random.Range(0, 2); } foreach (PointyHexPoint point in grid) { PipesCell cell = Instantiate (cellPrefab); Vector3 rPoint = map[point]; cell.transform.parent = root.transform; cell.transform.localScale = Vector3.one; cell.transform.localPosition = rPoint; cell.transform.SetRotationZ(-30); grid[point] = cell; SetCellSprite(edgeGrid, point, cell); } } private void RandomRotateCells() { foreach (PointyHexPoint point in grid) { int rotationCount = UnityEngine.Random.Range (0, 6); for (int i = 0; i < rotationCount; i++) { grid [point].RotateCW(); } } } private void UpdateHighlights() { foreach (var point in grid) { UpdateHighlight(point); } } private void SetCellSprite(IGrid<int, pointyrhombpoint=""> edgeGrid, PointyHexPoint point, PipesCell cell) { var edges = from edgePoint in point.GetEdges() select edgeGrid [edgePoint]; int imageIndex = edges.Reverse().Aggregate ((x, y) => (x << 1) + y); // Because images are flat hex, not pointy, and we want them pointy float zRotation = -30; for (int i = 0; i < 6; i++) { if (frameIndices [imageIndex] != -1) //we found it { //so we can use it cell.SetFrame (frameIndices[imageIndex]); cell.Image.transform.SetRotationZ (zRotation); break; } //While we cannot find the sprite, transform and check again zRotation += 60; imageIndex = RotateEdgeNumberClockWise (imageIndex); } cell.EdgeData = edges.ToList(); } public int RotateEdgeNumberClockWise(int edge) { return ((edge & 1) << 5) + (edge >> 1); } public int RotateEdgeNumberCounterClockWise(int edge) { return ((edge << 1) & 63) + (edge >> 5); } public void Update() { if(Input.GetMouseButtonDown(0)) { Vector3 worldPosition = ExampleUtils.ScreenToWorld(root, Input.mousePosition); PointyHexPoint hexPoint = map[worldPosition]; if(grid.Contains(hexPoint)) { grid[hexPoint].RotateCW(); UpdateHighlight(hexPoint); foreach(var neighbor in grid.GetNeighbors(hexPoint)) { UpdateHighlight(neighbor); } } } else if(Input.GetMouseButtonDown(1)) { Vector3 worldPosition = ExampleUtils.ScreenToWorld(root, Input.mousePosition); PointyHexPoint hexPoint = map[worldPosition]; if(grid.Contains(hexPoint)) { grid[hexPoint].RotateCCW(); UpdateHighlight(hexPoint); foreach(var neighbor in grid.GetNeighbors(hexPoint)) { UpdateHighlight(neighbor); } } } if(HasGameFinished()) { Debug.Log ("Game Ended!"); } } public bool HasGameFinished() { return grid.All(IsClosed); } public void UpdateHighlight(PointyHexPoint point) { grid[point].HighlightOn = IsClosed(point); } public bool IsClosed(PointyHexPoint point) { var neighbors = grid.GetAllNeighbors(point).ToList(); bool isClosed = true; //We use for loop so that we can use the index in the access operation below for (int i = 0; i < neighbors.Count(); i++) { if (grid.Contains(neighbors[i])) { //(i + 3) % 6 is the opposite neighbor //Here we abuse the fact that neighbors are returned in (anti-clockwise) order. if (grid[point].EdgeData[i] != grid[neighbors[i]].EdgeData[(i+3)%6]) { isClosed = false; } } } return isClosed; } }
Pipes Cell
using System.Linq; using System.Collections.Generic; using UnityEngine; public class PipesCell : Cell { private List edgeData; public List EdgeData { get { return edgeData; } set { edgeData = value; } } public MonoBehaviour Image { get { return image; } } public void RotateCW() { var newEdgeData = edgeData.ButFirst().ToList(); newEdgeData.Add(edgeData.First()); edgeData = newEdgeData; image.transform.RotateAroundZ(-60); } public void RotateCCW() { List newEdgeData = edgeData.ButLast().ToList(); newEdgeData.Insert(0, edgeData.Last()); edgeData = newEdgeData; image.transform.RotateAroundZ(60); } }