/// <summary> /// Passive gravity check coroutine. /// </summary> /// <returns> /// The gravity check. /// </returns> protected IEnumerator PassiveGravityChecker() { Match3BoardPiece curPiece = null; while (GravityUpdateEnabled) { if (!enabled || !GravityEnabled || BoardPiece == null) { yield return(null); continue; } debugPassiveGravity = true; curPiece = BoardPiece as Match3BoardPiece; // Check for active gravity enabling only if we're not moving and we're in a board piece that has no lock set on it. if (!IsMoving && curPiece.LockCount <= 0) { if (!HasReachedBoardPieceArea() || (curPiece.BottomLink != null && !curPiece.BottomLink.IsBlocked && curPiece.BottomLink.Tile == null) || (curPiece.BottomLeftLink != null && !curPiece.BottomLeftLink.IsBlocked && !curPiece.BottomLeftLink.IsTileSpawner && curPiece.BottomLeftLink.Tile == null && (curPiece.Left == null || curPiece.Left.IsBlocked || curPiece.Left.IsOrphan)) || (curPiece.BottomRightLink != null && !curPiece.BottomRightLink.IsBlocked && !curPiece.BottomRightLink.IsTileSpawner && curPiece.BottomRightLink.Tile == null && (curPiece.Right == null || curPiece.Right.IsBlocked || curPiece.Right.IsOrphan))) { // if (curPiece.BoardPosition.row == 0) { // Debug.LogWarning("PassiveGravity started for: " + curPiece.name + "\n" + // "curPiece.BottomRightLink != null => " + (curPiece.BottomLeftLink != null) + "\n" + // "!curPiece.BottomRightLink.IsBlocked => " + (!curPiece.BottomRightLink.IsBlocked) + "\n" + // "curPiece.BottomRightLink.Tile == null => " + (curPiece.BottomRightLink.Tile == null) + "\n" + // "curPiece.Right == null => " + (curPiece.Right == null) + "\n" + // "curPiece.Right.IsBlocked => " + (curPiece.Right.IsBlocked) + "\n" + // "curPiece.Right.IsOrphan => " + (curPiece.Right.IsOrphan) + "\n"); // // Debug.Break(); // } // Pass the control to the Active gravity checker. IsMoving = true; // Add the initial velocity to the current move velocity (that should be reset to zero when the tile finishes falling). moveVel += initialVel; tileMovedDiagonally = false; RaiseEventTileStartedActiveGravity(); break; } } yield return(null); } debugPassiveGravity = false; }
/// <summary> /// Copies the links from this board piece to a designated target board piece. /// </summary> public void CopyLinksTo(Match3BoardPiece target) { for (int i = 0; i < (int)LinkType.Count; i++) { target.links[i] = links[i]; } }
protected TileColorType GetMatchingColorBetweenDirections(Match3BoardPiece startPiece, Match3BoardPiece.LinkType dirA, Match3BoardPiece.LinkType dirB) { Match3BoardPiece pieceDirA = startPiece.GetNeighbor(dirA); Match3BoardPiece pieceDirB = null; if (dirA != dirB) { pieceDirB = startPiece.GetNeighbor(dirB); } else if (pieceDirA != null) { pieceDirB = pieceDirA.GetNeighbor(dirA); } if (pieceDirA != null && pieceDirB != null) { Match3Tile tileDirA = pieceDirA.Tile as Match3Tile; Match3Tile tileDirB = pieceDirB.Tile as Match3Tile; if (tileDirA != null && tileDirB != null && tileDirA.CanBeMatched && tileDirB.CanBeMatched && tileDirA.IsMatchWith(tileDirB)) { return(tileDirA.TileColor); } } return(TileColorType.None); }
void Awake() { boardPiece = GetComponent<Match3BoardPiece>(); // Mark the Match3BoardPiece this component is on as being a tile spawner. boardPiece.IsTileSpawner = true; }
void OnBoardPieceEnteredFreezeTrigger(Match3BoardPiece boardPiece) { if (boardPiece is LayeredBoardPiece) { layeredBoardPiecesToDestroy.Add(boardPiece); } }
protected bool LookupPossibleNeighborSlotsFor(Match3BoardPiece piece) { int numNeighborDirections = (int)Match3BoardPiece.LinkType.Count; possibleMatchSlots.Clear(); for (int i = 0; i < numNeighborDirections; i += 2) { // Count max 2 neighbors in each direction Match3BoardPiece neighborIterator = piece; for (int j = 0; j < 2; j++) { neighborIterator = neighborIterator.GetNeighbor((Match3BoardPiece.LinkType)i); if (neighborIterator != null && neighborIterator.Tile != null && neighborIterator.Tile.GetType() == typeof(NormalTile) && (!isBoardSetup || !(neighborIterator.Tile as NormalTile).IsTileIgnoredByAntiMatchSystems)) { possibleMatchSlots.Add(neighborIterator); if (possibleMatchSlots.Count == 3) { return(true); } } else { break; } } } return(false); }
public Match3Tile SpawnTileAt(Match3BoardPiece boardPiece, BoardCoord boardPos, GameObject tilePrefab) { // Destroy previous tile from board piece (if present). if (boardPiece.EditorTile != null) { // Remove the first spawn rule entry for this tile if it corresponds to its type. SetBoardPieceSpawnRuleForTile(boardPiece, boardPiece.EditorTile, true); GameObject.DestroyImmediate(boardPiece.EditorTile.gameObject); } GameObject newTileGO = PrefabUtility.InstantiatePrefab(tilePrefab) as GameObject; PrefabUtility.DisconnectPrefabInstance(newTileGO); Match3Tile newTile = newTileGO.GetComponent <Match3Tile>(); newTile.name = string.Format("[{0},{1}] {2}", boardPos.row, boardPos.col, newTile.name); newTile.transform.parent = boardRenderer.transform; newTile.transform.localPosition = boardPiece.transform.localPosition - boardRenderer.transform.forward * 2f; boardPiece.EditorTile = newTile; // Add the first spawn rule entry for with this tile's type. SetBoardPieceSpawnRuleForTile(boardPiece, boardPiece.EditorTile); return(newTile); }
public void ApplyPunchEffectToNeighbors(int xSign, int ySign, int zSign) { // Apply punch effect to neighbors at the end of the current frame Match3BoardPiece boardPiece = BoardPiece as Match3BoardPiece; if (boardPiece != null) { int numNeighbors = (int)Match3BoardPiece.LinkType.Count; Match3BoardPiece neighbor = null; for (int i = 0; i < numNeighbors; i++) { neighbor = boardPiece.GetNeighbor((Match3BoardPiece.LinkType)i); if (neighbor != null && neighbor.Tile != null && !neighbor.Tile.IsDestroying) { Vector3 punchHeading = neighbor.Tile.LocalPosition - LocalPosition; // Some of the tile model axis don't correspond with their parent axis and so the calculated direction must changed. punchHeading.x = punchHeading.x * xSign; punchHeading.y = punchHeading.y * ySign; punchHeading.z = punchHeading.z * zSign; // Apply the punch effect at the end of the current frame (neighbor.Tile as NormalTile).ApplyLateUpdatePunchEffect(punchHeading); } } } }
/// <summary> /// Finds the matching board pieces around the specified "boardPiece", looking at all neighbors in the 4 directions of this board piece /// and caches the pairs of colors found in the partial matches buffers "partialTileMatches". /// If any color type buffer from the "partialTileMatches" reaches a count of 3 then we found a possible match for this board piece. /// This method /// </summary> /// <returns> /// <c>true</c> if the method allows the processing to continue to the next board piece. /// </returns> /// <param name='boardPiece'> /// The current board piece being processed. /// </param> protected bool FindMatchingBoardPiecesAround(AbstractBoardPiece boardPiece) { Match3BoardPiece curPiece = boardPiece as Match3BoardPiece; // Skip this board piece. if (curPiece.Tile == null || curPiece.IsBlocked /*|| !(curPiece.Tile as Match3Tile).CanBeMatched*/ || !curPiece.Tile.IsUserMoveable || curPiece.Tile.IsDestroying || (curPiece.Tile as NormalTile).IsTileSwitching || (curPiece.Tile as NormalTile).IsFrozen()) { return(true); } // Clear partial matches buffers ClearPartialMatchesBuffers(); // If the current board piece we're on is a special trigger tile, add it to the trigger tiles bag in case we find another one around it. if (curPiece.Tile is TriggerTile) { triggerTileMatchFound.Add(curPiece.Tile as Match3Tile); } // Go to maximum 2 recursive neighbors (in each of the 4 directions) and check if they match. // If the first neighbor in the current direction doesn't match the next neighbor then don't add the 2nd neighbor in the // "partialTileMatches" buffer and only add the first one. Otherwise, add them both if they match. for (int i = 0; i < dirIndices.Length; i++) { if (!FindMatchingNeighborPiecesFor(curPiece, dirIndices[i])) { return(false); } } return(true); }
void Awake() { boardPiece = GetComponent <Match3BoardPiece>(); // Mark the Match3BoardPiece this component is on as being a tile spawner. boardPiece.IsTileSpawner = true; }
protected TileColorType[] ComputeIgnoreColorListFromNeighbors(Match3BoardPiece startPiece) { ignoreCount = 0; for (int i = 0; i < colorsToIgnore.Length; i++) { colorsToIgnore[i] = false; } LookupMatchingColors(startPiece, LookupDirection.Vertical); LookupMatchingColors(startPiece, LookupDirection.Horizontal); if (ignoreCount == 0) { return(null); } else { // Prepare lookup results. (an array of colors to ignore when picking a new random color for the current tile (on the "startPiece" board piece). TileColorType[] result = new TileColorType[ignoreCount]; int resultIdx = 0; for (int i = 1; i < colorsToIgnore.Length; i++) { if (colorsToIgnore[i]) { result[resultIdx++] = (TileColorType)i; } } return(result); } }
/// <summary> /// Raises the tile finished active gravity event. /// This event should set the "IsMoving" property to false when it finishes any tile bounce animation. /// </summary> public virtual void RaiseEventTileFinishedActiveGravity(Match3BoardPiece startingBoardPiece) { if (OnTileFinishedActiveGravity != null) { OnTileFinishedActiveGravity(this, startingBoardPiece); } }
public void UpdateBoardPieceGridTransform(Match3BoardPiece boardPiece, BoardCoord newGridPos) { Vector3 gridOffset = Vector3.zero; gridOffset.x = newGridPos.col * boardRenderer.horizontalTileDistance + boardRenderer.horizontalTileOffset; gridOffset.y = -newGridPos.row * boardRenderer.verticalTileDistance + boardRenderer.verticalTileOffset; boardPiece.transform.localPosition = gridOffset; }
/// <summary> /// Updates the falling tile position. /// </summary> /// <returns> /// The distance between the tile and the current fall destination. /// </returns> /// <param name='destination'> /// Destination. /// </param> protected void UpdateFallingTilePosition(Match3BoardPiece curPiece) { // Update fall direction moveDir = (fallDestination - LocalPosition).normalized; // Calculate and apply displacement. LocalPosition += moveDir * moveVel * Time.deltaTime; }
/// <summary> /// Raises the board piece button pressed event when pressing a level editor button in the Unity scene view. /// </summary> /// <param name='refBoardPiece'> /// Board piece. /// </param> /// <param name='rowIdx'> /// Row index. /// </param> /// <param name='colIdx'> /// Col index. /// </param> void OnBoardPieceButtonPressed(ref Match3BoardPiece refBoardPiece, BoardCoord boardPos) { // Validate the current board tool selection (the currently selected prefab) // editor.selectedBoardTool = Selection.activeGameObject; object selectedToolObj = null; if (editor.selectedBoardTool != null) { if (editor.selectedBoardTool.GetComponent <Match3BoardPiece>()) { selectedToolObj = editor.selectedBoardTool.GetComponent <Match3BoardPiece>(); } if (editor.selectedBoardTool.GetComponent <Match3Tile>()) { selectedToolObj = editor.selectedBoardTool.GetComponent <Match3Tile>(); } } if (selectedToolObj is Match3BoardPiece) { // Get the currently selected board tool type if (!LevelEditorUtils.IsPrefabInArray(editor.boardRenderer.prefabsPieces, editor.selectedBoardTool)) { EditorUtility.DisplayDialog("Level Editor", "The selected board prefab is not added to the Match3BoardRenderer pieces prefab list!", "Ok"); return; } // Spawn a new board piece editor.SpawnBoardPieceAt(boardPos, editor.selectedBoardTool); } else if (selectedToolObj is Match3Tile) { // Get the currently selected board tool type if (!LevelEditorUtils.IsPrefabInArray(editor.boardRenderer.tilesPrefabs, editor.selectedBoardTool)) { EditorUtility.DisplayDialog("Level Editor", "The selected board prefab is not added to the Match3BoardRenderer tiles prefab list!", "Ok"); return; } else if (refBoardPiece == null) { // Spawn a default board piece if none found at the current board position. editor.SpawnBoardPieceAt(boardPos, editor.defaultBoardPiece.gameObject); editor.UpdateBoardPieceGridTransform(refBoardPiece, boardPos); } // Spawn a new tile on the selected board piece. editor.SpawnTileAt(refBoardPiece, boardPos, editor.selectedBoardTool); } else { EditorUtility.DisplayDialog("Level Editor", "The selected board prefab type is not supported!", "Ok"); return; } }
public void OnApplyToSelectionButtonPressed() { GameObject[] selectedGOs = Selection.gameObjects; for (int i = 0; i < selectedGOs.Length; i++) { Match3BoardPiece selectedBoardPiece = selectedGOs[i].GetComponent <Match3BoardPiece>(); if (selectedBoardPiece != null) { editor.ApplyCurrentBoardToolToPos(selectedBoardPiece.editorBoardPos); } } }
/// <summary> /// Destroies the specified board piece and it's tile if it has one. /// </summary> /// <param name='piece'> /// Piece. /// </param> public void DestroyBoardPiece(Match3BoardPiece piece) { if (piece != null) { // Make sure we destroy it's tile if it has one. if (piece.EditorTile != null) { GameObject.DestroyImmediate(piece.EditorTile.gameObject); } // Destroy the board piece. GameObject.DestroyImmediate(piece.gameObject); } }
public bool TryRandomMoveAround(Match3BoardPiece piece) { // Get all valid neighbor tiles for the current starting board piece position GetValidTargetNeighborTilesFor(piece); if (possibleTargetTiles.Count > 0 && TileSwitchInput.Instance.IsEnabled && gameLogic.TryToMoveTile(piece.Tile, possibleTargetTiles[Random.Range(0, possibleTargetTiles.Count)])) { return(true); } return(false); }
public void GetValidTargetNeighborTilesFor(Match3BoardPiece piece) { possibleTargetTiles.Clear(); for (int i = 0; i < (int)Match3BoardPiece.LinkType.Count; i += 2) { Match3BoardPiece neighbor = piece.GetNeighbor((Match3BoardPiece.LinkType)i); if (neighbor != null && neighbor.Tile != null && neighbor.Tile.IsUserMoveable) { possibleTargetTiles.Add(neighbor.Tile as Match3Tile); } } }
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); }
protected void LookupMatchingColors(Match3BoardPiece startPiece, LookupDirection lookupDir) { int lookupOffset = (int)lookupDir; int numPatterns = baseLookupPattern.GetLength(0); for (int i = 0; i < numPatterns; i++) { Match3BoardPiece.LinkType lookupDirA = (Match3BoardPiece.LinkType)((int)baseLookupPattern[i, 0] + lookupOffset); Match3BoardPiece.LinkType lookupDirB = (Match3BoardPiece.LinkType)((int)baseLookupPattern[i, 1] + lookupOffset); ignoreCount = AddToIgnoreList(GetMatchingColorBetweenDirections(startPiece, lookupDirA, lookupDirB)); } }
public void OnDeleteButtonPressed(Match3BoardPiece boardPiece) { if (boardPiece != null && boardPiece.EditorTile != null) { // If there's a tile on this board piece, destroy the tile first editor.SetBoardPieceSpawnRuleForTile(boardPiece, boardPiece.EditorTile, true); GameObject.DestroyImmediate(boardPiece.EditorTile.gameObject); } else if (boardPiece != null) { // If there's only a board piece, destroy it. GameObject.DestroyImmediate(boardPiece.gameObject); editor.boardGrid[boardPiece.editorBoardPos.row, boardPiece.editorBoardPos.col] = null; } }
protected void Awake() { boardPiece = GetComponent<Match3BoardPiece>(); boardPiece.OnTileChanged += OnTileChanged; dropTileIndicator = (GameObject.Instantiate(Resources.Load(dropTileIndicatorResourcePath)) as GameObject).transform; dropTileIndicator.parent = boardPiece.cachedTransform; dropTileIndicator.localPosition = dropTileIndicatorLocalPosition; topSpawnMaskTransform = (GameObject.Instantiate(Resources.Load(dropTileMaskPath)) as GameObject).transform; topSpawnMaskTransform.name = "DropTileMask"; topSpawnMaskTransform.parent = transform.parent; topSpawnMaskTransform.localPosition = transform.localPosition; topSpawnMaskTransform.localPosition += maskOffset * Match3BoardRenderer.vertTileDistance; }
protected void Awake() { boardPiece = GetComponent <Match3BoardPiece>(); boardPiece.OnTileChanged += OnTileChanged; dropTileIndicator = (GameObject.Instantiate(Resources.Load(dropTileIndicatorResourcePath)) as GameObject).transform; dropTileIndicator.parent = boardPiece.cachedTransform; dropTileIndicator.localPosition = dropTileIndicatorLocalPosition; topSpawnMaskTransform = (GameObject.Instantiate(Resources.Load(dropTileMaskPath)) as GameObject).transform; topSpawnMaskTransform.name = "DropTileMask"; topSpawnMaskTransform.parent = transform.parent; topSpawnMaskTransform.localPosition = transform.localPosition; topSpawnMaskTransform.localPosition += maskOffset * Match3BoardRenderer.vertTileDistance; }
protected override void TileStoppedMoving(ref Match3BoardPiece startingPiece) { base.TileStoppedMoving(ref startingPiece); Match3BoardPiece currentPiece = BoardPiece as Match3BoardPiece; // Do the bounce animation only if the actual BoardPiece and the reported current piece where the tile stopped are different. if (currentPiece != startingPiece) { startingPiece = currentPiece; if (!fallBounceAnimEnabled) { StartCoroutine(ApplyTileBounceEffect(fallBounceStiffness, fallBouncePower)); } } }
/// <summary> /// Determines the board links and neighbors. /// Each board piece will have the reference to its direct neighbor (Top, TopRight, Right, etc.) or null for border pieces. /// Also, each board piece will have the reference to its logical linked neighbor (TopLink, TopRightLink, etc.) or null if they don't have /// any link in a certain direction. /// The logical links are mostly used for the logic behind the tiles gravity system. /// For example when dealing with empty board pieces, the piece above the empty slot will have logical link to the non-empty-piece below the empty slot. /// Thus it will fall through the empty pieces. /// </summary> public void DetermineBoardLinksAndNeighbors() { // Auto-determine board pieces neighbors. (only for pieces that have the "autoDetermineNeighbors" flag set) Board.ApplyActionToAll((boardPiece) => { Match3BoardPiece match3Piece = boardPiece as Match3BoardPiece; match3Piece.UpdateNeighbors(); if (match3Piece.autoDetermineLinks) { match3Piece.UpdateLinks(); } }); if (OnDetermineBoardLinksAndNeighbors != null) { OnDetermineBoardLinksAndNeighbors(); } }
protected void DestroyThisStuff(Match3BoardPiece boardPiece) { LayeredBoardPiece frostPiece = (boardPiece as LayeredBoardPiece); if (frostPiece != null && frostPiece.NumLayers > 0 && frostPiece.Tile == null) { frostPiece.NumLayers--; } else if (boardPiece.Tile != null) { if (frostPiece != null && (frostPiece.Tile is SnowTile || frostPiece.Tile is LockedTile || frostPiece.Tile is FreezerTile)) { frostPiece.NumLayers--; } boardPiece.Tile.Destroy(); } }
public bool UpdateTilePhysics(Match3BoardPiece curPiece) { // Update tile physics (apply gravity). // if (!waitingForOtherTile) { UpdateFallingTilePosition(curPiece); bool hasTileReachedFallDestination = HasTileReachedFallDestination(ref fallDestination); if (!hasTileReachedFallDestination) { // Update and limit tile maximum speed. moveVel = Mathf.Min(moveVel + accel * Time.smoothDeltaTime, maxVel); } else { LocalPosition = fallDestination; } return(hasTileReachedFallDestination); }
public override void RaiseEventTileFinishedActiveGravity(Match3BoardPiece startingBoardPiece) { base.RaiseEventTileFinishedActiveGravity(startingBoardPiece); IsMoving = false; if (!canBounce) { return; } // This tile can't bounce again until it passes at least once through passive gravity again. canBounce = false; if ((startingBoardPiece != BoardPiece) && !fallBounceAnimEnabled) { StartCoroutine(ApplyTileBounceEffect(fallBounceStiffness, fallBouncePower)); } // StartCoroutine(ApplyTileFallElasticEffect(curPiece, fallElasticStiffness, fallElasticPower)); }
public IEnumerator FindAndDoMove() { // while(true) // { Match3BoardPiece boardPiece = null; // Try to find a possible match to move bool foundPossibleMatchLastTime = possibleMatchFinder.FindFirstPossibleMatch(); if (foundPossibleMatchLastTime && !useOnlyRandomMoves) { boardPiece = possibleMatchFinder.lastFoundIsolatedTile.BoardPiece as Match3BoardPiece; } else if (!useOnlyPossibleMoves) { foundPossibleMatchLastTime = false; // Choose a random board piece to move from because no possible match found last time boardPiece = validBoardPieces[Random.Range(0, validBoardPieces.Count)]; } if (boardPiece != null && boardPiece.Tile != null && boardPiece.Tile.IsUserMoveable) { // Try to move using the last found possible match first if (foundPossibleMatchLastTime) { if (!TryPossibleMatchMove()) { // Debug.LogWarning("AI failed possible match move..."); } yield break; } else if (!useOnlyPossibleMoves && TryRandomMoveAround(boardPiece)) { // Found a random valid move (not necessary a matching move). yield break; } } yield return(null); // } }
public Match3BoardPiece SpawnBoardPiece(int rowIdx, int colIdx, System.Type pieceType, bool autoDestroyOldRef = true) { Match3BoardPiece boardPiece = (Instantiate(piecesDictionary[pieceType].gameObject) as GameObject).GetComponent <Match3BoardPiece>(); boardPiece.cachedTransform.position = Vector3.zero; boardPiece.name = string.Format("[{0},{1}] {2}", rowIdx, colIdx, boardPiece.name); boardPiece.InitComponent(this); Match3BoardPiece oldBoardPiece = Board[rowIdx, colIdx] as Match3BoardPiece; // If there is already a board piece GameObject instantiated in this slot, destroy it first. if (oldBoardPiece != null && autoDestroyOldRef) { Destroy(oldBoardPiece.gameObject); } Board[rowIdx, colIdx] = boardPiece; return(boardPiece); }
protected bool FindPossibleMatchLocation() { // Pick random tiles on the board and look up where there is a place to generate the possible match. while (normalTiles.Count > 0) { int randomIdx = Random.Range(0, normalTiles.Count); //TODO FLORIN - BUGGED! check all the board tiles that are user moveable not only normal tiles Match3BoardPiece piece = normalTiles[randomIdx].BoardPiece as Match3BoardPiece; if (LookupPossibleNeighborSlotsFor(piece)) { return(true); } else { normalTiles.RemoveAt(randomIdx); } } return(false); }
/// <summary> /// Raises the trigger enter Unity event. /// </summary> /// <param name='other'> /// The collider that entered this trigger. /// </param> void OnTriggerEnter(Collider other) { if (!enabled) //|| other.gameObject.layer != Match3Globals.Instance.layerBoardTile { return; } tileComponent = other.GetComponent<NormalTile>(); if (OnTileEntered != null && tileComponent != null) { OnTileEntered(tileComponent); return; } boardPieceComponent = other.GetComponent<Match3BoardPiece>(); if (OnBoardPieceEntered != null && boardPieceComponent != null) { OnBoardPieceEntered(boardPieceComponent); } }
public void AttachTileToBoardAt(Match3BoardPiece targetBoardPiece, Match3Tile tile, bool offBoardTile, bool isBoardSetup = false, bool resetTilePosition = true) { BoardCoord boardPos = targetBoardPiece.BoardPosition; AttachTileToBoardAt(boardPos.row, boardPos.col, tile, offBoardTile, isBoardSetup, resetTilePosition); }
protected virtual void TileStoppedMoving(ref Match3BoardPiece startingPiece) { }
protected bool LookupPossibleNeighborSlotsFor(Match3BoardPiece piece) { int numNeighborDirections = (int)Match3BoardPiece.LinkType.Count; possibleMatchSlots.Clear(); for(int i = 0; i < numNeighborDirections; i += 2) { // Count max 2 neighbors in each direction Match3BoardPiece neighborIterator = piece; for(int j = 0; j < 2; j++) { neighborIterator = neighborIterator.GetNeighbor( (Match3BoardPiece.LinkType)i ); if (neighborIterator != null && neighborIterator.Tile != null && neighborIterator.Tile.GetType() == typeof(NormalTile) && (!isBoardSetup || !(neighborIterator.Tile as NormalTile).IsTileIgnoredByAntiMatchSystems)) { possibleMatchSlots.Add(neighborIterator); if (possibleMatchSlots.Count == 3) { return true; } } else { break; } } } return false; }
public bool UpdateTilePhysics(Match3BoardPiece curPiece) { // Update tile physics (apply gravity). // if (!waitingForOtherTile) { UpdateFallingTilePosition(curPiece); bool hasTileReachedFallDestination = HasTileReachedFallDestination(ref fallDestination); if ( !hasTileReachedFallDestination ) { // Update and limit tile maximum speed. moveVel = Mathf.Min(moveVel + accel * Time.smoothDeltaTime, maxVel); } else { LocalPosition = fallDestination; } return hasTileReachedFallDestination; }
public void GetValidTargetNeighborTilesFor(Match3BoardPiece piece) { possibleTargetTiles.Clear(); for(int i = 0; i < (int)Match3BoardPiece.LinkType.Count; i += 2) { Match3BoardPiece neighbor = piece.GetNeighbor( (Match3BoardPiece.LinkType)i ); if (neighbor != null && neighbor.Tile != null && neighbor.Tile.IsUserMoveable) { possibleTargetTiles.Add(neighbor.Tile as Match3Tile); } } }
public void SetNeighbor(LinkType neighborType, Match3BoardPiece newNeighbor) { neighbors[(int)neighborType] = newNeighbor; }
private void RegisterNeighborBoardPieces(bool subscribe) { Match3BoardPiece match3BoardPiece = BoardPiece as Match3BoardPiece; for(int i = 0; i < match3BoardPiece.neighbors.Length; i+=2) { boardPieceIterator = match3BoardPiece.neighbors[i]; if(boardPieceIterator == null) { continue; } if(subscribe) { freezerNeighbors.Add(boardPieceIterator); boardPieceIterator.OnTileDestroyed += OnNeighborDestroy; } else { boardPieceIterator.OnTileDestroyed -= OnNeighborDestroy; } } }
protected void LookupMatchingColors(Match3BoardPiece startPiece, LookupDirection lookupDir) { int lookupOffset = (int)lookupDir; int numPatterns = baseLookupPattern.GetLength(0); for(int i = 0; i < numPatterns; i++) { Match3BoardPiece.LinkType lookupDirA = (Match3BoardPiece.LinkType)( (int)baseLookupPattern[i, 0] + lookupOffset ); Match3BoardPiece.LinkType lookupDirB = (Match3BoardPiece.LinkType)( (int)baseLookupPattern[i, 1] + lookupOffset ); ignoreCount = AddToIgnoreList( GetMatchingColorBetweenDirections(startPiece, lookupDirA, lookupDirB) ); } }
public override void RaiseEventTileFinishedActiveGravity (Match3BoardPiece startingBoardPiece) { base.RaiseEventTileFinishedActiveGravity(startingBoardPiece); IsMoving = false; if ( !canBounce ) { return; } // This tile can't bounce again until it passes at least once through passive gravity again. canBounce = false; if ( (startingBoardPiece != BoardPiece) && !fallBounceAnimEnabled ) { StartCoroutine(ApplyTileBounceEffect(fallBounceStiffness, fallBouncePower)); } // StartCoroutine(ApplyTileFallElasticEffect(curPiece, fallElasticStiffness, fallElasticPower)); }
/// <summary> /// Raises the select in hierarchy button pressed event. /// If the CONTROL key is pressed while clicking this button then all the board pieces on the same row will be selected. /// If the ALT key is pressed, all on the same column will be selected. /// /// If the SHIFT key is pressed together with one of the above keys, only the tiles will be selected. /// /// If the SHIFT key is pressed alone it will do a multi-select of the clicked board pieces. /// </summary> /// <param name='boardPiece'> /// Board piece. /// </param> public void OnSelectInHierarchyButtonPressed(Match3BoardPiece boardPiece) { if (Event.current.control) { // Modifier key to select entire row of the selected board piece was pressed. List<GameObject> selectedRow = new List<GameObject>(); for(int i = 0; i < editor.boardNumCols; i++) { // If Alt is also pressed, select tiles only if (Event.current.shift) { Match3Tile tile = editor.boardGrid[boardPiece.editorBoardPos.row, i].EditorTile; if (tile != null) { selectedRow.Add(tile.gameObject); } } else { selectedRow.Add(editor.boardGrid[boardPiece.editorBoardPos.row, i].gameObject); } } Selection.objects = selectedRow.ToArray(); selectedRow.Clear(); } else if (Event.current.alt) { // Select the entire column of the selected board piece. List<GameObject> selectedColumn = new List<GameObject>(); for(int i = 0; i < editor.boardNumRows; i++) { // If Alt is also pressed, select tiles only if (Event.current.shift) { Match3Tile tile = editor.boardGrid[i, boardPiece.editorBoardPos.col].EditorTile; if (tile != null) { selectedColumn.Add(tile.gameObject); } } else { selectedColumn.Add(editor.boardGrid[i, boardPiece.editorBoardPos.col].gameObject); } } Selection.objects = selectedColumn.ToArray(); selectedColumn.Clear(); } else if (Event.current.shift) { Object[] currentSelection = Selection.objects; Object[] newSelection = null; int selectedIndex = System.Array.IndexOf<Object>(currentSelection, boardPiece.gameObject); if (selectedIndex >= 0) { // The currently selected board piece is already present in the current selection group, so we need to remove it. currentSelection[selectedIndex] = null; newSelection = currentSelection; } else { // Add currently clicked board piece to the current selection newSelection = new Object[currentSelection.Length + 1]; System.Array.Copy(currentSelection, newSelection, currentSelection.Length); newSelection[newSelection.Length - 1] = boardPiece.gameObject; } // Update the current selection Selection.objects = newSelection; } else { // Select the current board piece in the hierarchy (if there is one). Selection.activeGameObject = boardPiece.gameObject; EditorGUIUtility.PingObject(Selection.activeGameObject); } }
/// <summary> /// Copies the links from this board piece to a designated target board piece. /// </summary> public void CopyLinksTo(Match3BoardPiece target) { for(int i = 0; i < (int)LinkType.Count; i++) { target.links[i] = links[i]; } }
public int EditorLoadBoardSetupFromHierarchy(Match3BoardPiece[,] gridDestination) { // Iterate through all the child board pieces Match3BoardPiece[] childBoardPieces = GetComponentsInChildren<Match3BoardPiece>(true); for(int i = 0; i < childBoardPieces.Length; i++) { BoardCoord boardPos = BoardCoord.ParseCoordFromString(childBoardPieces[i].name); // Set this board piece in the corresponding Board position gridDestination[boardPos.row, boardPos.col] = childBoardPieces[i]; childBoardPieces[i].editorBoardPos = boardPos; } // Return the number of board pieces found. return childBoardPieces.Length; }
/// <summary> /// Raises the tile finished active gravity event. /// This event should set the "IsMoving" property to false when it finishes any tile bounce animation. /// </summary> public virtual void RaiseEventTileFinishedActiveGravity (Match3BoardPiece startingBoardPiece) { if (OnTileFinishedActiveGravity != null) { OnTileFinishedActiveGravity(this, startingBoardPiece); } }
/// <summary> /// Raises the board piece button pressed event when pressing a level editor button in the Unity scene view. /// </summary> /// <param name='refBoardPiece'> /// Board piece. /// </param> /// <param name='rowIdx'> /// Row index. /// </param> /// <param name='colIdx'> /// Col index. /// </param> void OnBoardPieceButtonPressed(ref Match3BoardPiece refBoardPiece, BoardCoord boardPos) { // Validate the current board tool selection (the currently selected prefab) // editor.selectedBoardTool = Selection.activeGameObject; object selectedToolObj = null; if (editor.selectedBoardTool != null) { if (editor.selectedBoardTool.GetComponent<Match3BoardPiece>()) { selectedToolObj = editor.selectedBoardTool.GetComponent<Match3BoardPiece>(); } if (editor.selectedBoardTool.GetComponent<Match3Tile>()) { selectedToolObj = editor.selectedBoardTool.GetComponent<Match3Tile>(); } } if ( selectedToolObj is Match3BoardPiece ) { // Get the currently selected board tool type if ( !LevelEditorUtils.IsPrefabInArray(editor.boardRenderer.prefabsPieces, editor.selectedBoardTool) ) { EditorUtility.DisplayDialog("Level Editor", "The selected board prefab is not added to the Match3BoardRenderer pieces prefab list!", "Ok"); return; } // Spawn a new board piece editor.SpawnBoardPieceAt(boardPos, editor.selectedBoardTool); } else if ( selectedToolObj is Match3Tile ) { // Get the currently selected board tool type if ( !LevelEditorUtils.IsPrefabInArray(editor.boardRenderer.tilesPrefabs, editor.selectedBoardTool) ) { EditorUtility.DisplayDialog("Level Editor", "The selected board prefab is not added to the Match3BoardRenderer tiles prefab list!", "Ok"); return; } else if (refBoardPiece == null) { // Spawn a default board piece if none found at the current board position. editor.SpawnBoardPieceAt(boardPos, editor.defaultBoardPiece.gameObject); editor.UpdateBoardPieceGridTransform(refBoardPiece, boardPos); } // Spawn a new tile on the selected board piece. editor.SpawnTileAt(refBoardPiece, boardPos, editor.selectedBoardTool); } else { EditorUtility.DisplayDialog("Level Editor", "The selected board prefab type is not supported!", "Ok"); return; } }
public IEnumerator ApplyTileFallElasticEffect(Match3BoardPiece targetPiece, float fallStiffness, float fallPower) { fallElasticAnimEnabled = true; // Apply offset to current target piece HOTween.To((targetPiece.Tile as Match3Tile).tileModelTransform, fallStiffness, new TweenParms() .Prop("localPosition", Vector3.down * fallPower * 0.75f) .Ease(EaseType.EaseOutSine) ); // Apply offset to bottom neighbor HOTween.To((targetPiece.Bottom.Tile as Match3Tile).tileModelTransform, fallStiffness, new TweenParms() .Prop("localPosition", Vector3.down * fallPower) .Ease(EaseType.EaseOutSine) ); // Wait just one frame before overriding the above tweens to make them pull back in the starting position yield return null; // Apply offset comeback to current target piece if we can still do it. if (targetPiece != null && targetPiece.Tile != null && !targetPiece.Tile.IsMoving) { HOTween.To((targetPiece.Tile as Match3Tile).tileModelTransform, fallStiffness, new TweenParms() .Prop("localPosition", (targetPiece.Tile as Match3Tile).tileModelLocalPos) .Ease(EaseType.EaseOutSine) ); } // Apply offset comeback to bottom neighbor piece if we can still do it. if (targetPiece.Bottom != null && targetPiece.Bottom.Tile != null && !targetPiece.Bottom.Tile.IsMoving) { HOTween.To((targetPiece.Bottom.Tile as Match3Tile).tileModelTransform, fallStiffness, new TweenParms() .Prop("localPosition", (targetPiece.Bottom.Tile as Match3Tile).tileModelLocalPos) .Ease(EaseType.EaseOutSine) ); } fallElasticAnimEnabled = false; }
protected IEnumerator DestroyThisStuffAfterWaiting(Match3BoardPiece boardPiece) { yield return new WaitForSeconds(destroyEffect.destroyTileTime); DestroyThisStuff(boardPiece); }
protected TileColorType[] ComputeIgnoreColorListFromNeighbors(Match3BoardPiece startPiece) { ignoreCount = 0; for(int i = 0; i < colorsToIgnore.Length; i++) { colorsToIgnore[i] = false; } LookupMatchingColors(startPiece, LookupDirection.Vertical); LookupMatchingColors(startPiece, LookupDirection.Horizontal); if (ignoreCount == 0) { return null; } else { // Prepare lookup results. (an array of colors to ignore when picking a new random color for the current tile (on the "startPiece" board piece). TileColorType[] result = new TileColorType[ignoreCount]; int resultIdx = 0; for(int i = 1; i < colorsToIgnore.Length; i++) { if ( colorsToIgnore[i]) { result[resultIdx++] = (TileColorType)i; } } return result; } }
protected void DestroyThisStuff(Match3BoardPiece boardPiece) { LayeredBoardPiece frostPiece = (boardPiece as LayeredBoardPiece); if (frostPiece != null && frostPiece.NumLayers > 0 && frostPiece.Tile == null) { frostPiece.NumLayers--; } else if (boardPiece.Tile != null) { if(frostPiece != null && (frostPiece.Tile is SnowTile || frostPiece.Tile is LockedTile || frostPiece.Tile is FreezerTile)) { frostPiece.NumLayers--; } boardPiece.Tile.Destroy(); } }
protected TileColorType GetMatchingColorBetweenDirections(Match3BoardPiece startPiece, Match3BoardPiece.LinkType dirA, Match3BoardPiece.LinkType dirB) { Match3BoardPiece pieceDirA = startPiece.GetNeighbor(dirA); Match3BoardPiece pieceDirB = null; if (dirA != dirB) { pieceDirB = startPiece.GetNeighbor(dirB); } else if (pieceDirA != null) { pieceDirB = pieceDirA.GetNeighbor(dirA); } if (pieceDirA != null && pieceDirB != null) { Match3Tile tileDirA = pieceDirA.Tile as Match3Tile; Match3Tile tileDirB = pieceDirB.Tile as Match3Tile; if (tileDirA != null && tileDirB != null && tileDirA.CanBeMatched && tileDirB.CanBeMatched && tileDirA.IsMatchWith(tileDirB)) { return tileDirA.TileColor; } } return TileColorType.None; }
/// <summary> /// Find the neighbor pieces of the specified "currentPiece" in the direction "direction" that match between them. /// This method is called by <see cref="ProcessBoardPiece(AbstractBoardPiece boardPiece)"/>. /// </summary> /// <returns> /// The neighbor pieces for. /// </returns> /// <param name='currentPiece'> /// If set to <c>true</c> current piece. /// </param> /// <param name='direction'> /// If set to <c>true</c> direction. /// </param> protected bool FindMatchingNeighborPiecesFor(Match3BoardPiece currentPiece, Match3BoardPiece.LinkType direction) { Match3BoardPiece prevPiece = null; // // Reference to the piece who's neighbors we're about to process. // Match3BoardPiece originPiece = currentPiece; // Look at the next 2 neighbors in the specified "direction". for(int i = 0; i < 2; i++) { currentPiece = currentPiece.GetNeighbor(direction); // If this board piece is invalid or contains an invalid tile, stop the current neighbor lookup for the "currentPiece" // but continue the search with the next board pieces. if (currentPiece == null || currentPiece.Tile == null || currentPiece.Tile.IsDestroying || (currentPiece.Tile as NormalTile).IsTileSwitching || (currentPiece.Tile as NormalTile).IsFrozen() || !(currentPiece.Tile as Match3Tile).CanBeMatched && !(currentPiece.Tile is TriggerTile) || (currentPiece.Tile is TriggerTile) && !currentPiece.Tile.IsUserMoveable) { return true; } Match3Tile currentTile = currentPiece.Tile as Match3Tile; if (prevPiece != null) { Match3Tile prevTile = prevPiece.Tile as Match3Tile; if ( prevTile.IsMatchWith(currentTile) ) { // Add this tile because it matches the previous one. AddNewPossibleMatchTile(currentTile); if ( HasFoundPossibleMatchForColor(currentTile.TileColor) ) { // Stop looking for other possible matches. return false; } } } else { // int lastTriggerTileIdx = triggerTileMatchFound.Count - 1; // if (lastTriggerTileIdx >= 0 && triggerTileMatchFound[lastTriggerTileIdx] is ColorBombTile) { // Debug.LogWarning("[PossibleMatchesFinder] originalPiece = " + originalPiece + "\n -> search direction: " + direction + "\n -> " + " currentTile = " + currentTile); // } // Add this tile to the partial matches buffer because it's the first one AddNewPossibleMatchTile(currentTile); if ( HasFoundPossibleMatchForColor(currentTile.TileColor) ) { // Stop looking for other possible matches. return false; } } prevPiece = currentPiece; } // Can continue to the next board piece. return true; }
public static void OnDrawGizmos(Match3BoardPiece boardPiece, GizmoType gizmoType) { if ( !boardPiece.canDrawGizmos ) { return; } if (showBoardPiecesStates) { string states = ""; states = Match3TileEditor.AppendState(states, string.Format("[{0},{1}], ", boardPiece.BoardPosition.row, boardPiece.BoardPosition.col), maxStatesLength); if (boardPiece.IsBlocked) { states = Match3TileEditor.AppendState(states, "B,", maxStatesLength); } if (boardPiece.IsTemporaryOrphan) { states = Match3TileEditor.AppendState(states, "Ot,", maxStatesLength); } if (boardPiece.IsOrphan) { states = Match3TileEditor.AppendState(states, "O,", maxStatesLength); } if (boardPiece.IsEmpty) { states = Match3TileEditor.AppendState(states, "E,", maxStatesLength); } else if (boardPiece.IsEmpty && boardPiece.AllowTileFalling) { states = Match3TileEditor.AppendState(states, "EF, ", maxStatesLength); } if (boardPiece.IsBorderPiece) { states = Match3TileEditor.AppendState(states, "Br,", maxStatesLength); } if (boardPiece.LockCount > 0) { states = Match3TileEditor.AppendState(states, "L" + boardPiece.LockCount + ",", maxStatesLength); } if (boardPiece.IsTileSpawner) { states = Match3TileEditor.AppendState(states, "T,", maxStatesLength); } states = states.Trim(); if (labelStyle == null) { labelStyle = new GUIStyle(); labelStyle.normal.textColor = Color.yellow; labelStyle.fontSize = 14; labelStyle.normal.background = Match3TileEditor.MakeTex(2, 2, Color.blue); } Handles.Label(boardPiece.transform.position + new Vector3(-0.5f, 0.5f, 0f), states, labelStyle); } if (showBoardLinks) { if (boardPiece != null && boardPiece.links != null) { Gizmos.color = Color.green; Matrix4x4 pushedMatrix = Gizmos.matrix; if (boardPiece.transform.parent) { Gizmos.matrix = boardPiece.transform.parent.localToWorldMatrix; } for(int i = 0; i < boardPiece.links.Length; i++) { if (boardPiece.links[i] != null) { Gizmos.DrawLine(boardPiece.LocalPosition, boardPiece.links[i].LocalPosition); } } Gizmos.matrix = pushedMatrix; } } }
public void SetLink(LinkType linkType, Match3BoardPiece newLink) { links[(int)linkType] = newLink; }
public bool TryRandomMoveAround(Match3BoardPiece piece) { // Get all valid neighbor tiles for the current starting board piece position GetValidTargetNeighborTilesFor(piece); if ( possibleTargetTiles.Count > 0 && TileSwitchInput.Instance.IsEnabled && gameLogic.TryToMoveTile(piece.Tile, possibleTargetTiles[Random.Range(0, possibleTargetTiles.Count)]) ) { return true; } return false; }
void OnBoardPieceEnteredFreezeTrigger(Match3BoardPiece boardPiece) { if(boardPiece is LayeredBoardPiece) { layeredBoardPiecesToDestroy.Add(boardPiece); } }
protected bool CanReplicateOverBoardPiece(Match3BoardPiece targetBoardPiece) { Match3Tile tile = targetBoardPiece.Tile as Match3Tile; if (targetBoardPiece is EmptyBoardPiece) { return false; } if (tile != null && ( !tile.IsDestructible || tile.IsDestroying || tile.IsMoving || tile.IsTileSwitching || tile.IsMatched || (tile as NormalTile).IsFrozen()) ) { return false; } return true; }