Advertisement
Guest User

MatchCraft Matching

a guest
Oct 26th, 2012
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 42.98 KB | None | 0 0
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Text;
  6.  
  7. public class GameGrid : YetiBehavior
  8. {
  9.     #region :: Class Members ::
  10.     private Transform _transform;
  11.     private Vector3 _lowerLeftPosition;
  12.    
  13.     private Gem[,] _activeGrid;
  14.     private Gem[,] _upNextGrid;
  15.     private Vector3[,] _activeGridPosition;
  16.     private Vector3[,] _upNextGridPosition;
  17.    
  18.     private SpriteManager _spriteManagerComponent;
  19.    
  20.     private const int _numRows = 8;
  21.     private const int _numColumns = 8;
  22.     private float _gemSize = 80.0f;    
  23.     private Vector2 _size;
  24.    
  25.     private Point2i _selectedTileCurrent;
  26.     private Point2i _selectedTilePrevious;
  27.     private Point2i[] _swappedTiles;
  28.    
  29.     private List<GemMatch> _scoreQueue;
  30.     private List<Point2i> _deathQueue;
  31.     private List<Point2i> _treasureQueue;
  32.     private HintList _hintList;
  33.     private int _cascadeCount;
  34.    
  35.     private GameObject _input;
  36.     private UIButton _inputComponent;  
  37.     private bool _pauseActiveGridUpdates = false;
  38.     private bool _pauseMatchingGems = false;
  39.    
  40.     private int _validBoardLoopCounter = 0;
  41.    
  42.     public SelectionBox SelectionBox;
  43.     public HintArrow HintArrow1;
  44.     public HintArrow HintArrow2;
  45.    
  46.     public float HintArrowMoveSpeed = 35.0f;
  47.     public float HintArrowBobDistance = 5.0f;
  48.     #endregion
  49.    
  50.     public override void HandleAwake()
  51.     {
  52.         base.HandleAwake();
  53.        
  54.         //Cache a few components for faster runtime access     
  55.         _transform = this.gameObject.transform;
  56.        
  57.         _activeGrid = new Gem[_numColumns, _numRows];
  58.         _upNextGrid = new Gem[_numColumns, _numRows];
  59.         _activeGridPosition = new Vector3[_numColumns, _numRows];
  60.         _upNextGridPosition = new Vector3[_numColumns, _numRows];
  61.        
  62.         //Keep a permanent reference to the PackedSprite component
  63.         _spriteManagerComponent = this.GetComponent("SpriteManager") as SpriteManager;     
  64.        
  65.         _selectedTileCurrent = new Point2i();
  66.         _selectedTilePrevious = new Point2i();     
  67.         _swappedTiles = new Point2i[2] { new Point2i(), new Point2i() };       
  68.        
  69.         _scoreQueue = new List<GemMatch>();
  70.         _deathQueue = new List<Point2i>();
  71.         _treasureQueue = new List<Point2i>();
  72.         _hintList = new HintList();
  73.        
  74.         /*this.HintArrow1.gameObject.active = false;
  75.         this.HintArrow2.gameObject.active = false;
  76.         this.SelectionBox.active = false;*/
  77.     }
  78.    
  79.     #region :: Initialization ::   
  80.     public override void Initialize()
  81.     {  
  82.         base.Initialize();
  83.        
  84.         //Configure the speed of swapping and the gem size based on what type of device we're running on
  85.         InitializeBasedOnDeviceResolution();
  86.        
  87.         //How big is the game grid?
  88.         _size.x = _numColumns * _gemSize;
  89.         _size.y = _numRows * _gemSize;
  90.        
  91.         //Make sure that the gamegrid is at the right Z-position
  92.         //_transform.position = new Vector3(_transform.position.x, _transform.position.y, GameLayer.Gems);
  93.        
  94.         //What is the position of the lower left point of the game grid?
  95.         _lowerLeftPosition = new Vector3(_transform.position.x - _size.x/2, _transform.position.y - _size.y/2, _transform.position.z);
  96.        
  97.         //Create the object that will give us gameplay input
  98.         InitializeInput();
  99.        
  100.         //Create all the gem objects on the game board
  101.         LoadGems();
  102.                
  103.         this.DefineObjectTypeInPool("GemDeathEffect", "Prefabs/Particle Effects/GemDeathEffect", 8);
  104.        
  105.         //Initialize Child Controls
  106.         for(int y=0; y<_numRows; y++)
  107.         {
  108.             for(int x=0; x<_numColumns; x++)
  109.             {              
  110.                 if(_upNextGrid[x,y] != null)
  111.                     _upNextGrid[x,y].Initialize();
  112.                
  113.                 if(_activeGrid[x,y] != null)
  114.                     _activeGrid[x,y].Initialize();
  115.             }
  116.         }
  117.        
  118.         this.HintArrow1.Initialize();
  119.         this.HintArrow2.Initialize();
  120.         this.SelectionBox.Initialize();
  121.     }
  122.    
  123.     private void InitializeBasedOnDeviceResolution()
  124.     {      
  125.         if(GraphicsManager.Instance.IsDeviceIpad)
  126.         {
  127.             _gemSize = 80.0f;
  128.             this.HintArrowMoveSpeed = 36.0f;
  129.             this.HintArrowBobDistance = 6.0f;
  130.         }
  131.         else // iPhone
  132.         {
  133.             _gemSize = 40.0f;
  134.             this.HintArrowMoveSpeed = 18.0f;
  135.             this.HintArrowBobDistance = 3.0f;
  136.         }
  137.        
  138.         //If we're using a retina display, let's double all the values
  139.         if(GraphicsManager.Instance.IsRetinaDisplay)
  140.         {
  141.             _gemSize *= 2.0f;  
  142.             this.HintArrowMoveSpeed *= 2.0f;
  143.             this.HintArrowBobDistance *= 2.0f;
  144.         }
  145.     }
  146.    
  147.     private void InitializeInput()
  148.     {
  149.         //Create our input object and position it relative to the parent object
  150.         _input = new GameObject("InputObject");    
  151.         _input.transform.parent = this.transform;
  152.         _input.transform.localPosition = new Vector3(0.0f, 0.0f, -1.0f);
  153.        
  154.         //Create the actual UI Button component and attach it to the input object
  155.         _inputComponent = (UIButton)_input.AddComponent(typeof(UIButton));
  156.        
  157.         //Configure the input parameters
  158.         _inputComponent.width = _size.x;
  159.         _inputComponent.height = _size.y;
  160.         _inputComponent.RenderCamera = Camera.main;
  161.         _inputComponent.scriptWithMethodToInvoke = this;
  162.         _inputComponent.whenToInvoke = POINTER_INFO.INPUT_EVENT.PRESS;
  163.         _inputComponent.methodToInvoke = "HandleInputPress";
  164.         _inputComponent.whenToInvokeSecondary = POINTER_INFO.INPUT_EVENT.DRAG;
  165.         _inputComponent.methodToInvokeSecondary = "HandleInputDrag";
  166.        
  167.         //Remove the mesh renderer components that are automatically added
  168.         GameObject.Destroy(_input.GetComponent("MeshRenderer"));
  169.         GameObject.Destroy(_input.GetComponent("MeshFilter")); 
  170.     }
  171.    
  172.     private void LoadGems()
  173.     {              
  174.         //Load all the gems on the board
  175.         for(int y=0; y<_numRows; y++)
  176.         {
  177.             for(int x=0; x<_numColumns; x++)
  178.             {
  179.                 //Load the prefab and cache the prefab object / gem component
  180.                 string prefabLocation = "Prefabs/Game/iPad/Gem0Prefab";
  181.                 if(!GraphicsManager.Instance.IsDeviceIpad)
  182.                     prefabLocation = "Prefabs/Game/iPhone/Gem0Prefab-iPhone";
  183.                
  184.                 GameObject gemPrefab = Instantiate(Resources.Load(prefabLocation)) as GameObject;
  185.                 Gem gemComponent = gemPrefab.GetComponent("Gem") as Gem;               
  186.                
  187.                 _activeGrid[x,y] = null;
  188.                 _upNextGrid[x,y] = gemComponent;
  189.                
  190.                 //Ensure that the gem type we're about to create is not one of the 4 neighbors, left/right/up/down. This will ensure no instant matches when the game starts               
  191.                 gemComponent.GemID = 0;
  192.                
  193.                 //Set the size of the gem in the data model
  194.                 GemDataModel.Instance.SetSize(_gemSize);
  195.                
  196.                 //Add the Gem to the SpriteManager
  197.                 _spriteManagerComponent.AddSprite(gemPrefab);      
  198.                
  199.                 //Calculate the position that the gems will reside on the game board. The upNext grid is offset by the board height
  200.                 _activeGridPosition[x,y] = GetCenterPointFromGridCoords(new Point2i(x, y), GameLayer.Gems);
  201.                 _upNextGridPosition[x,y] = _activeGridPosition[x,y];
  202.                 _upNextGridPosition[x,y].y += _numRows * _gemSize;
  203.                
  204.                 gemPrefab.transform.position = _upNextGridPosition[x,y];
  205.                 gemPrefab.transform.parent = this.transform;
  206.                 gemPrefab.name = string.Format("Gem [{0},{1}]", x, y);
  207.                
  208.                 //We'll want to know when a gem starts or stops moving so we can look for matches              
  209.                 gemComponent.Kinematic.IsMovingChanged += new PropertyChangedEventHandler(HandleGemIsMovingChanged);
  210.             }
  211.         }
  212.     }
  213.     #endregion 
  214.    
  215.     #region :: Game Pump / Event Detection ::
  216.     public override void HandleUpdate(float frameStartTime, float deltaTime)
  217.     {      
  218.         base.HandleUpdate(frameStartTime, deltaTime);
  219.        
  220.         //Make sure our queues are flushed
  221.         if(_scoreQueue.Count != 0)
  222.         {
  223.             CommitScoreQueue();
  224.         }
  225.        
  226.         if(_deathQueue.Count != 0)
  227.         {
  228.             CommitDeathQueue();
  229.             UpdateActiveGrid();
  230.         }
  231.        
  232.         //Update the gems -- we do this manually because there is a performance hit if they use Unity's Update method
  233.         for(int y=0; y<_numRows; y++)
  234.         {
  235.             for(int x=0; x<_numColumns; x++)
  236.             {
  237.                 if(_activeGrid[x,y] != null)
  238.                     _activeGrid[x,y].HandleUpdate(frameStartTime, deltaTime);
  239.                
  240.                 if(_upNextGrid[x,y] != null)
  241.                     _upNextGrid[x,y].HandleUpdate(frameStartTime, deltaTime);
  242.             }
  243.         }
  244.        
  245.         this.HintArrow1.HandleUpdate(frameStartTime, deltaTime);
  246.         this.HintArrow2.HandleUpdate(frameStartTime, deltaTime);
  247.        
  248.         if(GameManager.Instance.AutoPlay)
  249.             AutoPlay();
  250.        
  251.         //Every 500 game updates, let's ensure we have a valid board -- Just in case some logic got screwed up somewhere. This is better than having a user with
  252.         //an unplayable game board
  253.         _validBoardLoopCounter++;
  254.         if(_validBoardLoopCounter > 500)
  255.         {
  256.             _validBoardLoopCounter = 0;
  257.             ConfirmValidBoardExists();
  258.         }
  259.     }
  260.     #endregion 
  261.    
  262.     #region :: Internal Implementation ::
  263.     public Vector3 GetCenterPointFromGridCoords(Point2i tileIndex, float positionZ)
  264.     {
  265.         //We'll offset the position with the GameGrid object's position. This is the lower left hand side of the game board
  266.         //Positions are centered on the object so we need to place them by dividing height & width by 2
  267.            
  268.         //Get the center point for the object that lives on the grid
  269.         Vector3 centerPoint = new Vector3(_lowerLeftPosition.x + tileIndex.x*_gemSize + _gemSize/2,
  270.                                           _lowerLeftPosition.y + tileIndex.y*_gemSize + _gemSize/2,
  271.                                           positionZ);
  272.  
  273.         return centerPoint;
  274.     }
  275.    
  276.     private void SelectGridPosition(Point2i tileIndex)
  277.     {
  278.         _selectedTilePrevious.Set(_selectedTileCurrent.x, _selectedTileCurrent.y);
  279.         _selectedTileCurrent.Set(tileIndex.x, tileIndex.y);
  280.        
  281.         //Show the SelectionBox around the gem that we clicked on
  282.         this.SelectionBox.gameObject.active = true;
  283.         this.SelectionBox.SpriteGraphics.Hide(false);
  284.         this.SelectionBox.gameObject.transform.position = GetCenterPointFromGridCoords(tileIndex, GameLayer.SelectionBox);
  285.        
  286.         //Was there a tile previously selected?
  287.         if(_selectedTilePrevious.IsValid)
  288.         {
  289.             //Check to see if we can swap these two tiles
  290.             if(CheckIfTilesShareEdge(_selectedTilePrevious, _selectedTileCurrent))
  291.             {
  292.                 //Swap Tiles
  293.                 SwapTiles(_selectedTileCurrent, _selectedTilePrevious, true);
  294.             }
  295.         }
  296.     }
  297.    
  298.     public void ClearGridSelection()
  299.     {
  300.         _selectedTileCurrent.Reset();
  301.         _selectedTilePrevious.Reset();
  302.         this.SelectionBox.gameObject.active = false;
  303.     }
  304.    
  305.     private void HideHintArrows()
  306.     {
  307.         this.HintArrow1.gameObject.active = false;
  308.         this.HintArrow2.gameObject.active = false;
  309.     }
  310.    
  311.     private bool CheckIfTilesShareEdge(Point2i tile1Index, Point2i tile2Index)
  312.     {
  313.         bool doTilesShareEdge = false;
  314.        
  315.         if(tile1Index.x == tile2Index.x)
  316.         {
  317.             if(Math.Abs(tile1Index.y - tile2Index.y) == 1)
  318.                 doTilesShareEdge = true;
  319.         }
  320.         else if(tile1Index.y == tile2Index.y)
  321.         {
  322.             if(Math.Abs(tile1Index.x - tile2Index.x) == 1)
  323.                 doTilesShareEdge = true;
  324.         }
  325.        
  326.         return doTilesShareEdge;
  327.     }
  328.    
  329.     public int[] GetListOfNeighborIDs(int gridX, int gridY)
  330.     {
  331.         return GetListOfNeighborIDs(_activeGrid, gridX, gridY);
  332.     }
  333.    
  334.     private int[] GetListOfNeighborIDs(Gem[,] grid, int gridX, int gridY)
  335.     {
  336.         List<int> neighborIDs = new List<int>();
  337.        
  338.         //Left
  339.         if(gridX-1 >= 0 && grid[gridX-1, gridY] != null)
  340.         {
  341.             int id = grid[gridX-1, gridY].GemID;
  342.            
  343.             if(!neighborIDs.Contains(id))
  344.                 neighborIDs.Add(id);
  345.         }
  346.        
  347.         //Bottom
  348.         if(gridY-1 >= 0 && grid[gridX, gridY-1] != null)
  349.         {
  350.             int id = grid[gridX, gridY-1].GemID;
  351.            
  352.             if(!neighborIDs.Contains(id))
  353.                 neighborIDs.Add(id);
  354.         }
  355.        
  356.         //Right
  357.         if(gridX+1 < _numColumns && grid[gridX+1, gridY] != null)
  358.         {
  359.             int id = grid[gridX+1, gridY].GemID;
  360.            
  361.             if(!neighborIDs.Contains(id))
  362.                 neighborIDs.Add(id);
  363.         }
  364.        
  365.         //Top
  366.         if(gridY+1 < _numRows && grid[gridX, gridY+1] != null)
  367.         {
  368.             int id = grid[gridX, gridY+1].GemID;
  369.            
  370.             if(!neighborIDs.Contains(id))
  371.                 neighborIDs.Add(id);
  372.         }
  373.        
  374.         return neighborIDs.ToArray();
  375.     }
  376.    
  377.     private void SwapTiles(Point2i tile1Index, Point2i tile2Index, bool isSwapUserInitiated)
  378.     {
  379.         //Swap the gems in our array
  380.         Gem tempGemComponent = _activeGrid[tile1Index.x, tile1Index.y];
  381.         _activeGrid[tile1Index.x, tile1Index.y] = _activeGrid[tile2Index.x, tile2Index.y];
  382.         _activeGrid[tile2Index.x, tile2Index.y] = tempGemComponent;
  383.        
  384.         //Move them to their new locations
  385.         //_activeGrid[tile1Index.x, tile1Index.y].Kinematic.MoveTo(_activeGrid[tile2Index.x, tile2Index.y].transform.position, this.GemSwapSpeed);
  386.         //_activeGrid[tile2Index.x, tile2Index.y].Kinematic.MoveTo(_activeGrid[tile1Index.x, tile1Index.y].transform.position, this.GemSwapSpeed);
  387.         float movementTime = 0.30f;
  388.         _activeGrid[tile1Index.x, tile1Index.y].Kinematic.MoveToWithTween(_activeGrid[tile2Index.x, tile2Index.y].transform.position, movementTime);
  389.         _activeGrid[tile2Index.x, tile2Index.y].Kinematic.MoveToWithTween(_activeGrid[tile1Index.x, tile1Index.y].transform.position, movementTime);
  390.        
  391.        
  392.         //Remember what gems we swapped. We do this incase there is not a match and we need to move the gems back to their proper location
  393.         if(isSwapUserInitiated)
  394.         {
  395.             _swappedTiles[0].Set(tile1Index);
  396.             _swappedTiles[1].Set(tile2Index);
  397.         }
  398.         else
  399.         {
  400.             _swappedTiles[0].Reset();
  401.             _swappedTiles[1].Reset();
  402.         }
  403.        
  404.         ClearGridSelection();
  405.         HideHintArrows();
  406.     }
  407.    
  408.     public bool GetAreTilesMoving()
  409.     {
  410.         //Checks the Gem array to see if any of the tiles are currently moving to a destination
  411.         for(int y=0; y<_numRows; y++)
  412.         {
  413.             for(int x=0; x<_numColumns; x++)
  414.             {
  415.                 if(_activeGrid[x, y] == null || _activeGrid[x, y].Kinematic.IsMoving)
  416.                     return true;
  417.             }
  418.         }
  419.        
  420.         return false;
  421.     }
  422.    
  423.     private void CheckForMatches(Gem[,] grid)
  424.     {
  425.         _treasureQueue.Clear();
  426.         _deathQueue.Clear();
  427.         _scoreQueue.Clear();
  428.        
  429.         CheckForHorizontalMatches(grid);
  430.         CheckForVerticalMatches(grid);
  431.     }
  432.    
  433.     private void CheckForHorizontalMatches(Gem[,] grid)
  434.     {
  435.         //Check for Horizontal Matches
  436.         for(int y=0; y<_numRows; y++)
  437.         {
  438.             //We can safely ignore the 2 right columns since they can't form matches with only two gems
  439.             for(int x=0; x<_numColumns-2; x++)
  440.             {
  441.                 int nextGemIndex = x + 1;
  442.                 int numGemsMatched = 1; //The tile found at currentIndexToCheck
  443.                 bool didNextGemMatch = true;
  444.                
  445.                 //Look for matches
  446.                 while(didNextGemMatch)
  447.                 {
  448.                     //Does the next gem to look at match our current [x,y] position?
  449.                     if(grid[nextGemIndex,y] != null && grid[x,y] != null &&
  450.                        grid[nextGemIndex,y].GemID == grid[x,y].GemID)
  451.                     {
  452.                         numGemsMatched++;
  453.                         nextGemIndex++;
  454.                        
  455.                         //Break out of the loop if we get to the edge of the game board
  456.                         if(nextGemIndex >= _numColumns)
  457.                             didNextGemMatch = false;
  458.                     }
  459.                     else
  460.                     {
  461.                         didNextGemMatch = false;
  462.                     }
  463.                 }
  464.                
  465.                 //Done searching for matches on this row. Let's see if we have enough tiles matched to score.
  466.                 if(numGemsMatched >= 3)
  467.                 {
  468.                     if(grid == _activeGrid)
  469.                     {
  470.                         //Add the matched gems to our score queue so that the player gets points
  471.                         AddGemsToScoreQueue(new Point2i(x, y), new Point2i(x+numGemsMatched-1, y), numGemsMatched);                    
  472.                         _cascadeCount++;
  473.                     }
  474.                    
  475.                     //Add the gems that matched to the death queue to be removed after all matches are found
  476.                     for(int i=x; i<(x+numGemsMatched); i++)
  477.                     {
  478.                         AddGemToDeathQueue(new Point2i(i, y));
  479.                     }
  480.                    
  481.                     //Increment our iterator to skip the gems we've already matched
  482.                     x += (numGemsMatched - 1);
  483.                 }
  484.             }
  485.         }      
  486.     }
  487.    
  488.     private void CheckForVerticalMatches(Gem[,] grid)
  489.     {
  490.         //Check for Vertical Matches
  491.         for(int x=0; x<_numColumns; x++)
  492.         {
  493.             //We can safely ignore the 2 right columns since they can't form matches with only two gems
  494.             for(int y=0; y<_numRows-2; y++)
  495.             {
  496.                 int nextGemIndex = y + 1;
  497.                 int numGemsMatched = 1; //The tile found at currentIndexToCheck
  498.                 bool didNextGemMatch = true;
  499.                
  500.                 //Look for matches
  501.                 while(didNextGemMatch)
  502.                 {
  503.                     //Does the next gem to look at match our current [x,y] position?
  504.                     if(grid[x, nextGemIndex] != null && grid[x,y] != null &&
  505.                        grid[x, nextGemIndex].GemID == grid[x,y].GemID)
  506.                     {
  507.                         numGemsMatched++;
  508.                         nextGemIndex++;
  509.                        
  510.                         //Break out of the loop if we get to the edge of the game board
  511.                         if(nextGemIndex >= _numRows)
  512.                             didNextGemMatch = false;
  513.                     }
  514.                     else
  515.                     {
  516.                         didNextGemMatch = false;
  517.                     }
  518.                 }
  519.                
  520.                 //Done searching for matches on this row. Let's see if we have enough tiles matched to score.
  521.                 if(numGemsMatched >= 3)
  522.                 {
  523.                     if(grid == _activeGrid)
  524.                     {
  525.                         //Add the matched gems to our score queue so that the player gets points                   
  526.                         AddGemsToScoreQueue(new Point2i(x, y), new Point2i(x, y+numGemsMatched-1), numGemsMatched);
  527.                         _cascadeCount++;
  528.                     }
  529.                    
  530.                     //Add the gems that matched to the death queue to be removed after all matches are found
  531.                     for(int i=y; i<(y+numGemsMatched); i++)
  532.                     {
  533.                         AddGemToDeathQueue(new Point2i(x, i));
  534.                     }
  535.                    
  536.                     //Increment our iterator to skip the gems we've already matched
  537.                     y += (numGemsMatched - 1);
  538.                 }
  539.             }
  540.         }
  541.     }
  542.        
  543.     private void CheckForMoves(Gem[,] grid)
  544.     {
  545.         _hintList.Clear();
  546.        
  547.         CheckForHorizontalMoves(grid);
  548.         CheckForVerticalMoves(grid);
  549.     }
  550.    
  551.     private void CheckForHorizontalMoves(Gem[,] grid)
  552.     {
  553.         for(int y=0; y<_numRows; y++)
  554.         {
  555.             //Check for Horizontal Hints of typed "JOINED"
  556.            
  557.             //We can safely ignore the right most column since they can't form matches with only two gems
  558.             for(int x=0; x<_numColumns-1; x++)
  559.             {
  560.                 int nextGemIndex = x + 1;
  561.                 int numGemsMatched = 1; //The tile found at currentIndexToCheck
  562.                 bool didNextGemMatch = true;
  563.                
  564.                 //Look for matches
  565.                 while(didNextGemMatch)
  566.                 {
  567.                     //Does the next gem to look at match our current [x,y] position?
  568.                     if(grid[nextGemIndex,y] != null && grid[x,y] != null &&
  569.                        grid[nextGemIndex,y].GemID == grid[x,y].GemID)
  570.                     {
  571.                         numGemsMatched++;
  572.                         nextGemIndex++;
  573.                        
  574.                         //Break out of the loop if we get to the edge of the game board or we have our required number matched to search for hints
  575.                         if(nextGemIndex >= _numColumns || numGemsMatched == 2)
  576.                             didNextGemMatch = false;
  577.                     }
  578.                     else
  579.                     {
  580.                         didNextGemMatch = false;
  581.                     }
  582.                 }
  583.                
  584.                 //Done searching for matches on this row. Let's see if we have enough tiles matched to create a hint
  585.                 if(numGemsMatched == 2)
  586.                 {
  587.                     //We found two tiles that match horizontally, so let's see if there is a tile that could match it around the endpoints
  588.                     //.2..5.
  589.                     //1.xx.4
  590.                     //.3..6.
  591.                    
  592.                     //Check the left most for match, #1
  593.                     if(x-2 >= 0)
  594.                     {
  595.                        if(grid[x-2,y].GemID == grid[x,y].GemID)
  596.                        {
  597.                           _hintList.AddHint(new Hint(x-2, y, x-1, y, grid[x,y].GemID, HintType.GEMS_JOINED));
  598.                        }
  599.                     }
  600.                    
  601.                     //Check the left-upper for match, #2
  602.                     if(x-1 >= 0 && y+1 < _numRows)
  603.                     {
  604.                        if(grid[x-1,y+1].GemID == grid[x,y].GemID)
  605.                        {
  606.                           _hintList.AddHint(new Hint(x-1, y+1, x-1, y, grid[x,y].GemID, HintType.GEMS_JOINED));
  607.                        }
  608.                     }
  609.                    
  610.                     //Check the left-lower for match, #3
  611.                     if(x-1 >= 0 && y-1 >= 0)
  612.                     {
  613.                        if(grid[x-1,y-1].GemID == grid[x,y].GemID)
  614.                        {
  615.                           _hintList.AddHint(new Hint(x-1, y-1, x-1, y, grid[x,y].GemID, HintType.GEMS_JOINED));
  616.                        }
  617.                     }  
  618.                    
  619.                     //Check the right most for match, #4
  620.                     if(x+3 < _numColumns)
  621.                     {
  622.                        if(grid[x+3,y].GemID == grid[x,y].GemID)
  623.                        {
  624.                           _hintList.AddHint(new Hint(x+3, y, x+2, y, grid[x,y].GemID, HintType.GEMS_JOINED));
  625.                        }
  626.                     }
  627.                    
  628.                     //Check the right-upper for match, #5
  629.                     if(x+2 < _numColumns && y+1 < _numRows)
  630.                     {
  631.                        if(grid[x+2,y+1].GemID == grid[x,y].GemID)
  632.                        {
  633.                           _hintList.AddHint(new Hint(x+2, y+1, x+2, y, grid[x,y].GemID, HintType.GEMS_JOINED));
  634.                        }
  635.                     }
  636.                    
  637.                     //Check the right-lower for match, #6
  638.                     if(x+2 < _numColumns && y-1 >= 0)
  639.                     {
  640.                        if(grid[x+2,y-1].GemID == grid[x,y].GemID)
  641.                        {
  642.                           _hintList.AddHint(new Hint(x+2, y-1, x+2, y, grid[x,y].GemID, HintType.GEMS_JOINED));
  643.                        }
  644.                     }                  
  645.                    
  646.                     //Increment our iterator to skip the gems we've already matched
  647.                     x += (numGemsMatched - 1);
  648.                 }
  649.             }
  650.            
  651.             //Check for Horizontal Hints of typed "SPLIT"
  652.             for(int x=0; x<_numColumns-2; x++)
  653.             {
  654.                 //We're looking for gems that are the same type but split apart. We'll add a hint if we can swap a gem from top or bottom with the middle gem to form a match
  655.                 //.1.
  656.                 //x.x
  657.                 //.2.
  658.                
  659.                 if(grid[x+2,y].GemID == grid[x,y].GemID)
  660.                 {
  661.                     //Check the upper for match, #1
  662.                     if(y+1 < _numRows)
  663.                     {
  664.                        if(grid[x+1,y+1].GemID == grid[x,y].GemID)
  665.                        {
  666.                           _hintList.AddHint(new Hint(x+1, y+1, x+1, y, grid[x,y].GemID, HintType.GEMS_SPLIT));
  667.                        }
  668.                     }
  669.                    
  670.                     //Check the lower for match, #2
  671.                     if(y-1 >= 0)
  672.                     {
  673.                        if(grid[x+1,y-1].GemID == grid[x,y].GemID)
  674.                        {
  675.                           _hintList.AddHint(new Hint(x+1, y-1, x+1, y, grid[x,y].GemID, HintType.GEMS_SPLIT));
  676.                        }
  677.                     }
  678.                 }                  
  679.             }
  680.         }
  681.     }
  682.    
  683.     private void CheckForVerticalMoves(Gem[,] grid)
  684.     {
  685.         for(int x=0; x<_numColumns; x++)
  686.         {
  687.             //Check for Horizontal Hints of typed "JOINED"
  688.            
  689.             //We can safely ignore the right most column since they can't form matches with only two gems
  690.             for(int y=0; y<_numRows-1; y++)
  691.             {
  692.                 int nextGemIndex = y + 1;
  693.                 int numGemsMatched = 1; //The tile found at currentIndexToCheck
  694.                 bool didNextGemMatch = true;
  695.                
  696.                 //Look for matches
  697.                 while(didNextGemMatch)
  698.                 {
  699.                     //Does the next gem to look at match our current [x,y] position?
  700.                     if(grid[x,nextGemIndex] != null && grid[x,y] != null &&
  701.                        grid[x,nextGemIndex].GemID == grid[x,y].GemID)
  702.                     {
  703.                         numGemsMatched++;
  704.                         nextGemIndex++;
  705.                        
  706.                         //Break out of the loop if we get to the edge of the game board or we have our required number matched to search for hints
  707.                         if(nextGemIndex >= _numRows || numGemsMatched == 2)
  708.                             didNextGemMatch = false;
  709.                     }
  710.                     else
  711.                     {
  712.                         didNextGemMatch = false;
  713.                     }
  714.                 }
  715.                
  716.                 //Done searching for matches on this row. Let's see if we have enough tiles matched to create a hint
  717.                 if(numGemsMatched == 2)
  718.                 {
  719.                     //We found two tiles that match vertically, so let's see if there is a tile that could match it around the endpoints
  720.                     //.4.
  721.                     //5.6
  722.                     //.x.
  723.                     //.x.
  724.                     //2.3
  725.                     //.1.
  726.                    
  727.                     //Check the bottom most match, #1
  728.                     if(y-2 >= 0)
  729.                     {
  730.                        if(grid[x,y-2].GemID == grid[x,y].GemID)
  731.                        {
  732.                           _hintList.AddHint(new Hint(x, y-2, x, y-1, grid[x,y].GemID, HintType.GEMS_JOINED));
  733.                        }
  734.                     }
  735.                    
  736.                     //Check the lower-left for match, #2
  737.                     if(x-1 >= 0 && y-1 >= 0)
  738.                     {
  739.                        if(grid[x-1,y-1].GemID == grid[x,y].GemID)
  740.                        {
  741.                           _hintList.AddHint(new Hint(x-1, y-1, x, y-1, grid[x,y].GemID, HintType.GEMS_JOINED));
  742.                        }
  743.                     }
  744.                    
  745.                     //Check the lower-right for match #3
  746.                     if(x+1 < _numColumns && y-1 >= 0)
  747.                     {
  748.                        if(grid[x+1,y-1].GemID == grid[x,y].GemID)
  749.                        {
  750.                           _hintList.AddHint(new Hint(x+1, y-1, x, y-1, grid[x,y].GemID, HintType.GEMS_JOINED));
  751.                        }
  752.                     }  
  753.                    
  754.                     //Check the top most for match, #4
  755.                     if(y+3 < _numRows)
  756.                     {
  757.                        if(grid[x,y+3].GemID == grid[x,y].GemID)
  758.                        {
  759.                           _hintList.AddHint(new Hint(x, y+3, x, y+2, grid[x,y].GemID, HintType.GEMS_JOINED));
  760.                        }
  761.                     }
  762.                    
  763.                     //Check the upper-left for match, #5
  764.                     if(x-1 >=0 && y+2 < _numRows)
  765.                     {
  766.                        if(grid[x-1,y+2].GemID == grid[x,y].GemID)
  767.                        {
  768.                           _hintList.AddHint(new Hint(x-1, y+2, x, y+2, grid[x,y].GemID, HintType.GEMS_JOINED));
  769.                        }
  770.                     }
  771.                    
  772.                     //Check the upper-right for match, #6
  773.                     if(x+1 < _numColumns && y+2 < _numRows)
  774.                     {
  775.                        if(grid[x+1,y+2].GemID == grid[x,y].GemID)
  776.                        {
  777.                           _hintList.AddHint(new Hint(x+1, y+2, x, y+2, grid[x,y].GemID, HintType.GEMS_JOINED));
  778.                        }
  779.                     }                  
  780.                    
  781.                     //Increment our iterator to skip the gems we've already matched
  782.                     y += (numGemsMatched - 1);
  783.                 }
  784.             }
  785.            
  786.             //Check for Vertical Hints of typed "SPLIT"
  787.             for(int y=0; y<_numRows-2; y++)
  788.             {
  789.                 //We're looking for gems that are the same type but split apart. We'll add a hint if we can swap a gem from left or right with the middle gem to form a match
  790.                 //.x.
  791.                 //1.2
  792.                 //.x.
  793.                
  794.                 if(grid[x,y+2].GemID == grid[x,y].GemID)
  795.                 {
  796.                     //Check the left for match, #1
  797.                     if(x-1 >= 0)
  798.                     {
  799.                        if(grid[x-1,y+1].GemID == grid[x,y].GemID)
  800.                        {
  801.                           _hintList.AddHint(new Hint(x-1, y+1, x, y+1, grid[x,y].GemID, HintType.GEMS_SPLIT));
  802.                        }
  803.                     }
  804.                    
  805.                     //Check the right for match, #2
  806.                     if(x+1 < _numColumns)
  807.                     {
  808.                        if(grid[x+1,y+1].GemID == grid[x,y].GemID)
  809.                        {
  810.                           _hintList.AddHint(new Hint(x+1, y+1, x, y+1, grid[x,y].GemID, HintType.GEMS_SPLIT));
  811.                        }
  812.                     }
  813.                 }                  
  814.             }
  815.         }
  816.     }
  817.    
  818.     private void UpdateActiveGrid()
  819.     {
  820.         if(this.PauseActiveGridUpdates)
  821.             return;
  822.        
  823.         List<Gem> droppingGems = new List<Gem>();
  824.        
  825.         float tweenSpeed = 0.40f;
  826.        
  827.         for(int x=0; x<_numColumns; x++)
  828.         {
  829.             for(int y=0; y<_numRows; y++)
  830.             {
  831.                 //Check for a hole in the column that needs to be filled
  832.                 if(_activeGrid[x,y] == null)
  833.                 {
  834.                     //We found a hole in the column, find the next closest gem above this hole
  835.                     for(int j=y; j<_numRows; j++)
  836.                     {
  837.                         if(_activeGrid[x,j] != null)
  838.                         {
  839.                             //Move the gem down to the empty spot
  840.                             //_activeGrid[x,j].Kinematic.MoveTo(_activeGridPosition[x,y], this.GemFallSpeed);
  841.                             _activeGrid[x,j].Kinematic.MoveToWithTween(_activeGridPosition[x,y], tweenSpeed);
  842.                            
  843.                             //Assign the moving gem to it's new spot and designate the other as empty
  844.                             _activeGrid[x,y] = _activeGrid[x,j];
  845.                             _activeGrid[x,j] = null;
  846.                            
  847.                             break;
  848.                         }
  849.                     }
  850.                 }
  851.                
  852.                 //Check to see if we still have a hole in the board after looking above us. If there is still a hole, we need to pull a gem out of the upNext board
  853.                 if(_activeGrid[x,y] == null)
  854.                 {
  855.                     //We found a hole in the column, find the next closest gem above this hole
  856.                     for(int j=0; j<_numRows; j++)
  857.                     {
  858.                         if(_upNextGrid[x,j] != null)
  859.                         {
  860.                             //Move the gem down to the empty spot
  861.                             _upNextGrid[x,j].Visible = true;
  862.                             //_upNextGrid[x,j].Kinematic.MoveTo(_activeGridPosition[x,y], this.GemFallSpeed);
  863.                             _upNextGrid[x,j].Kinematic.MoveToWithTween(_activeGridPosition[x,y], tweenSpeed);
  864.                            
  865.                             //Assign the moving gem to it's new spot and designate the other as empty
  866.                             _activeGrid[x,y] = _upNextGrid[x,j];                           
  867.                             _upNextGrid[x,j] = null;
  868.                            
  869.                             //Keep a list of the gems we're dropping in case there are no more moves and we need to reassign gems
  870.                             droppingGems.Add(_activeGrid[x,y]);
  871.                            
  872.                             //Tell everything above this gem in upNext to move down a spot
  873.                             for(int z=j+1; j<_numRows; j++)
  874.                             {
  875.                                 if(_upNextGrid[x,z] != null)
  876.                                 {
  877.                                     //_upNextGrid[x,z].Kinematic.MoveTo(_upNextGridPosition[x,z-1], this.GemFallSpeed);
  878.                                     _upNextGrid[x,z].Kinematic.MoveToWithTween(_upNextGridPosition[x,z-1], tweenSpeed);
  879.                                     _upNextGrid[x,z-1] = _upNextGrid[x,z];
  880.                                     _upNextGrid[x,z] = null;
  881.                                 }
  882.                             }
  883.                            
  884.                             break;
  885.                         }
  886.                     }
  887.                 }
  888.             }
  889.         }
  890.        
  891.         //Play a drop gem sound if we moved any gems
  892.         if(droppingGems.Count > 0)
  893.         {
  894.             //this.ScheduleTimer("", tweenSpeed, PlayGemsFallSound);           
  895.             this.ScheduleTimer("", 0.0f, PlayGemsFallSound);
  896.         }
  897.                
  898.         //The active grid changed, check for new moves
  899.         CheckForMoves(_activeGrid);
  900.        
  901.         //Did the gems we just added result in no new moves?
  902.         int boardRegenCount = 0;
  903.         while(!_hintList.HasHints && droppingGems.Count > 0)
  904.         {
  905.             foreach(Gem droppingGem in droppingGems)
  906.             {
  907.                 droppingGem.Randomize();
  908.             }
  909.            
  910.             boardRegenCount++;
  911.            
  912.             //Check for moves now that we've randomized the gems that were about to drop
  913.             CheckForMoves(_activeGrid);
  914.            
  915.             if(boardRegenCount > 30)
  916.                 break;
  917.         }
  918.        
  919.         if(boardRegenCount > 30)
  920.         {
  921.             Debug.Log("No More Moves. Board Regen Count Over 30.. Resetting board");
  922.         }
  923.        
  924.         //If no hints are available, reset the board
  925.         if(!_hintList.HasHints)
  926.             ResetGameBoard();
  927.        
  928.         //Save the game board
  929.         GameWindow.Instance.SaveGameBoard();
  930.     }
  931.    
  932.     private void CommitDeathQueue()
  933.     {
  934.         for(int i=0; i<_deathQueue.Count; i++)
  935.         {
  936.             if(_activeGrid[_deathQueue[i].x, _deathQueue[i].y] != null)
  937.             {
  938.                 _activeGrid[_deathQueue[i].x, _deathQueue[i].y].Die();         
  939.             }
  940.            
  941.             ClearGridSpace(_deathQueue[i]);
  942.         }
  943.        
  944.         _deathQueue.Clear();
  945.     }
  946.    
  947.     private void CommitScoreQueue()
  948.     {
  949.         for(int i=0; i<_scoreQueue.Count; i++)
  950.         {
  951.             GameWindow.Instance.ScoreGemMatch(_scoreQueue[i]);
  952.         }
  953.        
  954.         _scoreQueue.Clear();
  955.     }
  956.    
  957.     private void CommitTreasureQueue()
  958.     {      
  959.         for(int i=0; i<_treasureQueue.Count; i++)
  960.         {
  961.             //Remove the spot that we'll use for the treasure chest from the death queue.
  962.             for(int j=0; j<_deathQueue.Count; j++)
  963.             {
  964.                 if(_deathQueue[j].Equals(_treasureQueue[i]))
  965.                 {
  966.                     //Debug.Log(String.Format("Removing gem from death queue at {0},{1}", _deathQueue[j].x, _deathQueue[j].y));
  967.                     _deathQueue.RemoveAt(j);                   
  968.                     break;
  969.                 }              
  970.             }
  971.            
  972.             //Reassign the gem that we are removing to become a treasure chest         
  973.             //Debug.Log("Created Treasure Chest");
  974.             _activeGrid[_treasureQueue[i].x, _treasureQueue[i].y].IsTreasure = true;
  975.            
  976.             //Award the treasure chest in a few moments -- Give the timer a unique name just in case there are two chests made in the queue
  977.             ScheduleTimer(String.Format("AwardTreasureChest{0}{1}",_treasureQueue[i].x, _treasureQueue[i].y),
  978.                           0.5f,
  979.                           GameWindow.Instance.AwardTreasureChest,
  980.                           _activeGrid[_treasureQueue[i].x, _treasureQueue[i].y]);
  981.         }
  982.        
  983.         _treasureQueue.Clear();
  984.     }
  985.    
  986.     private void ClearGridSpace(Point2i tileIndex)
  987.     {
  988.         //Make sure the activeGrid hasn't already cleared that space
  989.         if(_activeGrid[tileIndex.x, tileIndex.y] == null)
  990.             return;
  991.            
  992.         //Find the lowest available item in UpNext Grid.       
  993.         for(int y=0; y<_numRows; y++)
  994.         {
  995.             if(_upNextGrid[tileIndex.x,y] == null)
  996.             {              
  997.                 //Move the reference to the gem to the upNextGrid
  998.                 _upNextGrid[tileIndex.x,y] = _activeGrid[tileIndex.x, tileIndex.y];
  999.                 _activeGrid[tileIndex.x, tileIndex.y] = null;
  1000.                
  1001.                 //Disable the gem in the upNextGrid so we don't see it rendered
  1002.                 _upNextGrid[tileIndex.x,y].Visible = false;
  1003.                
  1004.                 //Update it's position             
  1005.                 _upNextGrid[tileIndex.x,y].transform.position = _upNextGridPosition[tileIndex.x,y];
  1006.                                
  1007.                 //Change the gem
  1008.                 _upNextGrid[tileIndex.x,y].Randomize();
  1009.                
  1010.                 break;
  1011.             }
  1012.         }
  1013.     }
  1014.    
  1015.     public void AddGemsToScoreQueue(Point2i tile1Index, Point2i tile2Index, int numGemsMatched)
  1016.     {
  1017.         int gemID = _activeGrid[tile1Index.x, tile1Index.y].GemID;
  1018.         Vector3 tile1Position = GetCenterPointFromGridCoords(tile1Index, GameLayer.Gems);
  1019.         Vector3 tile2Position = GetCenterPointFromGridCoords(tile2Index, GameLayer.Gems);
  1020.        
  1021.         Vector3 centerPosition = new Vector3((tile1Position.x + tile2Position.x) / 2,
  1022.                                              (tile1Position.y + tile2Position.y) / 2,
  1023.                                              GameLayer.Text);
  1024.        
  1025.         _scoreQueue.Add(new GemMatch(centerPosition, gemID, numGemsMatched));
  1026.                
  1027.         //If we matched 5 gems, store the location where we want to put the treasure chest once the scoring is done
  1028.         if(numGemsMatched >= 5)
  1029.         {
  1030.             AddGemToTreasureQueue(tile1Index, tile2Index);
  1031.         }
  1032.     }
  1033.    
  1034.     public void AddGemToScoreQueue(Point2i tileIndex, bool wasDestroyedByMagic)
  1035.     {
  1036.         //Make sure this gem hasn't been recently destroyed
  1037.         if(_activeGrid[tileIndex.x, tileIndex.y] == null)
  1038.             return;
  1039.        
  1040.         int gemID = _activeGrid[tileIndex.x, tileIndex.y].GemID;
  1041.         Vector3 centerPosition = GetCenterPointFromGridCoords(tileIndex, GameLayer.Text);
  1042.        
  1043.         //Do they get a bonus for destroying this with magic?          
  1044.         int scoreMultiplier = 1;
  1045.         if(wasDestroyedByMagic && GameManager.Instance.GameState.HasUnlockedGnarledWoodenStaff)
  1046.             scoreMultiplier = 2;
  1047.        
  1048.         _scoreQueue.Add(new GemMatch(centerPosition, gemID, 1, scoreMultiplier));
  1049.     }
  1050.    
  1051.     public void AddGemToDeathQueue(Point2i tileIndex)
  1052.     {
  1053.         bool isAlreadyAdded = false;
  1054.        
  1055.         //Make sure this tileIndex is not already added.
  1056.         foreach(Point2i tile in _deathQueue)
  1057.         {
  1058.             if(tile.x == tileIndex.x && tile.y == tileIndex.y)
  1059.             {              
  1060.                 isAlreadyAdded = true;
  1061.                 break;
  1062.             }
  1063.         }
  1064.        
  1065.         if(!isAlreadyAdded)
  1066.             _deathQueue.Add(tileIndex);
  1067.     }
  1068.    
  1069.     public void DestroyGem(Gem gemToDestroy)
  1070.     {
  1071.         //Find the gem in the active grid and destroy it
  1072.         for(int y=0; y<_numRows; y++)
  1073.         {
  1074.             for(int x=0; x<_numColumns; x++)
  1075.             {
  1076.                 if(_activeGrid[x,y] == gemToDestroy)
  1077.                 {
  1078.                     ClearGridSpace(new Point2i(x,y));
  1079.                     gemToDestroy.Die();
  1080.                 }
  1081.             }
  1082.         }
  1083.     }
  1084.    
  1085.     private void AddGemToTreasureQueue(Point2i tile1Index, Point2i tile2Index)
  1086.     {      
  1087.         int treasureTileX = (tile1Index.x + tile2Index.x) / 2;
  1088.         int treasureTileY = (tile1Index.y + tile2Index.y) / 2;
  1089.        
  1090.         _treasureQueue.Add(new Point2i(treasureTileX, treasureTileY));
  1091.     }  
  1092.    
  1093.     private void MoveAllGemsToUpNext()
  1094.     {
  1095.         Gem[,] temporaryGrid = new Gem[_numColumns, _numRows];
  1096.         int temporaryGridIndex = 0;
  1097.        
  1098.         //Get a reference to every Gem because they could be spread out between the active or upNext grid
  1099.         for(int y=0; y<_numRows; y++)
  1100.         {
  1101.             for(int x=0; x<_numColumns; x++)
  1102.             {
  1103.                 if(_upNextGrid[x,y] != null)
  1104.                 {  
  1105.                     temporaryGrid[temporaryGridIndex % _numColumns, temporaryGridIndex / _numColumns] = _upNextGrid[x,y];
  1106.                     temporaryGridIndex++;
  1107.                     _upNextGrid[x,y] = null;
  1108.                 }
  1109.                
  1110.                 if(_activeGrid[x,y] != null)
  1111.                 {  
  1112.                     temporaryGrid[temporaryGridIndex % _numColumns, temporaryGridIndex / _numColumns] = _activeGrid[x,y];
  1113.                     temporaryGridIndex++;
  1114.                     _activeGrid[x,y] = null;                   
  1115.                 }
  1116.             }
  1117.         }
  1118.        
  1119.         //Move all the gems to the upNext grid & set their position
  1120.         for(int y=0; y<_numRows; y++)
  1121.         {
  1122.             for(int x=0; x<_numColumns; x++)
  1123.             {
  1124.                 _upNextGrid[x,y] = temporaryGrid[x,y];
  1125.                 _upNextGrid[x,y].transform.position = _upNextGridPosition[x,y];
  1126.             }
  1127.         }
  1128.     }
  1129.    
  1130.     private void ConfirmValidBoardExists()
  1131.     {
  1132.         if(GetAreTilesMoving())
  1133.             return;
  1134.        
  1135.         //Checks the board to make sure there is a valid game board with at least one move. If there isnt, which should be very rare, the entire board will be reset.
  1136.         CheckForMoves(_activeGrid);
  1137.                    
  1138.         //If no hints are available, reset the board
  1139.         if(!_hintList.HasHints)
  1140.         {
  1141.             Debug.Log("There were no valid moves on the board. Resetting.");
  1142.            
  1143.             ResetGameBoard();
  1144.             GameWindow.Instance.SaveGameBoard();
  1145.         }
  1146.     }
  1147.     #endregion 
  1148.    
  1149.     private void AutoPlay()
  1150.     {      
  1151.         if(GetAreTilesMoving() || !_hintList.HasHints)
  1152.             return;
  1153.        
  1154.         //Get one of the best hints and use it
  1155.         Hint hint = _hintList.GetBestHint();
  1156.         SwapTiles(hint.Gem1Position, hint.Gem2Position, true);
  1157.     }
  1158.    
  1159.     #region :: Event Handlers ::
  1160.     private void HandleGemIsMovingChanged(object kinematicComponent, EventArgs e)
  1161.     {
  1162.         if(((Kinematic2D)kinematicComponent).IsMoving == false)
  1163.         {
  1164.             //If all the tiles on the board are done moving, check for matches                                            
  1165.             if(GetAreTilesMoving() == false)
  1166.             {
  1167.                 CheckForMatches(_activeGrid);
  1168.                
  1169.                 //If we found no matches but swapped a tile, reverse the swapping
  1170.                 if(_deathQueue.Count == 0 && _swappedTiles[0].IsValid)
  1171.                 {                  
  1172.                     SwapTiles(_swappedTiles[0], _swappedTiles[1], false);
  1173.                     return;
  1174.                 }
  1175.                 else if(_deathQueue.Count == 0)
  1176.                 {
  1177.                     return;
  1178.                 }
  1179.                
  1180.                 _swappedTiles[0].Reset();
  1181.                 _swappedTiles[1].Reset();
  1182.                    
  1183.                 //We must commit the treasure queue before the death queue because this method will remove a gem from the death queue for use by the treasure icon
  1184.                 CommitTreasureQueue();
  1185.                 CommitDeathQueue();
  1186.                 CommitScoreQueue();
  1187.                        
  1188.                 //Move the gems from the up next grid to the active grid
  1189.                 UpdateActiveGrid();
  1190.             }
  1191.         }
  1192.     }
  1193.    
  1194.     public void HandleInputPress(POINTER_INFO pointer)
  1195.     {
  1196.         //Ignore touches if we are moving tiles around
  1197.         if(GetAreTilesMoving() || this.PauseActiveGridUpdates)
  1198.             return;
  1199.                
  1200.         //Our pointer is in screen coordinates, convert this into world coordinates using our camera       
  1201.         Vector3 mouseWorldPosition = _inputComponent.RenderCamera.ScreenToWorldPoint(pointer.devicePos);
  1202.        
  1203.         //We need to adjust our mouse click to be relative to the lower left corner of the game grid so that it's easier to determine which grid x,y we clicked on.
  1204.         //We cached the lower left point of the grid during initialization in _lowerLeftPosition
  1205.         Vector3 mouseLowerLeftPosition = mouseWorldPosition - _lowerLeftPosition;
  1206.         int gridX = (int)(Math.Floor(mouseLowerLeftPosition.x) / _gemSize);
  1207.         int gridY = (int)(Math.Floor(mouseLowerLeftPosition.y) / _gemSize);
  1208.         Point2i tileIndex = new Point2i(gridX, gridY);
  1209.        
  1210.         //Check to see if the mouse input needs to be handled by the GameWindow because we have an active spell
  1211.         if(GameWindow.Instance.GetDoesActiveSpellExecuteOnUserInput())
  1212.         {
  1213.             GameWindow.Instance.ExecuteSpellsOnUserInput(tileIndex);
  1214.                
  1215.         }
  1216.         else if(_selectedTileCurrent.x != gridX || _selectedTileCurrent.y != gridY)
  1217.         {
  1218.             //No tiles are moving on the board, did we select a new tile?s
  1219.             SelectGridPosition(tileIndex);
  1220.         }
  1221.     }
  1222.    
  1223.     public void HandleInputDrag(POINTER_INFO pointer)
  1224.     {  
  1225.         //Ignore touches if we are moving tiles around
  1226.         if(GetAreTilesMoving() || this.PauseActiveGridUpdates)
  1227.             return;
  1228.        
  1229.         //Our pointer is in screen coordinates, convert this into world coordinates using our camera       
  1230.         Vector3 mouseWorldPositionStart = _inputComponent.RenderCamera.ScreenToWorldPoint(pointer.origPos);
  1231.         Vector3 mouseWorldPositionEnd = _inputComponent.RenderCamera.ScreenToWorldPoint(pointer.devicePos);
  1232.        
  1233.         //We need to adjust our mouse click to be relative to the lower left corner of the game grid so that it's easier to determine which grid x,y we clicked on.
  1234.         //We cached the lower left point of the grid during initialization in _lowerLeftPosition
  1235.         Vector3 mouseLowerLeftPositionStart = mouseWorldPositionStart - _lowerLeftPosition; //The position of the mouse relative to the lower left point on the game grid
  1236.         int gridXStart = (int)(Math.Floor(mouseLowerLeftPositionStart.x) / _gemSize);
  1237.         int gridYStart = (int)(Math.Floor(mouseLowerLeftPositionStart.y) / _gemSize);
  1238.        
  1239.         Vector3 mouseLowerLeftPositionEnd = mouseWorldPositionEnd - _lowerLeftPosition; //The position of the mouse relative to the lower left point on the game grid
  1240.         int gridXEnd = (int)(Math.Floor(mouseLowerLeftPositionEnd.x) / _gemSize);
  1241.         int gridYEnd = (int)(Math.Floor(mouseLowerLeftPositionEnd.y) / _gemSize);
  1242.        
  1243.         //Did the user drag the mouse far enough to be over another column? If so, try to swap them if it's a valid move
  1244.         if(gridXStart != gridXEnd && gridXEnd >= 0 && gridXEnd < _numColumns)
  1245.         {
  1246.             //Swap horizontally. We'll keep the original Y position just in case the user dragged diagonally
  1247.             if(gridXEnd > gridXStart)
  1248.                 SelectGridPosition(new Point2i(gridXStart + 1, gridYStart));
  1249.             else if(gridXEnd < gridXStart)
  1250.                 SelectGridPosition(new Point2i(gridXStart - 1, gridYStart));
  1251.         }
  1252.         else if(gridYStart != gridYEnd && gridYEnd >= 0 && gridYEnd < _numRows)
  1253.         {
  1254.             //Swap vertically. We'll keep the original X position just in case the user dragged diagonally
  1255.             if(gridYEnd > gridYStart)
  1256.                 SelectGridPosition(new Point2i(gridXStart, gridYStart + 1));
  1257.             else if(gridYEnd < gridYStart)
  1258.                 SelectGridPosition(new Point2i(gridXStart, gridYStart - 1));
  1259.         }
  1260.     }
  1261.     #endregion
  1262.    
  1263.     #region :: Public Methods ::
  1264.     public void ResetGameBoard()
  1265.     {
  1266.         //Ensure all our gems are in the UpNext grid
  1267.         MoveAllGemsToUpNext();
  1268.        
  1269.         //Guarantee that there's at least 5 matches in the upNextGrid so that we'll always have a valid board when the game starts
  1270.         _hintList.Clear();
  1271.         while(_hintList.NumHints < 4)
  1272.         {  
  1273.             for(int y=0; y<_numRows; y++)
  1274.             {
  1275.                 for(int x=0; x<_numColumns; x++)
  1276.                 {                  
  1277.                     _upNextGrid[x,y].GemID = GemDataModel.Instance.GetRandomGemID();
  1278.                 }
  1279.             }          
  1280.            
  1281.             //Check to see if there are any matches -- we want none when it starts         
  1282.             CheckForMatches(_upNextGrid);
  1283.             if(_deathQueue.Count > 0)
  1284.             {
  1285.                 continue;
  1286.             }
  1287.             else
  1288.             {
  1289.                 CheckForMoves(_upNextGrid);
  1290.             }
  1291.         }
  1292.        
  1293.         //Tell the game to fill in the empty holes in the game grid with those in the upNext grid
  1294.         UpdateActiveGrid();
  1295.     }
  1296.    
  1297.     public void ShowHint()
  1298.     {
  1299.         Hint hint = _hintList.GetBestHint();
  1300.        
  1301.         if(hint != null)
  1302.         {
  1303.             //Put the hint arrows to show what to swap
  1304.             this.HintArrow1.gameObject.active = true;
  1305.             this.HintArrow2.gameObject.active = true;
  1306.            
  1307.             this.HintArrow1.SpriteGraphics.Hide(false);
  1308.             this.HintArrow2.SpriteGraphics.Hide(false);
  1309.            
  1310.             //Find the position for the arrows that will place them at the top of the gems
  1311.             Vector3 hintArrow1Position = GetCenterPointFromGridCoords(hint.Gem1Position, GameLayer.HintArrows) + new Vector3(0, _gemSize/2, 0);
  1312.             Vector3 hintArrow2Position = GetCenterPointFromGridCoords(hint.Gem2Position, GameLayer.HintArrows) + new Vector3(0, _gemSize/2, 0);
  1313.            
  1314.             //Tell the hint arrows to animate up and down
  1315.             this.HintArrow1.Kinematic.MoveBetween(hintArrow1Position + new Vector3(0, this.HintArrowBobDistance, 0), hintArrow1Position - new Vector3(0, this.HintArrowBobDistance, 0), this.HintArrowMoveSpeed);
  1316.             this.HintArrow2.Kinematic.MoveBetween(hintArrow2Position + new Vector3(0, this.HintArrowBobDistance, 0), hintArrow2Position - new Vector3(0, this.HintArrowBobDistance, 0), this.HintArrowMoveSpeed);
  1317.            
  1318.             ScheduleTimer("HideHintArrows", 2.0f, HideHintArrows);
  1319.         }
  1320.        
  1321.         AudioManager.Instance.Play(AudioClips.UI_TAP);
  1322.     }
  1323.    
  1324.     public Gem GetGemAtPosition(Point2i tileIndex)
  1325.     {
  1326.         return _activeGrid[tileIndex.x, tileIndex.y];      
  1327.     }
  1328.    
  1329.     public void PlayGemsFallSound()
  1330.     {
  1331.         //GameWindow.Instance.SoundGemsFall.PlayOneShot(GameWindow.Instance.SoundGemsFall.clip);
  1332.     }
  1333.     #endregion
  1334.    
  1335.     #region :: Public Properties ::
  1336.     public int NumRows
  1337.     {
  1338.         get
  1339.         {
  1340.             return _numRows;
  1341.         }
  1342.     }
  1343.    
  1344.     public int NumColumns
  1345.     {
  1346.         get
  1347.         {
  1348.             return _numColumns;
  1349.         }
  1350.     }
  1351.    
  1352.     public float GemSize
  1353.     {
  1354.         get
  1355.         {
  1356.             return _gemSize;
  1357.         }
  1358.     }
  1359.    
  1360.     public float Width
  1361.     {
  1362.         get
  1363.         {
  1364.             return _numColumns * _gemSize;
  1365.         }
  1366.     }
  1367.    
  1368.     public float Height
  1369.     {
  1370.         get
  1371.         {
  1372.             return _numRows * _gemSize;
  1373.         }
  1374.    
  1375.     }
  1376.    
  1377.     public SpriteManager SpriteManager
  1378.     {
  1379.         get
  1380.         {
  1381.             return _spriteManagerComponent;
  1382.         }
  1383.     }
  1384.     #endregion
  1385. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement