Added element animation and swipe movement.

This commit is contained in:
Alex Vasilev 2024-08-08 23:50:55 +03:00
parent 5d08e84407
commit a440fd1545
3 changed files with 82 additions and 21 deletions

View File

@ -39,6 +39,7 @@ class Board extends FlameGame {
row: row, row: row,
col: col, col: col,
onTileTap: handleTileTap, onTileTap: handleTileTap,
onSwipe: handleTileSwipe,
); );
rowTiles.add(tile); rowTiles.add(tile);
add(tile); add(tile);
@ -83,7 +84,7 @@ class Board extends FlameGame {
if (_isAdjacent(selectedRow!, selectedCol!, row, col)) { if (_isAdjacent(selectedRow!, selectedCol!, row, col)) {
swapTiles(tiles[selectedRow!]![selectedCol!]!, tiles[row]![col]!, true); swapTiles(tiles[selectedRow!]![selectedCol!]!, tiles[row]![col]!, true);
Future.delayed(const Duration(milliseconds: 300), () { Future.delayed(const Duration(milliseconds: 300), () {
if (!_checkMatches()) { if (!checkMatches()) {
swapTiles( swapTiles(
tiles[row]![col]!, tiles[selectedRow!]![selectedCol!]!, true); tiles[row]![col]!, tiles[selectedRow!]![selectedCol!]!, true);
} }
@ -99,36 +100,71 @@ class Board extends FlameGame {
} }
} }
Future<void> handleTileSwipe(Tile tile, Vector2 delta) async {
if (animating) return; // Блокируем свайп во время анимации
int row = tile.row;
int col = tile.col;
Tile? targetTile;
if (delta.x.abs() > delta.y.abs()) {
if (delta.x > 0 && col < cols - 1) {
targetTile = tiles[row][col + 1];
} else if (delta.x < 0 && col > 0) {
targetTile = tiles[row][col - 1];
}
} else {
if (delta.y > 0 && row < rows - 1) {
targetTile = tiles[row + 1][col];
} else if (delta.y < 0 && row > 0) {
targetTile = tiles[row - 1][col];
}
}
if (targetTile != null) {
animating = true; // Устанавливаем флаг анимации
swapTiles(tile, targetTile, true);
await Future.delayed(const Duration(milliseconds: 300));
if (!checkMatches()) {
swapTiles(tile, targetTile!, true);
}
animating = false; // Сбрасываем флаг анимации
}
}
bool _isAdjacent(int row1, int col1, int row2, int col2) { bool _isAdjacent(int row1, int col1, int row2, int col2) {
return (row1 == row2 && (col1 - col2).abs() == 1) || return (row1 == row2 && (col1 - col2).abs() == 1) ||
(col1 == col2 && (row1 - row2).abs() == 1); (col1 == col2 && (row1 - row2).abs() == 1);
} }
void swapTiles(Tile tile1, Tile tile2, bool animate) { void swapTiles(Tile tile1, Tile tile2, bool animate) {
final tempPosition = tile1.position; final tempPosition1 = tile1.position.clone();
final tempRow = tile1.row; final tempPosition2 = tile2.position.clone();
final tempCol = tile1.col; final tempRow1 = tile1.row;
final tempCol1 = tile1.col;
final tempRow2 = tile2.row;
final tempCol2 = tile2.col;
tile1.position = tile2.position; tile1.row = tempRow2;
tile1.row = tile2.row; tile1.col = tempCol2;
tile1.col = tile2.col; tile2.row = tempRow1;
tile2.col = tempCol1;
tile2.position = tempPosition;
tile2.row = tempRow;
tile2.col = tempCol;
tiles[tile1.row][tile1.col] = tile1; tiles[tile1.row][tile1.col] = tile1;
tiles[tile2.row][tile2.col] = tile2; tiles[tile2.row][tile2.col] = tile2;
if (animate) { if (animate) {
tile1.animateMoveTo(tile1.position, () {}); tile1.animateMoveTo(tempPosition2, () {});
tile2.animateMoveTo(tile2.position, () {}); tile2.animateMoveTo(tempPosition1, () {});
} }
} }
bool _checkMatches() { bool checkMatches() {
if (animating) return false; if (animating) return false; // Не проверяем совпадения, пока идет анимация
animating = true; animating = true; // Устанавливаем флаг анимации
final matches = <List<int>>[]; final matches = <List<int>>[];
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
@ -148,14 +184,14 @@ class Board extends FlameGame {
Future.delayed(const Duration(milliseconds: 300), () { Future.delayed(const Duration(milliseconds: 300), () {
_fillEmptySpaces(); _fillEmptySpaces();
Future.delayed(const Duration(milliseconds: 300), () { Future.delayed(const Duration(milliseconds: 300), () {
animating = false; animating = false; // Сбрасываем флаг анимации после всех анимаций
_checkMatches(); checkMatches();
}); });
}); });
}); });
return true; return true;
} }
animating = false; animating = false; // Сбрасываем флаг анимации, если нет совпадений
return false; return false;
} }
@ -247,6 +283,7 @@ class Board extends FlameGame {
row: row, row: row,
col: col, col: col,
onTileTap: handleTileTap, onTileTap: handleTileTap,
onSwipe: handleTileSwipe, // Добавлен обработчик свайпов
); );
tiles[row][col] = tile; tiles[row][col] = tile;
add(tile); add(tile);

View File

@ -12,7 +12,12 @@ class SwapNotifier extends ChangeNotifier {
} else { } else {
if (_isNeighbor(selectedTile!, tile)) { if (_isNeighbor(selectedTile!, tile)) {
board.swapTiles(selectedTile!, tile, true); board.swapTiles(selectedTile!, tile, true);
selectedTile = null; Future.delayed(const Duration(milliseconds: 300), () {
if (!board.checkMatches()) {
board.swapTiles(tile, selectedTile!, true);
}
selectedTile = null;
});
} else { } else {
selectedTile?.deselect(); selectedTile?.deselect();
selectedTile = tile; selectedTile = tile;

View File

@ -3,12 +3,14 @@ import 'package:flame/effects.dart';
import 'package:flame/events.dart'; import 'package:flame/events.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Tile extends SpriteComponent with TapCallbacks { class Tile extends SpriteComponent with TapCallbacks, DragCallbacks {
int row; int row;
int col; int col;
int spriteIndex; int spriteIndex;
final void Function(Tile) onTileTap; final void Function(Tile) onTileTap;
final void Function(Tile, Vector2) onSwipe;
bool isSelected = false; bool isSelected = false;
Vector2? startDragPosition;
Tile({ Tile({
required Sprite sprite, required Sprite sprite,
@ -18,6 +20,7 @@ class Tile extends SpriteComponent with TapCallbacks {
required this.row, required this.row,
required this.col, required this.col,
required this.onTileTap, required this.onTileTap,
required this.onSwipe,
}) : super(sprite: sprite, size: size, position: position); }) : super(sprite: sprite, size: size, position: position);
@override @override
@ -26,6 +29,22 @@ class Tile extends SpriteComponent with TapCallbacks {
return true; return true;
} }
@override
bool onDragStart(DragStartEvent event) {
startDragPosition = event.localPosition;
return true;
}
@override
bool onDragEnd(DragEndEvent event) {
if (startDragPosition != null) {
final delta = event.velocity;
onSwipe(this, delta);
}
startDragPosition = null;
return true;
}
void select() { void select() {
isSelected = true; isSelected = true;
updateBorder(); updateBorder();