diff --git a/android/gradle.properties b/android/gradle.properties index 818e87b23b224ced309ae5c147e5ed827826e237..db7a1ee2908d6e94aeb319e1c1b548a8bb245891 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.0.2 -app.versionCode=2 +app.versionName=0.0.3 +app.versionCode=3 diff --git a/fastlane/metadata/android/en-US/changelogs/3.txt b/fastlane/metadata/android/en-US/changelogs/3.txt new file mode 100644 index 0000000000000000000000000000000000000000..0b66218ab5b5439847f39fbda7b65eaa975e4460 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3.txt @@ -0,0 +1 @@ +Add minimal 2 players game diff --git a/fastlane/metadata/android/fr-FR/changelogs/3.txt b/fastlane/metadata/android/fr-FR/changelogs/3.txt new file mode 100644 index 0000000000000000000000000000000000000000..2785db161132e1dddf3b87dca6b6d7748c29a391 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/3.txt @@ -0,0 +1 @@ +Ajout du mode 2 joueurs (minimal) diff --git a/lib/entity/player.dart b/lib/entity/player.dart new file mode 100644 index 0000000000000000000000000000000000000000..227ab9f9b1b9a10afae27aef719fbb22f499699a --- /dev/null +++ b/lib/entity/player.dart @@ -0,0 +1,65 @@ +import 'dart:math'; + +import 'package:flutter/cupertino.dart'; +import 'package:tetrisdual/layout/board_painter.dart'; +import 'package:tetrisdual/provider/data.dart'; + +class Player { + int _currentTetrimino = 0; + + Widget buildTetriminoWidget(Data myProvider, double width) { + return Container( + child: GestureDetector( + onTapUp: (details) { + pickRandomTetrimino(); + myProvider.redraw(); + }, + child: Container( + child: CustomPaint( + size: Size(width, width), + willChange: false, + painter: BoardPainter(_currentTetrimino), + isComplex: true, + key: Key(_currentTetrimino.toString()), + ), + ), + ), + ); + } + + Widget buildManagerWidget() { + return Container( + margin: EdgeInsets.all(5), + child: Column( + children: [ + Text(''), + ], + ), + ); + } + + Widget buildPlayerBoard(Data myProvider, double boardWidth) { + double tetriminoBlockWidth = boardWidth / 2; + + return Row( + children: [ + buildTetriminoWidget(myProvider, tetriminoBlockWidth), + buildManagerWidget(), + ], + ); + } + + void pickRandomTetrimino() { + // ensure new tetrimino is not same as current one + int newTetrimino = _currentTetrimino; + while (newTetrimino == _currentTetrimino) { + newTetrimino = Random().nextInt(5) + 1; + } + + _currentTetrimino = newTetrimino; + } + + void resetTetrimino() { + _currentTetrimino = 0; + } +} diff --git a/lib/layout/board.dart b/lib/layout/board.dart index 009bd5fabbb9d49901007c6e4475586c1da51629..06686669b7dd5a6467703196b6c54307ac664282 100644 --- a/lib/layout/board.dart +++ b/lib/layout/board.dart @@ -1,32 +1,49 @@ import 'package:flutter/material.dart'; -import 'package:tetrisdual/layout/board_painter.dart'; import 'package:tetrisdual/provider/data.dart'; -import 'package:tetrisdual/utils/game_utils.dart'; class Board { + static Container activePlayer(Widget playerBoard, bool active) { + Color borderColor = active ? Colors.greenAccent : Colors.blueGrey; + + return Container( + decoration: BoxDecoration( + border: Border.all( + color: borderColor, + width: 15, + ), + ), + child: playerBoard, + ); + } + static Container buildGameBoard(Data myProvider, double boardWidth) { + Widget player1 = new RotatedBox( + quarterTurns: 2, + child: myProvider.getPlayer(1).buildPlayerBoard(myProvider, boardWidth), + ); + Widget player2 = myProvider.getPlayer(2).buildPlayerBoard(myProvider, boardWidth); + + Widget togglePlayerWidget = GestureDetector( + onTapUp: (details) { + myProvider.toggleCurrentPlayer(); + myProvider.getPlayer(myProvider.currentPlayer).pickRandomTetrimino(); + }, + child: Text( + '🔄', + style: TextStyle( + fontSize: 50, + ), + ), + ); + return Container( - margin: EdgeInsets.all(4), - padding: EdgeInsets.all(4), child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Container( - child: Center( - child: GestureDetector( - onTapUp: (details) { - GameUtils.pickRandomTetrimino(myProvider); - }, - child: Container( - child: CustomPaint( - size: Size(boardWidth, boardWidth), - willChange: false, - painter: BoardPainter(myProvider), - isComplex: true, - ), - ), - ), - ), - ) + activePlayer(player1, myProvider.currentPlayer == 1), + togglePlayerWidget, + activePlayer(player2, myProvider.currentPlayer == 2), ], ), ); diff --git a/lib/layout/board_painter.dart b/lib/layout/board_painter.dart index 620de7c5c2c4f803a0d593b2467ff3401c382952..47c4d30b8348cdb04366b076d4fa57fb556ca493 100644 --- a/lib/layout/board_painter.dart +++ b/lib/layout/board_painter.dart @@ -1,12 +1,11 @@ import 'dart:math'; import 'package:flutter/material.dart'; -import 'package:tetrisdual/provider/data.dart'; class BoardPainter extends CustomPainter { - const BoardPainter(this.myProvider); + const BoardPainter(this.currentTetrimino); - final Data myProvider; + final int currentTetrimino; void drawPixels(List<List<int>> pixels, Canvas canvas, double drawSize, Color pixelColor) { int blockWidth = 1; @@ -69,7 +68,7 @@ class BoardPainter extends CustomPainter { canvas.drawRect(rectBackground, paintBackground); // Add tetrimino - switch (myProvider.currentTetrimino) { + switch (currentTetrimino) { // empty case 0: break; diff --git a/lib/layout/game.dart b/lib/layout/game.dart index d46557140943a7742594cb5b708f278d55fbae12..a12eddeb986da596402a86d4988e38a3e260a562 100644 --- a/lib/layout/game.dart +++ b/lib/layout/game.dart @@ -5,42 +5,10 @@ import 'package:tetrisdual/utils/game_utils.dart'; class Game { static Container buildGameWidget(Data myProvider, double boardWidth) { - bool gameIsFinished = myProvider.isGameFinished; - return Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(height: 8), - Game.buildTopIndicatorWidget(myProvider), - SizedBox(height: 2), - Expanded( - child: Board.buildGameBoard(myProvider, boardWidth), - ), - SizedBox(height: 2), - Container( - child: gameIsFinished ? Game.buildEndGameMessage(myProvider) : SizedBox(height: 2), - ), - ], - ), - ); - } - - static Widget buildTopIndicatorWidget(Data myProvider) { - return Table( - children: [ - TableRow( - children: [ - Column( - children: [], - ), - Column( - children: [], - ), - ], - ), - ], + child: !myProvider.isGameFinished + ? Board.buildGameBoard(myProvider, boardWidth) + : Game.buildEndGameMessage(myProvider), ); } diff --git a/lib/provider/data.dart b/lib/provider/data.dart index 8d0d68858bf76d56e7617584f96b95ff0e1cf78a..63c76e329b5ff22c9fe7255a0017e447e2abc428 100644 --- a/lib/provider/data.dart +++ b/lib/provider/data.dart @@ -1,5 +1,8 @@ +import 'dart:math'; + import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tetrisdual/entity/player.dart'; class Data extends ChangeNotifier { // Configuration available parameters @@ -32,7 +35,8 @@ class Data extends ChangeNotifier { // Game data bool _gameIsRunning = false; bool _gameIsFinished = false; - int _currentTetrimino = 0; + int _currentPlayer = 0; + List<Player?> _players = [null, null]; bool get isGameRunning => _gameIsRunning; void updateGameIsRunning(bool gameIsRunning) { @@ -46,15 +50,50 @@ class Data extends ChangeNotifier { notifyListeners(); } - int get currentTetrimino => _currentTetrimino; - void updateCurrentTetrimino(int currentTetrimino) { - _currentTetrimino = currentTetrimino; + int get currentPlayer => _currentPlayer; + void toggleCurrentPlayer() { + if (_currentPlayer == 0) { + // start game + _currentPlayer = 1; + } else { + // Reset current player tetrimino + getCurrentPlayer().resetTetrimino(); + + // 1 -> 2 ; 2 -> 1 + _currentPlayer = 3 - _currentPlayer; + } + notifyListeners(); + } + + void enableRandomPlayer() { + _currentPlayer = Random().nextInt(2) + 1; + } + + Player getPlayer(int playerId) { + int playerIndex = playerId - 1; + Player? player = _players[playerIndex]; + + // Create new player if none + if (null == player) { + player = new Player(); + _players[playerIndex] = player; + } + + return player; + } + + Player getCurrentPlayer() { + return getPlayer(currentPlayer); + } + + void redraw() { notifyListeners(); } void resetGame() { _gameIsRunning = false; _gameIsFinished = false; + _players = [new Player(), new Player()]; notifyListeners(); } } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 32d196c5dc9fe498b08c61355cbb83508a9b640d..952fb7ca99c5cc0a9e2458dca70b9c561030f4ad 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -53,11 +53,9 @@ class _HomeState extends State<Home> { actions: menuActions, ), body: SafeArea( - child: Center( - child: myProvider.isGameRunning - ? Game.buildGameWidget(myProvider, boardWidth) - : Parameters.buildParametersSelector(myProvider), - ), + child: myProvider.isGameRunning + ? Game.buildGameWidget(myProvider, boardWidth) + : Parameters.buildParametersSelector(myProvider), ), ); } diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart index 86fcd8ae35cfde461553599f94466ff58462d055..5bd436ba68ef0e2c9943efce9b629e8e90326049 100644 --- a/lib/utils/game_utils.dart +++ b/lib/utils/game_utils.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:tetrisdual/provider/data.dart'; class GameUtils { @@ -11,14 +9,8 @@ class GameUtils { print('Starting game'); myProvider.resetGame(); + myProvider.enableRandomPlayer(); + myProvider.getCurrentPlayer().pickRandomTetrimino(); myProvider.updateGameIsRunning(true); } - - static void pickRandomTetrimino(Data myProvider) { - int newTetrimino = myProvider.currentTetrimino; - while (newTetrimino == myProvider.currentTetrimino) { - newTetrimino = Random().nextInt(5) + 1; - } - myProvider.updateCurrentTetrimino(newTetrimino); - } }