Pipes (Jungle Altar)

JungleAltar

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);
  }  
}

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top