public Match3BoardPiece AttachTileToBoardAt(int rowIdx, int columnIdx, Match3Tile tile, bool offBoardTile, bool isBoardSetup = false, bool resetTilePosition = true) { // Assign the tile to the specified BoardPiece. Match3BoardPiece targetBoardPiece = Board[rowIdx, columnIdx] as Match3BoardPiece; if (isBoardSetup) { targetBoardPiece.TileRef = tile; } else { targetBoardPiece.Tile = tile; // if (targetBoardPiece.BottomLink != null && targetBoardPiece.BottomLink.Tile != null && targetBoardPiece.BottomLink.Tile.IsMoving) { // Match3Tile nextTile = targetBoardPiece.BottomLink.Tile as Match3Tile; // newTile.moveVel = Mathf.Clamp(nextTile.moveVel - newTile.initialVel, -newTile.initialVel, newTile.maxVel); // } } if (resetTilePosition) { targetBoardPiece.ResetTilePosition(); } // if (offBoardTile) // { // Match3BoardPiece bottomLinkPiece = targetBoardPiece.BottomLink; // Vector3 tileLocalPos = newTile.LocalPosition; // // if (bottomLinkPiece != null && bottomLinkPiece.Tile != null && bottomLinkPiece.LocalPosition.y < bottomLinkPiece.Tile.LocalPosition.y) // { // tileLocalPos.y = bottomLinkPiece.Tile.LocalPosition.y + verticalTileDistance + verticalTileOffset; // } // else { // tileLocalPos.y = targetBoardPiece.LocalPosition.y + verticalTileDistance + verticalTileOffset; // } // // newTile.LocalPosition = tileLocalPos; // //// Debug.LogWarning("Spawning offboard tile at : " + tileLocalPos); // //Debug.Break(); // } if (!isBoardSetup && !offBoardTile) { tile.InitAfterAttachedToBoard(); } return(targetBoardPiece); }
public bool GenerateMatch(bool _isBoardSetup) { isBoardSetup = _isBoardSetup; normalTiles.Clear(); for (int i = 0; i < tilesBuffers.Length; i++) { tilesBuffers[i].Clear(); } // tileBufferIndices.Clear(); possibleMatchSlots.Clear(); // Collect all normal tiles and create tile buffers for each color. Board.ApplyActionToAll((boardPiece) => { if (boardPiece.Tile != null && boardPiece.Tile.GetType() == typeof(NormalTile) && (!isBoardSetup || !(boardPiece.Tile as NormalTile).IsTileIgnoredByAntiMatchSystems)) { Match3Tile tile = boardPiece.Tile as Match3Tile; normalTiles.Add(tile); // Add tile to corresponding color buffer. tilesBuffers[(int)tile.TileColor].Add(tile); } }); // No tiles allowed to be overriden by possible match generator if (normalTiles.Count == 0) { // Debug.LogWarning("[PossibleMatchGenerator] No normal tiles allowed to be touched by PossibleMatchGenerator..."); return(false); } // for(int i = 1; i < tilesBuffers.Length; i++) // { // Debug.LogWarning((TileColorType)i + " => " + tilesBuffers[i].Count); // } // Sort tile buffer indices descending. // After sorting the tile buffers the first tile buffer will contain the tiles that have the biggest count on the board. // So tileBuffers[0] won't represent the colored tiles buffer of the TileColorType.None anymore. (which was an empty buffer anyway) SortTilesBuffersCountDescending(); if (tilesBuffers[0].Count < 3) { TileColorType tileColorNeeded = tilesBuffers[0][0].TileColor; // Debug.LogWarning("[PossibleMatchGenerator] The color we need to generate: " + tileColorNeeded); // Go through each tile buffer and convert tiles into the color we need above to get at least 3 tiles of the same color // so we can create a possible match on the board. for (int i = 1; i < tilesBuffers.Length && tilesBuffers[0].Count < 3; i++) { int numAvailableTiles = tilesBuffers[i].Count; for (int j = 0; j < numAvailableTiles && tilesBuffers[0].Count < 3; j++) { Match3BoardPiece tilePiece = tilesBuffers[i][j].BoardPiece as Match3BoardPiece; // Destroy old tiles GameObject.DestroyImmediate(tilePiece.Tile.gameObject); tilesBuffers[i][j] = null; // Create new tile of the color we need. Match3Tile newTile = Match3BoardRenderer.Instance.SpawnSpecificTileAt(tilePiece.BoardPosition, typeof(NormalTile), tileColorNeeded, false, isBoardSetup); // Do any customization to new tiles spawned by this system. if (OnNewTileSpawned != null) { OnNewTileSpawned(newTile); } tilesBuffers[0].Add(newTile); } } } // Debug.LogWarning("[PossibleMatchGenerator] After repopulating with tiles:"); // for(int i = 0; i < tilesBuffers.Length; i++) // { // Debug.Log((TileColorType)i + " => " + tilesBuffers[i].Count); // } // Find a location on the board where to place the 3 tiles from the tile buffer 0 to create a possible match. if (FindPossibleMatchLocation()) { // Create possible match on the board for (int i = 0; i < possibleMatchSlots.Count; i++) { Match3Tile tempTile = possibleMatchSlots[i].Tile as Match3Tile; Match3BoardPiece targetPiece = tilesBuffers[0][i].BoardPiece as Match3BoardPiece; if (tempTile != targetPiece.Tile) { possibleMatchSlots[i].Tile = tilesBuffers[0][i]; targetPiece.Tile = tempTile; targetPiece.ResetTilePosition(); possibleMatchSlots[i].ResetTilePosition(); } } return(true); } return(false); // else // { // Debug.LogWarning("No possible match location found!!!"); // } }
/// <summary> /// Active gravity check coroutine. When it stops, it should go back up to passive gravity checking. /// </summary> /// <returns> /// The gravity check. /// </returns> protected IEnumerator ActiveGravityChecker() { Match3BoardPiece curPiece = null; Match3BoardPiece nextPiece = null; Match3BoardPiece startingPiece = null; bool waitedForOtherTile = false; bool boardCoordUpdated; while (GravityUpdateEnabled) { // Safety check block. (especially for when a tile might be removed from the board meaning it has no BoardPiece that it doesn't belong to it. if (!enabled || !GravityEnabled || BoardPiece == null) { yield return(null); continue; } debugActiveGravity = true; curPiece = BoardPiece as Match3BoardPiece; if (startingPiece == null) { startingPiece = curPiece; } fallDestination = curPiece.LocalPosition; boardCoordUpdated = false; waitedForOtherTile = false; bool hasReachedBoardPieceArea = HasReachedBoardPieceArea(); // If the tile has previously moved diagonally, we must wait for it to reach it's new current board piece position first and then // continue to fall down vertically. if (/*hasReachedBoardPieceArea &&*/ curPiece.LockCount <= 0 && curPiece.BottomLink != null && !curPiece.BottomLink.IsBlocked && (tileMovedDiagonally && hasReachedBoardPieceArea || !tileMovedDiagonally)) { //TODO: to the same loop check like below for the diagonal tiles to fix the bug where 2 tiles one above the other can start to move diagonally at the same time if (curPiece.BottomLink.Tile == null) { nextPiece = curPiece.BottomLink; boardCoordUpdated = true; tileMovedDiagonally = false; } else if (curPiece.BottomLink.Tile.IsMoving && HasTileInArea(curPiece.BottomLink.Tile as Match3Tile)) { // Adopt the velocity of the moving tile in front only if it's in the vicinity of this current tile. moveVel = (curPiece.BottomLink.Tile as Match3Tile).moveVel; } } //TODO: separate and merge these repeating block of code in a nice method that can be called here and remove boilerplate code (when there is human time to do so). //Was left like this for easier debugging and code flow following. // Don't move sideways if we can already move vertically and until the tile has reached it's target fallDestination. if (!boardCoordUpdated && hasReachedBoardPieceArea) { if (curPiece.BottomLeftLink != null && !curPiece.BottomLeftLink.IsBlocked && !curPiece.BottomLeftLink.IsTileSpawner) { if (curPiece.Left == null || curPiece.Left.IsBlocked || curPiece.Left.IsOrphan || curPiece.Left.IsTemporaryOrphan) { if (curPiece.BottomLeftLink.Tile != null && curPiece.BottomLeftLink.Tile.IsMoving) { float nextVel = initialVel; bool raisedTileStoppedMoving = false; do { if (!raisedTileStoppedMoving && UpdateTilePhysics(curPiece)) { raisedTileStoppedMoving = true; TileStoppedMoving(ref startingPiece); } nextVel = (curPiece.BottomLeftLink.Tile as Match3Tile).moveVel; if (curPiece.BottomLeftLink.Tile.IsMoving) { moveVel = nextVel; } yield return(null); } while(curPiece.BottomLeftLink.Tile != null && curPiece.BottomLeftLink.Tile.IsMoving); waitedForOtherTile = true; // Apply the move speed from the moving tile after waiting moveVel = nextVel; } if (curPiece.BottomLeftLink.Tile == null) { if (waitedForOtherTile) { moveVel = Mathf.Clamp(moveVel * (1f - velWaitDampFactor), initialVel, maxVel); } nextPiece = curPiece.BottomLeftLink; boardCoordUpdated = true; tileMovedDiagonally = true; } else if (waitedForOtherTile) { // The tile that we've been waiting for changed its status to IsMoving=false and it didn't clear the way for this tile // so we have to go back up and re-analyze the possible directions in which this tile can move. continue; } } } if (!boardCoordUpdated && curPiece.BottomRightLink != null && !curPiece.BottomRightLink.IsBlocked && !curPiece.BottomRightLink.IsTileSpawner) { if (curPiece.Right == null || curPiece.Right.IsBlocked || curPiece.Right.IsOrphan || curPiece.Right.IsTemporaryOrphan) { if (curPiece.BottomRightLink.Tile != null && curPiece.BottomRightLink.Tile.IsMoving) { float nextVel = initialVel; bool raisedTileStoppedMoving = false; do { if (!raisedTileStoppedMoving && UpdateTilePhysics(curPiece)) { raisedTileStoppedMoving = true; TileStoppedMoving(ref startingPiece); } nextVel = (curPiece.BottomRightLink.Tile as Match3Tile).moveVel; if (curPiece.BottomRightLink.Tile.IsMoving) { moveVel = nextVel; } yield return(null); } while(curPiece.BottomRightLink.Tile != null && curPiece.BottomRightLink.Tile.IsMoving); waitedForOtherTile = true; // Apply the move speed from the moving tile after waiting moveVel = nextVel; } if (curPiece.BottomRightLink.Tile == null) { if (waitedForOtherTile) { // Apply velocity damping for tiles that waited last time moveVel = Mathf.Clamp(moveVel * (1f - velWaitDampFactor), initialVel, maxVel); } nextPiece = curPiece.BottomRightLink; boardCoordUpdated = true; tileMovedDiagonally = true; } else if (waitedForOtherTile) { // The tile that we've been waiting for changed its status to IsMoving=false and it didn't clear the way for this tile // so we have to go back up and re-analyze the possible directions in which this tile can move. continue; } } } } if (boardCoordUpdated) { fallDestination = nextPiece.LocalPosition; curPiece.MoveTileTo(nextPiece); curPiece.UpdateOrphanState(); } bool hasTileReachedFallDestination = UpdateTilePhysics(curPiece); // Check gravity stop condition if (!boardCoordUpdated && hasTileReachedFallDestination && (nextPiece == null || (nextPiece.Tile != null && !nextPiece.Tile.IsMoving) || curPiece == nextPiece || curPiece.LockCount > 0)) { // Attach this tile to its current board piece. (correctly updating all other internal states of the board piece) curPiece.Tile = this; // Set the local position of this tile to the local position of it's new owner board piece curPiece.ResetTilePosition(); TileStoppedMoving(ref startingPiece); RaiseEventTileFinishedActiveGravity(startingPiece); // Reset the current move velocity of the tile moveVel = 0f; break; } yield return(null); } debugActiveGravity = false; }