Blocks Slider Example Code

using System;
using System.Collections.Generic;
using System.Linq;

using UnityEngine;

using Gamelogic.Grids;

public class BlocksSlider : GLMonoBehaviour
{
  private enum BlockType
  {
    Vertical,
    Horizontal
  }

  private class Block
  {
    private Dictionary tileObjects;
    private int blockID;

    public int ID
    {
      get
      {
        return blockID;
      }
    }

    public IEnumerable TilePoints
    {
      get
      {
        return tileObjects.Keys;
      }
    }

    public IEnumerable TileObjects
    {
      get
      {
        return tileObjects.Values;
      }
    }

    public RectPoint CurrentPosition
    {
      get;
      set;
    }

    public Block(int blockID)
    {
      tileObjects = new Dictionary();
      this.blockID = blockID;
    }

    //All tile points are relative to CurrentPosition
    public void AddTile(RectPoint tilePoint, Cell tileObject)
    {
      tileObjects[tilePoint] = tileObject;
    }

    public void UpdateTilePositions(IMap3D map)
    {
      foreach (RectPoint tilePoint in TilePoints)
      {
        tileObjects[tilePoint].transform.localPosition = map[CurrentPosition + tilePoint];
      }
    }

    public void Clear()
    {
      tileObjects.Clear();
    }
  }

  public GameObject uiRoot;
  public Cell cellPrefab;

  private RectGrid tileGrid;
  private RectGrid blocksGrid;
  private IMap3D map;
  private Block currentBlock;
  private int currentBlockIndex;
  private List blocks;
  private RectPoint winPosition;

  private Dictionary keysToDirections = new Dictionary
  {
    {KeyCode.UpArrow, RectPoint.North},
    {KeyCode.LeftArrow, RectPoint.West},
    {KeyCode.DownArrow, RectPoint.South},
    {KeyCode.RightArrow, RectPoint.East},
  };

  public void Start()
  {
    BuildPuzzle();
  }

  private void Update()
  {
    if (Input.GetMouseButtonDown(0))
    {
      Vector3 worldPosition = ExampleUtils.ScreenToWorld_NGUI(uiRoot, Input.mousePosition);
      RectPoint rectPosition = map[worldPosition];

      if (tileGrid.Contains(rectPosition))
      {
        if (blocksGrid[rectPosition] != null)
        {
          SetHighlight(currentBlock, false);
          currentBlock = blocksGrid[rectPosition];
          SetHighlight(currentBlock, true);
        }
      }
    }

    foreach (KeyCode key in keysToDirections.Keys)
    {
      if (Input.GetKeyDown(key))
      {
        Debug.Log(key);

        RectPoint newPoint = currentBlock.CurrentPosition + keysToDirections[key];

        if (CanOccupy(currentBlock, newPoint))
        {
          RemoveTile(currentBlock);
          PlaceTile(currentBlock, newPoint);
          currentBlock.UpdateTilePositions(map);
        }
      }
    }

    if (Input.GetKeyDown(KeyCode.Tab))
    {
      SetHighlight(currentBlock, false);

      if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
      {
        currentBlockIndex--;
      }
      else
      {
        currentBlockIndex++;
      }

      currentBlockIndex = currentBlockIndex + blocks.Count() % blocks.Count();
      currentBlock = blocks[currentBlockIndex];
      SetHighlight(currentBlock, true);
    }

    if (blocksGrid[winPosition] != null && blocksGrid[winPosition].ID == 0)
    {
      Debug.Log("Game finished!");
    }
  }

