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

View File

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

View File

@ -3,12 +3,14 @@ import 'package:flame/effects.dart';
import 'package:flame/events.dart';
import 'package:flutter/material.dart';
class Tile extends SpriteComponent with TapCallbacks {
class Tile extends SpriteComponent with TapCallbacks, DragCallbacks {
int row;
int col;
int spriteIndex;
final void Function(Tile) onTileTap;
final void Function(Tile, Vector2) onSwipe;
bool isSelected = false;
Vector2? startDragPosition;
Tile({
required Sprite sprite,
@ -18,6 +20,7 @@ class Tile extends SpriteComponent with TapCallbacks {
required this.row,
required this.col,
required this.onTileTap,
required this.onSwipe,
}) : super(sprite: sprite, size: size, position: position);
@override
@ -26,6 +29,22 @@ class Tile extends SpriteComponent with TapCallbacks {
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() {
isSelected = true;
updateBorder();