diff --git a/lib/game/board.dart b/lib/game/board.dart index a2bb60e..2237926 100644 --- a/lib/game/board.dart +++ b/lib/game/board.dart @@ -18,6 +18,7 @@ class Board extends FlameGame { int? selectedCol; bool animating = false; Tile? lastMovedTile; + Tile? lastMovedByGravity; Board({required this.sprites, required this.swapNotifier}); @@ -54,7 +55,7 @@ class Board extends FlameGame { position: Vector2(col * tileSize, row * tileSize), row: row, col: col, - onTileTap: handleTileTap, + // onTileTap: handleTileTap, onSwipe: handleTileSwipe, ); rowTiles.add(tile); @@ -85,37 +86,37 @@ class Board extends FlameGame { } while (hasMatches); } - void handleTileTap(Tile tappedTile) { - if (animating) return; + // void handleTileTap(Tile tappedTile) { + // if (animating) return; - int row = tappedTile.row; - int col = tappedTile.col; + // int row = tappedTile.row; + // int col = tappedTile.col; - if (selectedRow == null || selectedCol == null) { - tappedTile.select(); - selectedRow = row; - selectedCol = col; - } else { - tiles[selectedRow!][selectedCol!]?.deselect(); - if (_isAdjacent(selectedRow!, selectedCol!, row, col)) { - lastMovedTile = tiles[selectedRow!][selectedCol!]; - swapTiles(tiles[selectedRow!][selectedCol!]!, tiles[row][col]!, true); - Future.delayed(const Duration(milliseconds: 300), () { - if (!checkMatches()) { - swapTiles( - tiles[row][col]!, tiles[selectedRow!][selectedCol!]!, true); - } - selectedRow = null; - selectedCol = null; - }); - } else { - tiles[selectedRow!][selectedCol!]?.deselect(); - tappedTile.select(); - selectedRow = row; - selectedCol = col; - } - } - } + // if (selectedRow == null || selectedCol == null) { + // tappedTile.select(); + // selectedRow = row; + // selectedCol = col; + // } else { + // tiles[selectedRow!][selectedCol!]?.deselect(); + // if (_isAdjacent(selectedRow!, selectedCol!, row, col)) { + // lastMovedTile = tiles[selectedRow!][selectedCol!]; + // swapTiles(tiles[selectedRow!][selectedCol!]!, tiles[row][col]!, true); + // Future.delayed(const Duration(milliseconds: 300), () { + // if (!checkMatches()) { + // swapTiles( + // tiles[row][col]!, tiles[selectedRow!][selectedCol!]!, true); + // } + // selectedRow = null; + // selectedCol = null; + // }); + // } else { + // tiles[selectedRow!][selectedCol!]?.deselect(); + // tappedTile.select(); + // selectedRow = row; + // selectedCol = col; + // } + // } + // } Future handleTileSwipe(Tile tile, Vector2 delta) async { if (animating) return; @@ -148,7 +149,8 @@ class Board extends FlameGame { if (!checkMatches()) { swapTiles(tile, targetTile, true); } - + selectedRow = null; + selectedCol = null; animating = false; } } @@ -159,8 +161,8 @@ class Board extends FlameGame { } void swapTiles(Tile tile1, Tile tile2, bool animate) { - final tempPosition1 = tile1.position.clone(); - final tempPosition2 = tile2.position.clone(); + // final tempPosition1 = tile1.position.clone(); + // final tempPosition2 = tile2.position.clone(); final tempRow1 = tile1.row; final tempCol1 = tile1.col; final tempRow2 = tile2.row; @@ -175,9 +177,13 @@ class Board extends FlameGame { tiles[tile2.row][tile2.col] = tile2; if (animate) { + final tempPosition1 = tile1.position.clone(); + final tempPosition2 = tile2.position.clone(); tile1.animateMoveTo(tempPosition2, () {}); tile2.animateMoveTo(tempPosition1, () {}); } + tile1.deselect(); + tile1.deselect(); } bool checkMatches() { @@ -233,11 +239,90 @@ class Board extends FlameGame { return count >= 3; } + // int _removeMatchedElements(int row, int col) { + // int score = 0; + // final int? value = tiles[row][col]?.spriteIndex; + // bool bombTriggered = false; + // Tile? tileToTransformIntoBomb = null; + + // int left = col; + // while (left > 0 && tiles[row][left - 1]?.spriteIndex == value) left--; + // int right = col; + // while (right < cols - 1 && tiles[row][right + 1]?.spriteIndex == value) + // right++; + + // if (right - left + 1 >= 3) { + // score += _calculateScore(right - left + 1); + + // if (right - left + 1 >= 4 && + // lastMovedTile != null && + // lastMovedTile!.row == row && + // lastMovedTile!.col >= left && + // lastMovedTile!.col <= right) { + // tileToTransformIntoBomb = lastMovedTile; + // } + + // for (int i = left; i <= right; i++) { + // if (tiles[row][i] != null) { + // if (tiles[row][i]!.isBomb) { + // bombTriggered = true; + // _triggerBomb(row, i); + // } + // if (tiles[row][i] != tileToTransformIntoBomb) { + // _animateRemoveTile(tiles[row][i]!); + // tiles[row][i] = null; + // } + // } + // } + // } + + // int top = row; + // while (top > 0 && tiles[top - 1][col]?.spriteIndex == value) top--; + // int bottom = row; + // while (bottom < rows - 1 && tiles[bottom + 1][col]?.spriteIndex == value) + // bottom++; + + // if (bottom - top + 1 >= 3) { + // score += _calculateScore(bottom - top + 1); + + // if (bottom - top + 1 >= 4 && + // lastMovedTile != null && + // lastMovedTile!.col == col && + // lastMovedTile!.row >= top && + // lastMovedTile!.row <= bottom) { + // tileToTransformIntoBomb = lastMovedTile; + // } + + // for (int i = top; i <= bottom; i++) { + // if (tiles[i][col] != null) { + // if (tiles[i][col]!.isBomb) { + // bombTriggered = true; + // _triggerBomb(i, col); + // } + // if (tiles[i][col] != tileToTransformIntoBomb) { + // _animateRemoveTile(tiles[i][col]!); + // tiles[i][col] = null; + // } + // } + // } + // } + + // if (bombTriggered) { + // _triggerBomb(row, col); + // } + + // if (tileToTransformIntoBomb != null) { + // _createBomb(tileToTransformIntoBomb.row, tileToTransformIntoBomb.col); + // } + + // return score; + // } + int _removeMatchedElements(int row, int col) { int score = 0; final int? value = tiles[row][col]?.spriteIndex; bool bombTriggered = false; - Tile? tileToTransformIntoBomb = lastMovedTile; + Tile? tileToTransformIntoBomb = null; int left = col; while (left > 0 && tiles[row][left - 1]?.spriteIndex == value) left--; @@ -249,7 +334,7 @@ class Board extends FlameGame { score += _calculateScore(right - left + 1); if (right - left + 1 >= 4) { - tileToTransformIntoBomb = tiles[row][col]; + tileToTransformIntoBomb = lastMovedTile ?? lastMovedByGravity; } for (int i = left; i <= right; i++) { @@ -276,7 +361,7 @@ class Board extends FlameGame { score += _calculateScore(bottom - top + 1); if (bottom - top + 1 >= 4) { - tileToTransformIntoBomb = tiles[row][col]; + tileToTransformIntoBomb = lastMovedTile ?? lastMovedByGravity; } for (int i = top; i <= bottom; i++) { @@ -426,45 +511,87 @@ class Board extends FlameGame { ); } + // void explodeBomb(Tile bombTile) { + // final bombPosition = bombTile.position; + // final bombRow = bombTile.row; + // final bombCol = bombTile.col; + + // for (int rowOffset = -1; rowOffset <= 1; rowOffset++) { + // for (int colOffset = -1; colOffset <= 1; colOffset++) { + // final row = bombRow + rowOffset; + // final col = bombCol + colOffset; + + // if (row >= 0 && row < rows && col >= 0 && col < cols) { + // final tile = tiles[row][col]; + // if (tile != null && tile != bombTile) { + // _animateRemoveTile(tile); + // tiles[row][col] = null; + // } + // } + // } + // } + + // bombTile.add(RemoveEffect( + // delay: 0.5, + // onComplete: () => remove(bombTile), + // )); + + // final explosion = CircleComponent( + // radius: tileSize / 2, + // paint: Paint()..color = Colors.orange.withOpacity(0.7), + // position: bombPosition, + // ); + // add(explosion); + + // explosion.add(ScaleEffect.to( + // Vector2.all(2), + // EffectController(duration: 0.5), + // onComplete: () => explosion.removeFromParent(), + // )); + // } + void explodeBomb(Tile bombTile) { - final bombPosition = bombTile.position; + final bombPosition = bombTile.position.clone(); final bombRow = bombTile.row; final bombCol = bombTile.col; - for (int rowOffset = -1; rowOffset <= 1; rowOffset++) { - for (int colOffset = -1; colOffset <= 1; colOffset++) { - final row = bombRow + rowOffset; - final col = bombCol + colOffset; - - if (row >= 0 && row < rows && col >= 0 && col < cols) { - final tile = tiles[row][col]; - if (tile != null && tile != bombTile) { - _animateRemoveTile(tile); - tiles[row][col] = null; + for (int i = max(0, bombRow - 1); i <= min(rows - 1, bombRow + 1); i++) { + for (int j = max(0, bombCol - 1); j <= min(cols - 1, bombCol + 1); j++) { + if (tiles[i][j] != null) { + if (tiles[i][j]!.isBomb && (i != bombRow || j != bombCol)) { + _triggerBomb(i, j); + } else { + _animateRemoveTile(tiles[i][j]!); + tiles[i][j] = null; } } } } - bombTile.add(RemoveEffect( - delay: 0.5, - onComplete: () => remove(bombTile), - )); - - final explosion = CircleComponent( - radius: tileSize / 2, - paint: Paint()..color = Colors.orange.withOpacity(0.7), - position: bombPosition, - ); - add(explosion); - - explosion.add(ScaleEffect.to( - Vector2.all(2), - EffectController(duration: 0.5), - onComplete: () => explosion.removeFromParent(), - )); + // Анимация взрыва бомбы + _animateBombExplosion(bombPosition); + tiles[bombRow][bombCol] = null; } + // void _applyGravity() { + // for (int col = 0; col < cols; col++) { + // for (int row = rows - 1; row >= 0; row--) { + // if (tiles[row][col] == null) { + // for (int k = row - 1; k >= 0; k--) { + // if (tiles[k][col] != null) { + // tiles[row][col] = tiles[k][col]!; + // tiles[k][col] = null; + // tiles[row][col]!.row = row; + // tiles[row][col]!.animateMoveTo( + // Vector2(col * tileSize, row * tileSize), () {}); + // break; + // } + // } + // } + // } + // } + // } + void _applyGravity() { for (int col = 0; col < cols; col++) { for (int row = rows - 1; row >= 0; row--) { @@ -476,6 +603,7 @@ class Board extends FlameGame { tiles[row][col]!.row = row; tiles[row][col]!.animateMoveTo( Vector2(col * tileSize, row * tileSize), () {}); + lastMovedByGravity = tiles[row][col]; break; } } @@ -496,7 +624,7 @@ class Board extends FlameGame { position: Vector2(col * tileSize, -tileSize), row: row, col: col, - onTileTap: handleTileTap, + // onTileTap: handleTileTap, onSwipe: handleTileSwipe, ); tiles[row][col] = tile; diff --git a/lib/game/match_magic_game.dart b/lib/game/match_magic_game.dart index 6b531f7..bc626a3 100644 --- a/lib/game/match_magic_game.dart +++ b/lib/game/match_magic_game.dart @@ -47,9 +47,7 @@ class _MatchMagicGameScreenState extends State { sprites: sprites, swapNotifier: context.read()); return Column( children: [ - SizedBox( - height: 50, - ), + const SizedBox(height: 50), const ScoreDisplay(), Expanded( child: Center( @@ -59,16 +57,27 @@ class _MatchMagicGameScreenState extends State { ), ), ), - ElevatedButton( - onPressed: _restartGame, - child: const Text( - 'Restart', - style: TextStyle(color: Colors.black), - ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: _restartGame, + child: const Text( + 'Restart', + style: TextStyle(color: Colors.black), + ), + ), + const SizedBox(width: 20), + ElevatedButton( + onPressed: () {}, + child: const Text( + 'Hint', + style: TextStyle(color: Colors.black), + ), + ), + ], ), - SizedBox( - height: 50, - ) + const SizedBox(height: 50), ], ); } diff --git a/lib/game/tile.dart b/lib/game/tile.dart index 5634237..4a1bf81 100644 --- a/lib/game/tile.dart +++ b/lib/game/tile.dart @@ -8,13 +8,15 @@ class Tile extends SpriteComponent with TapCallbacks, DragCallbacks { int row; int col; int spriteIndex; - final void Function(Tile) onTileTap; + // final void Function(Tile) onTileTap; final void Function(Tile, Vector2) onSwipe; bool isSelected = false; bool isBomb = false; bool isMagicCube = false; Vector2? startDragPosition; + bool isAnimating = false; + Tile({ required Sprite sprite, required this.spriteIndex, @@ -22,31 +24,34 @@ class Tile extends SpriteComponent with TapCallbacks, DragCallbacks { required Vector2 position, required this.row, required this.col, - required this.onTileTap, + // required this.onTileTap, required this.onSwipe, }) : super(sprite: sprite, size: size, position: position); - @override - bool onTapDown(TapDownEvent event) { - if (parent is Board && (parent as Board).animating) { - return false; - } - onTileTap(this); - return true; - } + // @override + // bool onTapDown(TapDownEvent event) { + // if (isAnimating || (parent is Board && (parent as Board).animating)) { + // return false; + // } + // onTileTap(this); + // return true; + // } @override bool onDragStart(DragStartEvent event) { - super.onDragStart(event); - if (parent is Board && (parent as Board).animating) { + if (isAnimating || (parent as Board).animating) { return false; } + super.onDragStart(event); startDragPosition = event.localPosition; return true; } @override bool onDragEnd(DragEndEvent event) { + if (isAnimating || (parent as Board).animating) { + return false; + } super.onDragEnd(event); if (startDragPosition != null) { final delta = event.velocity; @@ -81,17 +86,27 @@ class Tile extends SpriteComponent with TapCallbacks, DragCallbacks { } void animateMoveTo(Vector2 newPosition, VoidCallback onComplete) { + isAnimating = true; + print('animation start'); add(MoveEffect.to( newPosition, EffectController(duration: 0.3), - onComplete: onComplete, + onComplete: () { + print('animation complete'); + isAnimating = false; + onComplete(); + }, )); } - void animateRemove(VoidCallback onComplete) { - add(RemoveEffect( - delay: 0.5, - onComplete: onComplete, - )); - } + // void animateRemove(VoidCallback onComplete) { + // isAnimating = true; + // add(RemoveEffect( + // delay: 0.5, + // onComplete: () { + // isAnimating = false; + // onComplete(); + // }, + // )); + // } }