import 'package:flutter/material.dart'; import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; import 'package:jeweled/config/default_game_settings.dart'; import 'package:jeweled/models/game/cell_location.dart'; import 'package:jeweled/models/game/game.dart'; import 'package:jeweled/models/settings/settings_game.dart'; import 'package:jeweled/models/settings/settings_global.dart'; part 'game_state.dart'; class GameCubit extends HydratedCubit<GameState> { GameCubit() : super(GameState( currentGame: Game.createEmpty(), )); void updateState(Game game) { emit(GameState( currentGame: game, )); } void refresh() { final Game game = Game( // Settings gameSettings: state.currentGame.gameSettings, globalSettings: state.currentGame.globalSettings, // State isRunning: state.currentGame.isRunning, isStarted: state.currentGame.isStarted, isFinished: state.currentGame.isFinished, animationInProgress: state.currentGame.animationInProgress, // Base data board: state.currentGame.board, // Game data shuffledColors: state.currentGame.shuffledColors, availableBlocksCount: state.currentGame.availableBlocksCount, score: state.currentGame.score, movesCount: state.currentGame.movesCount, ); // game.dump(); updateState(game); } void startNewGame({ required GameSettings gameSettings, required GlobalSettings globalSettings, }) { final Game newGame = Game.createNew( gameSettings: gameSettings, globalSettings: globalSettings, ); newGame.dump(); updateState(newGame); postAnimate(); } void quitGame() { state.currentGame.isRunning = false; refresh(); } void resumeSavedGame() { state.currentGame.isRunning = true; refresh(); } void deleteSavedGame() { state.currentGame.isRunning = false; state.currentGame.isFinished = true; refresh(); } void updateCellValue(CellLocation locationToUpdate, int? value) { state.currentGame.updateCellValue(locationToUpdate, value); refresh(); } void increaseMovesCount() { state.currentGame.isStarted = true; state.currentGame.increaseMovesCount(); refresh(); } void increaseScore(int increment) { state.currentGame.increaseScore(increment); refresh(); } void updateAvailableBlocksCount() { state.currentGame.updateAvailableBlocksCount(); refresh(); } void updateGameIsFinished(bool gameIsFinished) { state.currentGame.isFinished = gameIsFinished; refresh(); } void shuffleColors(final String colorsTheme) { state.currentGame.shuffleColorsAgain(colorsTheme); } moveCellsDown() { final Game currentGame = state.currentGame; final int boardSizeHorizontal = currentGame.gameSettings.boardSizeValue; final int boardSizeVertical = currentGame.gameSettings.boardSizeValue; for (int row = 0; row < boardSizeVertical; row++) { for (int col = 0; col < boardSizeHorizontal; col++) { // empty cell? if (currentGame.getCellValue(CellLocation.go(row, col)) == null) { // move cells down for (int r = row; r > 0; r--) { updateCellValue(CellLocation.go(r, col), currentGame.getCellValue(CellLocation.go(r - 1, col))); } // fill top empty cell updateCellValue( CellLocation.go(0, col), currentGame.getFillValue(CellLocation.go(row, col))); } } } } void deleteBlock(List<CellLocation> block) { // Sort cells from top to bottom block.sort((cell1, cell2) => cell1.row.compareTo(cell2.row)); // Delete all cells for (CellLocation blockItemToDelete in block) { updateCellValue(blockItemToDelete, null); } } int getScoreFromBlock(int blockSize) { return 3 * (blockSize - 2); } List<CellLocation> tapOnCell(CellLocation tappedCellLocation) { final Game currentGame = state.currentGame; final int? cellValue = currentGame.getCellValue(tappedCellLocation); if (cellValue != null) { List<CellLocation> blockCells = currentGame.getSiblingCells(tappedCellLocation, []); if (blockCells.length >= DefaultGameSettings.blockMinimumCellsCount) { deleteBlock(blockCells); increaseMovesCount(); increaseScore(getScoreFromBlock(blockCells.length)); return blockCells; } } return []; } void postAnimate() { moveCellsDown(); updateAvailableBlocksCount(); refresh(); if (!state.currentGame.hasAtLeastOneAvailableBlock()) { printlog('no more block found. finish game.'); updateGameIsFinished(true); } } @override GameState? fromJson(Map<String, dynamic> json) { final Game currentGame = json['currentGame'] as Game; return GameState( currentGame: currentGame, ); } @override Map<String, dynamic>? toJson(GameState state) { return <String, dynamic>{ 'currentGame': state.currentGame.toJson(), }; } }