  private void BuildPuzzle()
  {
    int size = 5;

    tileGrid = RectGrid.Rectangle(size, size);
    blocksGrid = (RectGrid)tileGrid.CloneStructure();

    map = new RectMap(new Vector2(40, 40))
      .AnchorCellMiddelCenter()
      .WithWindow(ExampleUtils.ScreenRect)
      .AlignMiddelCenter(tileGrid)
      .To3DXY();

    foreach (RectPoint point in tileGrid)
    {
      Cell cell = Instantiate(cellPrefab);
      cell.transform.parent = uiRoot.transform;
      cell.transform.localScale = Vector3.one;
      cell.transform.localPosition = map[point];
      cell.SetColor(ExampleUtils.ColorFromInt(40, 40, 40));
      cell.HighlightOn = false;
      cell.SetText("");

      tileGrid[point] = cell;
      blocksGrid[point] = null;
    }

    blocks = new List();

    //First block
    currentBlock = MakeBlock(0, BlockType.Horizontal, new RectPoint(2, 2));
    SetHighlight(currentBlock, true);
    blocks.Add(currentBlock);

    //Other blocks
    blocks.Add(MakeBlock(1, BlockType.Horizontal, new RectPoint(1, 1)));
    blocks.Add(MakeBlock(2, BlockType.Vertical, new RectPoint(4, 2)));
    blocks.Add(MakeBlock(3, BlockType.Horizontal, new RectPoint(3, 4)));
    blocks.Add(MakeBlock(4, BlockType.Vertical, new RectPoint(2, 3)));
    blocks.Add(MakeBlock(5, BlockType.Vertical, new RectPoint(4, 0)));
    blocks.Add(MakeBlock(6, BlockType.Vertical, new RectPoint(3, 0)));
    blocks.Add(MakeBlock(7, BlockType.Vertical, new RectPoint(0, 0)));
    blocks.Add(MakeBlock(8, BlockType.Vertical, new RectPoint(0, 2)));
    blocks.Add(MakeBlock(9, BlockType.Vertical, new RectPoint(1, 2)));

    winPosition = new RectPoint(4, 2);
  }

  private bool CanOccupy(Block block, RectPoint gridPoint)
  {
    foreach (RectPoint tilePoint in block.TilePoints)
    {
      var absoluteTilePoint = gridPoint + tilePoint;

      if (!tileGrid.Contains(absoluteTilePoint))
      {
        return false;
      }

      if ((blocksGrid[absoluteTilePoint] != null) && (blocksGrid[absoluteTilePoint] != block))
      {
        return false;
      }
    }

    return true;
  }

  private Cell MakeTile()
  {
    Cell cell = Instantiate(cellPrefab);
    cell.transform.parent = uiRoot.transform;
    cell.transform.localScale = Vector3.one;

    return cell;
  }

  private Block MakeBlock(int id, BlockType type, RectPoint initialPosition)
  {
    Block block = new Block(id);

    if (type == BlockType.Horizontal)
    {
      block.AddTile(RectPoint.Zero, MakeTile());
      block.AddTile(RectPoint.East, MakeTile());
    }
    else
    {
      block.AddTile(RectPoint.Zero, MakeTile());
      block.AddTile(RectPoint.North, MakeTile());
    }

    if (CanOccupy(block, initialPosition))
    {
      foreach (Cell tile in block.TileObjects)
      {
        tile.SetColor(ExampleUtils.colors[id]);
        tile.SetText("");
      }

      PlaceTile(block, initialPosition);
      block.UpdateTilePositions(map);
    }
    else
    {
      Debug.LogError("Invalid placement. Making block empty");

      foreach (Cell tile in block.TileObjects)
      {
        Destroy(tile.gameObject);
      }

      block.Clear();
    }

    return block;
  }

  private void PlaceTile(Block block, RectPoint gridPoint)
  {
    foreach (RectPoint tilePoint in block.TilePoints)
    {
      tileGrid[gridPoint + tilePoint].gameObject.active = false;
      blocksGrid[gridPoint + tilePoint] = block;
    }

    block.CurrentPosition = gridPoint;
  }

  private void RemoveTile(Block block)
  {
    foreach (RectPoint tilePoint in block.TilePoints)
    {
      tileGrid[block.CurrentPosition + tilePoint].gameObject.active = true;
      blocksGrid[block.CurrentPosition + tilePoint] = null;
    }
  }

  private void SetHighlight(Block block, bool highlightOn)
  {
    foreach (Cell tile in block.TileObjects)
    {
      tile.HighlightOn = highlightOn;
    }
  }  
}

Leave a Reply

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

Scroll to Top