Changed the behaviour of elements on the field.
This commit is contained in:
parent
2c5aec71cb
commit
5d08e84407
@ -1,9 +1,8 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flame/effects.dart';
|
||||||
import 'package:flame/game.dart';
|
import 'package:flame/game.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'tile.dart';
|
import 'tile.dart';
|
||||||
import 'swap_notifier.dart';
|
|
||||||
import 'package:flame/sprite.dart';
|
import 'package:flame/sprite.dart';
|
||||||
|
|
||||||
class Board extends FlameGame {
|
class Board extends FlameGame {
|
||||||
@ -14,6 +13,7 @@ class Board extends FlameGame {
|
|||||||
List<List<Tile?>> tiles = [];
|
List<List<Tile?>> tiles = [];
|
||||||
int? selectedRow;
|
int? selectedRow;
|
||||||
int? selectedCol;
|
int? selectedCol;
|
||||||
|
bool animating = false;
|
||||||
|
|
||||||
Board({required this.sprites});
|
Board({required this.sprites});
|
||||||
|
|
||||||
@ -69,23 +69,30 @@ class Board extends FlameGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleTileTap(Tile tappedTile) {
|
void handleTileTap(Tile tappedTile) {
|
||||||
|
if (animating) return;
|
||||||
|
|
||||||
int row = tappedTile.row;
|
int row = tappedTile.row;
|
||||||
int col = tappedTile.col;
|
int col = tappedTile.col;
|
||||||
|
|
||||||
if (selectedRow == null || selectedCol == null) {
|
if (selectedRow == null || selectedCol == null) {
|
||||||
|
tappedTile.select();
|
||||||
selectedRow = row;
|
selectedRow = row;
|
||||||
selectedCol = col;
|
selectedCol = col;
|
||||||
} else {
|
} else {
|
||||||
|
tiles[selectedRow!][selectedCol!]?.deselect();
|
||||||
if (_isAdjacent(selectedRow!, selectedCol!, row, col)) {
|
if (_isAdjacent(selectedRow!, selectedCol!, row, col)) {
|
||||||
swapTiles(tiles[selectedRow!][selectedCol!]!, tiles[row][col]!);
|
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(tiles[row][col]!, tiles[selectedRow!][selectedCol!]!);
|
swapTiles(
|
||||||
|
tiles[row]![col]!, tiles[selectedRow!]![selectedCol!]!, true);
|
||||||
}
|
}
|
||||||
selectedRow = null;
|
selectedRow = null;
|
||||||
selectedCol = null;
|
selectedCol = null;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
tiles[selectedRow!][selectedCol!]?.deselect();
|
||||||
|
tappedTile.select();
|
||||||
selectedRow = row;
|
selectedRow = row;
|
||||||
selectedCol = col;
|
selectedCol = col;
|
||||||
}
|
}
|
||||||
@ -97,7 +104,7 @@ class Board extends FlameGame {
|
|||||||
(col1 == col2 && (row1 - row2).abs() == 1);
|
(col1 == col2 && (row1 - row2).abs() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swapTiles(Tile tile1, Tile tile2) {
|
void swapTiles(Tile tile1, Tile tile2, bool animate) {
|
||||||
final tempPosition = tile1.position;
|
final tempPosition = tile1.position;
|
||||||
final tempRow = tile1.row;
|
final tempRow = tile1.row;
|
||||||
final tempCol = tile1.col;
|
final tempCol = tile1.col;
|
||||||
@ -113,13 +120,16 @@ class Board extends FlameGame {
|
|||||||
tiles[tile1.row][tile1.col] = tile1;
|
tiles[tile1.row][tile1.col] = tile1;
|
||||||
tiles[tile2.row][tile2.col] = tile2;
|
tiles[tile2.row][tile2.col] = tile2;
|
||||||
|
|
||||||
tile1.animateMoveTo(tile1.position, () {});
|
if (animate) {
|
||||||
tile2.animateMoveTo(tile2.position, () {});
|
tile1.animateMoveTo(tile1.position, () {});
|
||||||
|
tile2.animateMoveTo(tile2.position, () {});
|
||||||
_checkMatches();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _checkMatches() {
|
bool _checkMatches() {
|
||||||
|
if (animating) return false;
|
||||||
|
animating = true;
|
||||||
|
|
||||||
final matches = <List<int>>[];
|
final matches = <List<int>>[];
|
||||||
for (int row = 0; row < rows; row++) {
|
for (int row = 0; row < rows; row++) {
|
||||||
for (int col = 0; col < cols; col++) {
|
for (int col = 0; col < cols; col++) {
|
||||||
@ -133,71 +143,92 @@ class Board extends FlameGame {
|
|||||||
for (final match in matches) {
|
for (final match in matches) {
|
||||||
_removeMatchedElements(match[0], match[1]);
|
_removeMatchedElements(match[0], match[1]);
|
||||||
}
|
}
|
||||||
_applyGravity();
|
|
||||||
Future.delayed(const Duration(milliseconds: 300), () {
|
Future.delayed(const Duration(milliseconds: 300), () {
|
||||||
_fillEmptySpaces();
|
_applyGravity();
|
||||||
_checkMatches();
|
Future.delayed(const Duration(milliseconds: 300), () {
|
||||||
|
_fillEmptySpaces();
|
||||||
|
Future.delayed(const Duration(milliseconds: 300), () {
|
||||||
|
animating = false;
|
||||||
|
_checkMatches();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
animating = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _hasMatch(int row, int col) {
|
bool _hasMatch(int row, int col) {
|
||||||
final value = tiles[row][col]!.spriteIndex;
|
final value = tiles[row]?[col]?.spriteIndex;
|
||||||
|
|
||||||
int count = 1;
|
int count = 1;
|
||||||
for (int i = col + 1; i < cols && tiles[row][i]!.spriteIndex == value; i++)
|
for (int i = col + 1; i < cols && tiles[row]?[i]?.spriteIndex == value; i++)
|
||||||
count++;
|
count++;
|
||||||
for (int i = col - 1; i >= 0 && tiles[row][i]!.spriteIndex == value; i--)
|
for (int i = col - 1; i >= 0 && tiles[row]?[i]?.spriteIndex == value; i--)
|
||||||
count++;
|
count++;
|
||||||
if (count >= 3) return true;
|
if (count >= 3) return true;
|
||||||
|
|
||||||
count = 1;
|
count = 1;
|
||||||
for (int i = row + 1; i < rows && tiles[i][col]!.spriteIndex == value; i++)
|
for (int i = row + 1; i < rows && tiles[i]?[col]?.spriteIndex == value; i++)
|
||||||
count++;
|
count++;
|
||||||
for (int i = row - 1; i >= 0 && tiles[i][col]!.spriteIndex == value; i--)
|
for (int i = row - 1; i >= 0 && tiles[i]?[col]?.spriteIndex == value; i--)
|
||||||
count++;
|
count++;
|
||||||
return count >= 3;
|
return count >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _removeMatchedElements(int row, int col) {
|
void _removeMatchedElements(int row, int col) {
|
||||||
final value = tiles[row][col]!.spriteIndex;
|
final value = tiles[row]?[col]?.spriteIndex;
|
||||||
|
|
||||||
int left = col;
|
int left = col;
|
||||||
while (left > 0 && tiles[row][left - 1]!.spriteIndex == value) left--;
|
while (left > 0 && tiles[row]?[left - 1]?.spriteIndex == value) left--;
|
||||||
int right = col;
|
int right = col;
|
||||||
while (right < cols - 1 && tiles[row][right + 1]!.spriteIndex == value)
|
while (right < cols - 1 && tiles[row]?[right + 1]?.spriteIndex == value)
|
||||||
right++;
|
right++;
|
||||||
if (right - left + 1 >= 3) {
|
if (right - left + 1 >= 3) {
|
||||||
for (int i = left; i <= right; i++) {
|
for (int i = left; i <= right; i++) {
|
||||||
tiles[row][i] = null;
|
if (tiles[row]?[i] != null) {
|
||||||
|
_animateRemoveTile(tiles[row]![i]!);
|
||||||
|
tiles[row]![i] = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int top = row;
|
int top = row;
|
||||||
while (top > 0 && tiles[top - 1][col]!.spriteIndex == value) top--;
|
while (top > 0 && tiles[top - 1]?[col]?.spriteIndex == value) top--;
|
||||||
int bottom = row;
|
int bottom = row;
|
||||||
while (bottom < rows - 1 && tiles[bottom + 1][col]!.spriteIndex == value)
|
while (bottom < rows - 1 && tiles[bottom + 1]?[col]?.spriteIndex == value)
|
||||||
bottom++;
|
bottom++;
|
||||||
if (bottom - top + 1 >= 3) {
|
if (bottom - top + 1 >= 3) {
|
||||||
for (int i = top; i <= bottom; i++) {
|
for (int i = top; i <= bottom; i++) {
|
||||||
tiles[i][col] = null;
|
if (tiles[i]?[col] != null) {
|
||||||
|
_animateRemoveTile(tiles[i]![col]!);
|
||||||
|
tiles[i]![col] = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _animateRemoveTile(Tile tile) {
|
||||||
|
tile.animateRemove(() {
|
||||||
|
remove(tile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _applyGravity() {
|
void _applyGravity() {
|
||||||
for (int col = 0; col < cols; col++) {
|
for (int col = 0; col < cols; col++) {
|
||||||
int emptyRow = rows - 1;
|
|
||||||
for (int row = rows - 1; row >= 0; row--) {
|
for (int row = rows - 1; row >= 0; row--) {
|
||||||
if (tiles[row][col] != null) {
|
if (tiles[row]?[col] == null) {
|
||||||
if (row != emptyRow) {
|
for (int k = row - 1; k >= 0; k--) {
|
||||||
tiles[emptyRow][col] = tiles[row][col];
|
if (tiles[k]?[col] != null) {
|
||||||
tiles[emptyRow][col]!.row = emptyRow;
|
tiles[row]![col] = tiles[k]![col]!;
|
||||||
tiles[row][col] = null;
|
tiles[k]![col] = null;
|
||||||
|
tiles[row]![col]!.row = row;
|
||||||
|
tiles[row]![col]!.animateMoveTo(
|
||||||
|
Vector2(col * tileSize, row * tileSize), () {});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
emptyRow--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,19 +237,20 @@ class Board extends FlameGame {
|
|||||||
void _fillEmptySpaces() {
|
void _fillEmptySpaces() {
|
||||||
for (int col = 0; col < cols; col++) {
|
for (int col = 0; col < cols; col++) {
|
||||||
for (int row = rows - 1; row >= 0; row--) {
|
for (int row = rows - 1; row >= 0; row--) {
|
||||||
if (tiles[row][col] == null) {
|
if (tiles[row]?[col] == null) {
|
||||||
int spriteIndex = _randomElement();
|
int spriteIndex = _randomElement();
|
||||||
var tile = Tile(
|
var tile = Tile(
|
||||||
sprite: sprites[spriteIndex],
|
sprite: sprites[spriteIndex],
|
||||||
spriteIndex: spriteIndex,
|
spriteIndex: spriteIndex,
|
||||||
size: Vector2.all(tileSize),
|
size: Vector2.all(tileSize),
|
||||||
position: Vector2(col * tileSize, row * tileSize),
|
position: Vector2(col * tileSize, -tileSize),
|
||||||
row: row,
|
row: row,
|
||||||
col: col,
|
col: col,
|
||||||
onTileTap: handleTileTap,
|
onTileTap: handleTileTap,
|
||||||
);
|
);
|
||||||
tiles[row][col] = tile;
|
tiles[row][col] = tile;
|
||||||
add(tile);
|
add(tile);
|
||||||
|
tile.animateMoveTo(Vector2(col * tileSize, row * tileSize), () {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import 'package:flame/components.dart';
|
|||||||
import 'package:flame/game.dart';
|
import 'package:flame/game.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'sprite_loader.dart';
|
|
||||||
import 'board.dart';
|
import 'board.dart';
|
||||||
import 'swap_notifier.dart';
|
import 'swap_notifier.dart';
|
||||||
|
|
||||||
|
@ -8,12 +8,15 @@ class SwapNotifier extends ChangeNotifier {
|
|||||||
void selectTile(Tile tile, Board board) {
|
void selectTile(Tile tile, Board board) {
|
||||||
if (selectedTile == null) {
|
if (selectedTile == null) {
|
||||||
selectedTile = tile;
|
selectedTile = tile;
|
||||||
|
tile.select();
|
||||||
} else {
|
} else {
|
||||||
if (_isNeighbor(selectedTile!, tile)) {
|
if (_isNeighbor(selectedTile!, tile)) {
|
||||||
board.swapTiles(selectedTile!, tile);
|
board.swapTiles(selectedTile!, tile, true);
|
||||||
selectedTile = null;
|
selectedTile = null;
|
||||||
} else {
|
} else {
|
||||||
|
selectedTile?.deselect();
|
||||||
selectedTile = tile;
|
selectedTile = tile;
|
||||||
|
tile.select();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/effects.dart';
|
import 'package:flame/effects.dart';
|
||||||
import 'package:flame/events.dart';
|
import 'package:flame/events.dart';
|
||||||
import 'package:flame/input.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Tile extends SpriteComponent with TapCallbacks {
|
class Tile extends SpriteComponent with TapCallbacks {
|
||||||
@ -9,6 +8,7 @@ class Tile extends SpriteComponent with TapCallbacks {
|
|||||||
int col;
|
int col;
|
||||||
int spriteIndex;
|
int spriteIndex;
|
||||||
final void Function(Tile) onTileTap;
|
final void Function(Tile) onTileTap;
|
||||||
|
bool isSelected = false;
|
||||||
|
|
||||||
Tile({
|
Tile({
|
||||||
required Sprite sprite,
|
required Sprite sprite,
|
||||||
@ -26,10 +26,41 @@ class Tile extends SpriteComponent with TapCallbacks {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void select() {
|
||||||
|
isSelected = true;
|
||||||
|
updateBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
void deselect() {
|
||||||
|
isSelected = false;
|
||||||
|
updateBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBorder() {
|
||||||
|
if (isSelected) {
|
||||||
|
add(RectangleComponent(
|
||||||
|
size: size,
|
||||||
|
paint: Paint()
|
||||||
|
..color = Colors.yellow
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 3,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
children.removeWhere((child) => child is RectangleComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void animateMoveTo(Vector2 newPosition, VoidCallback onComplete) {
|
void animateMoveTo(Vector2 newPosition, VoidCallback onComplete) {
|
||||||
add(MoveEffect.to(
|
add(MoveEffect.to(
|
||||||
newPosition,
|
newPosition,
|
||||||
EffectController(duration: 0.5),
|
EffectController(duration: 0.3),
|
||||||
|
onComplete: onComplete,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void animateRemove(VoidCallback onComplete) {
|
||||||
|
add(RemoveEffect(
|
||||||
|
delay: 0.5,
|
||||||
onComplete: onComplete,
|
onComplete: onComplete,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,12 @@ class MatchMagicGameScreen extends StatelessWidget {
|
|||||||
return const Center(child: Text('No sprites found'));
|
return const Center(child: Text('No sprites found'));
|
||||||
} else {
|
} else {
|
||||||
final sprites = snapshot.data!;
|
final sprites = snapshot.data!;
|
||||||
return MatchMagicGame(sprites: sprites);
|
return Center(
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 1,
|
||||||
|
child: MatchMagicGame(sprites: sprites),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
Loading…
Reference in New Issue
Block a user