From c6b5ed65d97db2ec9c59697a91a9b486b86d566d Mon Sep 17 00:00:00 2001 From: alexvasl Date: Tue, 13 Aug 2024 17:50:11 +0300 Subject: [PATCH] Added score counter. --- lib/game/board.dart | 55 ++++++++++++++++---- lib/game/match_magic_game.dart | 91 ++++++++++++++++++++++++++++++++-- lib/game/swap_notifier.dart | 32 ++++++++---- lib/main.dart | 30 ----------- 4 files changed, 153 insertions(+), 55 deletions(-) diff --git a/lib/game/board.dart b/lib/game/board.dart index 8163a01..e7812e7 100644 --- a/lib/game/board.dart +++ b/lib/game/board.dart @@ -4,9 +4,12 @@ import 'package:flame/effects.dart'; import 'package:flame/game.dart'; import 'tile.dart'; import 'package:flame/sprite.dart'; +import 'package:provider/provider.dart'; +import 'swap_notifier.dart'; class Board extends FlameGame { final List sprites; + final SwapNotifier swapNotifier; static const int rows = 8; static const int cols = 8; late double tileSize; @@ -15,17 +18,29 @@ class Board extends FlameGame { int? selectedCol; bool animating = false; - Board({required this.sprites}); + Board({required this.sprites, required this.swapNotifier}); @override Future onLoad() async { super.onLoad(); + _resetGame(); + } + void _resetGame() { + tiles.clear(); + selectedRow = null; + selectedCol = null; + animating = false; tileSize = size.x / cols; _initializeGrid(); _removeInitialMatches(); } + void restartGame() { + _resetGame(); + swapNotifier.resetScore(); + } + void _initializeGrid() { for (int row = 0; row < rows; row++) { List rowTiles = []; @@ -101,7 +116,7 @@ class Board extends FlameGame { } Future handleTileSwipe(Tile tile, Vector2 delta) async { - if (animating) return; // Блокируем свайп во время анимации + if (animating) return; int row = tile.row; int col = tile.col; @@ -122,7 +137,7 @@ class Board extends FlameGame { } if (targetTile != null) { - animating = true; // Устанавливаем флаг анимации + animating = true; swapTiles(tile, targetTile, true); await Future.delayed(const Duration(milliseconds: 300)); @@ -131,7 +146,7 @@ class Board extends FlameGame { swapTiles(tile, targetTile!, true); } - animating = false; // Сбрасываем флаг анимации + animating = false; } } @@ -163,8 +178,7 @@ class Board extends FlameGame { } bool checkMatches() { - if (animating) return false; // Не проверяем совпадения, пока идет анимация - animating = true; // Устанавливаем флаг анимации + animating = true; final matches = >[]; for (int row = 0; row < rows; row++) { @@ -176,22 +190,25 @@ class Board extends FlameGame { } if (matches.isNotEmpty) { + int points = 0; for (final match in matches) { - _removeMatchedElements(match[0], match[1]); + points += _removeMatchedElements(match[0], match[1]); } Future.delayed(const Duration(milliseconds: 300), () { _applyGravity(); Future.delayed(const Duration(milliseconds: 300), () { _fillEmptySpaces(); Future.delayed(const Duration(milliseconds: 300), () { - animating = false; // Сбрасываем флаг анимации после всех анимаций + animating = false; checkMatches(); }); }); }); + swapNotifier.incrementScore(points); + return true; } - animating = false; // Сбрасываем флаг анимации, если нет совпадений + animating = false; return false; } @@ -213,7 +230,8 @@ class Board extends FlameGame { return count >= 3; } - void _removeMatchedElements(int row, int col) { + int _removeMatchedElements(int row, int col) { + int score = 0; final value = tiles[row]?[col]?.spriteIndex; int left = col; @@ -222,6 +240,8 @@ class Board extends FlameGame { while (right < cols - 1 && tiles[row]?[right + 1]?.spriteIndex == value) right++; if (right - left + 1 >= 3) { + int matchLength = right - left + 1; + score += _calculateScore(matchLength); for (int i = left; i <= right; i++) { if (tiles[row]?[i] != null) { _animateRemoveTile(tiles[row]![i]!); @@ -236,6 +256,8 @@ class Board extends FlameGame { while (bottom < rows - 1 && tiles[bottom + 1]?[col]?.spriteIndex == value) bottom++; if (bottom - top + 1 >= 3) { + int matchLength = bottom - top + 1; + score += _calculateScore(matchLength); for (int i = top; i <= bottom; i++) { if (tiles[i]?[col] != null) { _animateRemoveTile(tiles[i]![col]!); @@ -243,6 +265,17 @@ class Board extends FlameGame { } } } + + return score; + } + + int _calculateScore(int matchLength) { + if (matchLength == 3) { + return 50; + } else if (matchLength == 4) { + return 100; + } + return 0; } void _animateRemoveTile(Tile tile) { @@ -283,7 +316,7 @@ class Board extends FlameGame { row: row, col: col, onTileTap: handleTileTap, - onSwipe: handleTileSwipe, // Добавлен обработчик свайпов + onSwipe: handleTileSwipe, ); tiles[row][col] = tile; add(tile); diff --git a/lib/game/match_magic_game.dart b/lib/game/match_magic_game.dart index ba3a4d8..1808f47 100644 --- a/lib/game/match_magic_game.dart +++ b/lib/game/match_magic_game.dart @@ -1,10 +1,77 @@ import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; +import 'package:match_magic/game/sprite_loader.dart'; +import 'package:match_magic/main.dart'; import 'package:provider/provider.dart'; import 'board.dart'; import 'swap_notifier.dart'; +class MatchMagicGameScreen extends StatefulWidget { + const MatchMagicGameScreen({Key? key}) : super(key: key); + + @override + _MatchMagicGameScreenState createState() => _MatchMagicGameScreenState(); +} + +class _MatchMagicGameScreenState extends State { + late Future> _spritesFuture; + Board? board; + + @override + void initState() { + super.initState(); + _spritesFuture = SpriteLoader.loadSprites(); + } + + void _restartGame() { + context.read().resetScore(); + setState(() { + board = null; + _spritesFuture = SpriteLoader.loadSprites(); + }); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder>( + future: _spritesFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else if (!snapshot.hasData || snapshot.data == null) { + return const Center(child: Text('No sprites found')); + } else { + final sprites = snapshot.data!; + board ??= Board( + sprites: sprites, swapNotifier: context.read()); + return Column( + children: [ + const ScoreDisplay(), + Expanded( + child: Center( + child: AspectRatio( + aspectRatio: 1, + child: GameWidget(game: board!), + ), + ), + ), + ElevatedButton( + onPressed: _restartGame, + child: const Text('Restart'), + ), + ], + ); + } + } else { + return const Center(child: CircularProgressIndicator()); + } + }, + ); + } +} + class MatchMagicGame extends StatelessWidget { final List sprites; @@ -12,10 +79,26 @@ class MatchMagicGame extends StatelessWidget { @override Widget build(BuildContext context) { - return ChangeNotifierProvider( - create: (_) => SwapNotifier(), - child: GameWidget( - game: Board(sprites: sprites), + return GameWidget( + game: Board(sprites: sprites, swapNotifier: context.read()), + ); + } +} + +class ScoreDisplay extends StatelessWidget { + const ScoreDisplay({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Consumer( + builder: (context, notifier, child) { + return Text( + 'Score: ${notifier.score}', + style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ); + }, ), ); } diff --git a/lib/game/swap_notifier.dart b/lib/game/swap_notifier.dart index 9233387..1b07727 100644 --- a/lib/game/swap_notifier.dart +++ b/lib/game/swap_notifier.dart @@ -1,34 +1,46 @@ import 'package:flutter/material.dart'; -import 'board.dart'; import 'tile.dart'; class SwapNotifier extends ChangeNotifier { Tile? selectedTile; + int _score = 0; - void selectTile(Tile tile, Board board) { + int get score => _score; + + void resetScore() { + _score = 0; + selectedTile = null; + notifyListeners(); + } + + void incrementScore(int value) { + _score += value; + notifyListeners(); + } + + void selectTile(Tile tile) { if (selectedTile == null) { selectedTile = tile; tile.select(); } else { if (_isNeighbor(selectedTile!, tile)) { - board.swapTiles(selectedTile!, tile, true); - Future.delayed(const Duration(milliseconds: 300), () { - if (!board.checkMatches()) { - board.swapTiles(tile, selectedTile!, true); - } - selectedTile = null; - }); + notifyListeners(); } else { selectedTile?.deselect(); selectedTile = tile; tile.select(); + notifyListeners(); } } - notifyListeners(); } bool _isNeighbor(Tile tile1, Tile tile2) { return (tile1.row == tile2.row && (tile1.col - tile2.col).abs() == 1) || (tile1.col == tile2.col && (tile1.row - tile2.row).abs() == 1); } + + void clearSelectedTile() { + selectedTile = null; + notifyListeners(); + } } diff --git a/lib/main.dart b/lib/main.dart index ad5332d..c727e92 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -32,33 +32,3 @@ class MyApp extends StatelessWidget { ); } } - -class MatchMagicGameScreen extends StatelessWidget { - const MatchMagicGameScreen({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return FutureBuilder>( - future: SpriteLoader.loadSprites(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); - } else if (!snapshot.hasData || snapshot.data == null) { - return const Center(child: Text('No sprites found')); - } else { - final sprites = snapshot.data!; - return Center( - child: AspectRatio( - aspectRatio: 1, - child: MatchMagicGame(sprites: sprites), - ), - ); - } - } else { - return const Center(child: CircularProgressIndicator()); - } - }, - ); - } -}