Skip to content
Snippets Groups Projects
Commit 5e297ab2 authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Merge branch '1-init-application' into 'master'

Resolve "Init application"

Closes #1

See merge request !1
parents a8f99d6d ea45bf18
No related branches found
No related tags found
1 merge request!1Resolve "Init application"
Pipeline #3881 passed
Showing
with 824 additions and 0 deletions
Tetris Dual - Assistant de jeu
\ No newline at end of file
Tetris Dual - Assistant de jeu
\ No newline at end of file
AuthorName: 'Benoît Harrault'
Categories:
- Games
Name: Tetris Dual assistant
AutoName: TetrisDualAssistant
License: GPL-3.0-only
WebSite: 'https://git.harrault.fr/android/org.benoitharrault.tetrisdual'
SourceCode: https://git.harrault.fr/android/org.benoitharrault.tetrisdual
IssueTracker: https://git.harrault.fr/android/org.benoitharrault.tetrisdual/issues
Changelog: https://git.harrault.fr/android/org.benoitharrault.tetrisdual/-/tags
Summary: Tetris Dual - Game Assistant
Description: |-
Tetris Dual - Game Assistant.
Will replace Tetris dual (physical game) LCD game controller.
RepoType: git
Repo: 'https://git.harrault.fr/android/org.benoitharrault.tetrisdual.git'
#! /bin/bash
# Check dependencies
command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
BASE_DIR="$(dirname "${CURRENT_DIR}")"
ASSETS_DIR="${BASE_DIR}/assets"
OPTIPNG_OPTIONS="-preserve -quiet -o7"
ICON_SIZE=192
#######################################################
# Game images
AVAILABLE_GAME_IMAGES="
button_back
button_start
placeholder
"
# Settings images
AVAILABLES_GAME_SETTINGS="
"
#######################################################
# optimize svg
function optimize_svg() {
SOURCE="$1"
cp ${SOURCE} ${SOURCE}.tmp
scour \
--remove-descriptive-elements \
--enable-id-stripping \
--enable-viewboxing \
--enable-comment-stripping \
--nindent=4 \
--quiet \
-i ${SOURCE}.tmp \
-o ${SOURCE}
rm ${SOURCE}.tmp
}
# build icons
function build_icon() {
SOURCE="$1"
TARGET="$2"
echo "Building ${TARGET}"
if [ ! -f "${SOURCE}" ]; then
echo "Missing file: ${SOURCE}"
exit 1
fi
optimize_svg "${SOURCE}"
inkscape \
--export-width=${ICON_SIZE} \
--export-height=${ICON_SIZE} \
--export-filename=${TARGET} \
${SOURCE}
optipng ${OPTIPNG_OPTIONS} ${TARGET}
}
#######################################################
# Create output folders
mkdir -p ${ASSETS_DIR}/icons
# Delete existing generated images
find ${ASSETS_DIR}/icons -type f -name "*.png" -delete
# build game images
for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
do
build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/icons/${GAME_IMAGE}.png
done
#! /bin/bash
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
"${CURRENT_DIR}/build_application_icons.sh"
"${CURRENT_DIR}/build_repository_icons.sh"
#! /bin/bash
# Check dependencies
command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
BASE_DIR="$(dirname "${CURRENT_DIR}")"
SOURCE_ICON="${CURRENT_DIR}/icon.svg"
SOURCE_FASTLANE="${CURRENT_DIR}/featureGraphic.svg"
SOURCE_LAUNCH_IMAGE="${CURRENT_DIR}/icon.svg"
OPTIPNG_OPTIONS="-preserve -quiet -o7"
if [ ! -f "${SOURCE_ICON}" ]; then
echo "Missing file: ${SOURCE_ICON}"
fi
if [ ! -f "${SOURCE_FASTLANE}" ]; then
echo "Missing file: ${SOURCE_FASTLANE}"
fi
if [ ! -f "${SOURCE_LAUNCH_IMAGE}" ]; then
echo "Missing file: ${SOURCE_LAUNCH_IMAGE}"
fi
function optimize_svg() {
SVG="$1"
cp ${SVG} ${SVG}.tmp
scour \
--remove-descriptive-elements \
--enable-id-stripping \
--enable-viewboxing \
--enable-comment-stripping \
--nindent=4 \
--quiet \
-i ${SVG}.tmp \
-o ${SVG}
rm ${SVG}.tmp
}
# optimize source svg files
optimize_svg ${SOURCE_ICON}
optimize_svg ${SOURCE_FASTLANE}
optimize_svg ${SOURCE_LAUNCH_IMAGE}
# build icons
function build_application_icon() {
ICON_SIZE="$1"
TARGET="$2"
echo "Building ${TARGET}"
TARGET_PNG="${TARGET}.png"
inkscape \
--export-width=${ICON_SIZE} \
--export-height=${ICON_SIZE} \
--export-filename=${TARGET_PNG} \
${SOURCE_ICON}
optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG}
}
# build fastlane image
function build_fastlane_image() {
WIDTH="$1"
HEIGHT="$2"
TARGET="$3"
echo "Building ${TARGET}"
TARGET_PNG="${TARGET}.png"
inkscape \
--export-width=${WIDTH} \
--export-height=${HEIGHT} \
--export-filename=${TARGET_PNG} \
${SOURCE_FASTLANE}
optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG}
}
# build launch images (splash screen)
function build_launch_image() {
ICON_SIZE="$1"
TARGET="$2"
echo "Building ${TARGET}"
TARGET_PNG="${TARGET}.png"
inkscape \
--export-width=${ICON_SIZE} \
--export-height=${ICON_SIZE} \
--export-filename=${TARGET_PNG} \
${SOURCE_LAUNCH_IMAGE}
optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG}
}
build_application_icon 72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/ic_launcher
build_application_icon 48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/ic_launcher
build_application_icon 96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/ic_launcher
build_application_icon 144 ${BASE_DIR}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher
build_application_icon 192 ${BASE_DIR}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher
build_application_icon 512 ${BASE_DIR}/fastlane/metadata/android/en-US/images/icon
build_launch_image 72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/launch_image
build_launch_image 48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/launch_image
build_launch_image 96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/launch_image
build_launch_image 144 ${BASE_DIR}/android/app/src/main/res/mipmap-xxhdpi/launch_image
build_launch_image 192 ${BASE_DIR}/android/app/src/main/res/mipmap-xxxhdpi/launch_image
build_fastlane_image 1024 500 ${BASE_DIR}/fastlane/metadata/android/en-US/images/featureGraphic
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 1024 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="1024" height="500" rx="0" ry="0" fill="#977cff"/></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 28.747 28.747" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="filter6206-7" x="-.072" y="-.072001" width="1.144" height="1.144" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="0.658125"/>
</filter>
</defs>
<g transform="translate(0 -1093.8)">
<path transform="matrix(1.0781 0 0 1.0641 -.093733 2.7509)" d="m4.4177 1028.2v1.6051h-1.6052v18.192h1.6052v2.1402h18.192v-2.1402h2.1402v-18.192h-2.1402v-1.6051z" fill="#1a237e" filter="url(#filter6206-7)" opacity=".2"/>
<rect x="2.9987" y="1096.8" width="22.749" height="22.749" rx="1.1973" ry="1.1974" fill="#3f51b5"/>
<g transform="translate(-22.32 1056.5)">
<path d="m0 0h51.2v51.2h-51.2z" fill="none" stroke-width="1.0667"/>
<g transform="matrix(.33601 0 0 .33601 1.5296 73.043)">
<path d="m0 0h51.2v51.2h-51.2z" fill="none" stroke-width="1.0667"/>
</g>
<g transform="matrix(.37187 0 0 .37187 38.802 63.239)">
<path d="m0 0h51.2v51.2h-51.2z" fill="none" stroke-width="1.0667"/>
<g transform="matrix(2.6891 0 0 2.6891 -82.906 -48.45)">
<path d="m0 0h51.2v51.2h-51.2z" fill="none" stroke-width="1.0667"/>
</g>
</g>
</g>
<path d="m4.1958 1096.8c-0.66332 0-1.1979 0.5346-1.1979 1.1979v0.3334c0-0.6634 0.53459-1.1979 1.1979-1.1979h20.354c0.66332 0 1.1979 0.5345 1.1979 1.1979v-0.3334c0-0.6633-0.5346-1.1979-1.1979-1.1979z" fill="#fff" opacity=".2"/>
<rect x="128" y="546.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="128" y="631.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="128" y="674.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="128" y="589.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="128" y="717.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="213.33" y="546.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="213.33" y="631.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="213.33" y="674.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="213.33" y="589.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="213.33" y="717.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="298.67" y="546.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="298.67" y="631.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="298.67" y="674.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="298.67" y="589.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="298.67" y="717.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="170.67" y="546.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="170.67" y="631.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="170.67" y="674.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="170.67" y="589.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="170.67" y="717.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="256" y="546.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="256" y="631.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="256" y="674.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="256" y="589.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="256" y="717.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="128" y="759.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="213.33" y="759.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="298.67" y="759.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="170.67" y="759.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="256" y="759.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="341.33" y="589.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="341.33" y="631.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="341.33" y="717.19" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="341.33" y="546.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="341.33" y="674.52" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="341.33" y="759.85" width="42.667" height="42.667" fill="none" stroke-width="1.0667"/>
<rect x="160" y="578.52" width="192" height="192" fill="none" stroke-width="1.0667"/>
<g transform="matrix(.37344 0 0 .37344 4.7333 1097.4)">
<path d="m0 0h51.2v51.2h-51.2z" fill="none" stroke-width="1.0667"/>
</g>
<g transform="matrix(.36471 0 0 .36471 5.1356 1097.4)">
<path d="m0 0h51.2v51.2h-51.2z" fill="none" stroke-width="1.0667"/>
</g>
<g transform="matrix(.41585 0 0 .41585 84.325 1055.9)">
<g transform="matrix(.062269 0 0 .062269 -28.238 185.29)">
<g transform="matrix(38.618 0 0 38.618 14724 -13542)">
<g transform="matrix(.71436 0 0 .71436 -400.52 188.34)">
<path d="m1293.2-120.67c-181.75 0.2763-511.18 0.13525-699.05 0.13998-2.3216 10.413-3.593 21.251-3.593 32.384v114c207.65 0.73695 494.72 0.38136 706.23 0.3733v-114.37c0-11.18-1.2522-22.07-3.593-32.523zm-458.69 295.56c-78.385-4e-3 -158.85 0.17892-243.95 0.55995v138.63c286.34-0.39317 421.73-0.13827 706.23-0.32664v-137.75c-163.2-0.53005-311.22-1.1113-462.28-1.1199z" opacity="0" stroke-width="1.4932"/>
</g>
</g>
</g>
</g>
<path d="m24.549 1119.5c0.66325 0 1.1979-0.5346 1.1979-1.1979v-0.3333c0 0.6632-0.53461 1.1978-1.1979 1.1978h-20.354c-0.66325 0-1.1979-0.5346-1.1979-1.1978v0.3333c0 0.6633 0.53461 1.1979 1.1979 1.1979z" fill="#1a237e" opacity=".2"/>
</g>
<g transform="matrix(.36901 0 0 .36901 -1.2187 13.371)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3">
<rect x="31.881" y="-12.943" width="10.173" height="10.173"/>
<rect x="31.881" y="-2.3698" width="10.173" height="10.173"/>
<rect x="42.454" y="-2.3698" width="10.173" height="10.173"/>
<rect x="42.454" y="8.2031" width="10.173" height="10.173"/>
</g>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"/>
import 'package:flutter/material.dart';
import 'package:tetrisdual/layout/board_painter.dart';
import 'package:tetrisdual/provider/data.dart';
class Board {
static Container buildGameBoard(Data myProvider, double boardWidth) {
return Container(
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
child: Column(
children: [
Container(
child: Center(
child: GestureDetector(
onTapUp: (details) {
double xTap = details.localPosition.dx;
double yTap = details.localPosition.dy;
print('xTap: ' + xTap.toString() + ' / yTap: ' + yTap.toString());
},
child: Container(
child: CustomPaint(
size: Size(boardWidth, boardWidth),
willChange: false,
painter: BoardPainter(myProvider),
isComplex: true,
),
),
),
),
)
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:tetrisdual/provider/data.dart';
class BoardPainter extends CustomPainter {
const BoardPainter(this.myProvider);
final Data myProvider;
@override
void paint(Canvas canvas, Size size) {
print('paint');
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
class ColorTheme {
static Map<String, Map<String, int>> colors = {
'default': {
'0': 0xffffff,
'1': 0xff6f43,
'2': 0x708cfd,
},
};
static int defaultColor = 0x808080;
static int getColorCode(String skin, String value) {
if (colors.containsKey(skin) && null != colors[skin]) {
Map<String, int>? skinColors = colors[skin];
if (null != skinColors && skinColors.containsKey(value) && null != skinColors[value]) {
return (skinColors[value] ?? defaultColor) | 0xFF000000;
}
}
return defaultColor | 0xFF000000;
}
}
import 'package:flutter/material.dart';
import 'package:tetrisdual/layout/board.dart';
import 'package:tetrisdual/provider/data.dart';
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: [
Text(
'X',
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
Text(
'Y',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.grey,
),
),
],
),
Column(
children: [
Text(
'Z',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.green,
),
),
],
),
],
),
],
);
}
static TextButton buildQuitGameButton(Data myProvider) {
return TextButton(
child: Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill,
),
onPressed: () => GameUtils.quitGame(myProvider),
);
}
static Container buildEndGameMessage(Data myProvider) {
String decorationImageAssetName = 'assets/icons/game_fail.png';
Widget decorationWidget = TextButton(
child: Image(
image: AssetImage(decorationImageAssetName),
fit: BoxFit.fill,
),
onPressed: () => null,
);
return Container(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
Column(
children: [decorationWidget],
),
Column(
children: [buildQuitGameButton(myProvider)],
),
Column(
children: [decorationWidget],
),
],
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:tetrisdual/provider/data.dart';
import 'package:tetrisdual/utils/game_utils.dart';
class Parameters {
static double separatorHeight = 2.0;
static double blockMargin = 3.0;
static double blockPadding = 2.0;
static Color buttonBackgroundColor = Colors.white;
static Color buttonBorderColorActive = Colors.blue;
static Color buttonBorderColorInactive = Colors.white;
static double buttonBorderWidth = 10.0;
static double buttonBorderRadius = 8.0;
static double buttonPadding = 0.0;
static double buttonMargin = 0.0;
static Container buildParametersSelector(Data myProvider) {
List<Widget> lines = [];
List parameters = myProvider.availableParameters;
for (var index = 0; index < parameters.length; index++) {
lines.add(buildParameterSelector(myProvider, parameters[index]));
lines.add(SizedBox(height: separatorHeight));
}
Widget buttonsBlock = buildStartNewGameButton(myProvider);
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: separatorHeight),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: lines,
),
),
SizedBox(height: separatorHeight),
Container(
child: buttonsBlock,
),
],
),
);
}
static Image buildImageWidget(String imageAssetCode) {
return Image(
image: AssetImage('assets/icons/' + imageAssetCode + '.png'),
fit: BoxFit.fill,
);
}
static Container buildImageContainerWidget(String imageAssetCode) {
return Container(
child: buildImageWidget(imageAssetCode),
);
}
static Column buildDecorationImageWidget() {
return Column(
children: [
TextButton(
child: buildImageContainerWidget('placeholder'),
onPressed: () => null,
),
],
);
}
static Container buildStartNewGameButton(Data myProvider) {
return Container(
margin: EdgeInsets.all(blockMargin),
padding: EdgeInsets.all(blockPadding),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
buildDecorationImageWidget(),
Column(
children: [
TextButton(
child: buildImageContainerWidget('button_start'),
onPressed: () => GameUtils.startNewGame(myProvider),
),
],
),
buildDecorationImageWidget(),
],
),
],
),
);
}
static Widget buildParameterSelector(Data myProvider, String parameterCode) {
List availableValues = myProvider.getParameterAvailableValues(parameterCode);
if (availableValues.length == 1) {
return SizedBox(height: 0.0);
}
return Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
for (var index = 0; index < availableValues.length; index++)
Column(
children: [
_buildParameterButton(myProvider, parameterCode, availableValues[index])
],
),
],
),
],
);
}
static Widget _buildParameterButton(
Data myProvider, String parameterCode, String parameterValue) {
String currentValue = myProvider.getParameterValue(parameterCode).toString();
bool isActive = (parameterValue == currentValue);
String imageAsset = parameterCode + '_' + parameterValue;
return TextButton(
child: Container(
margin: EdgeInsets.all(buttonMargin),
padding: EdgeInsets.all(buttonPadding),
decoration: BoxDecoration(
color: buttonBackgroundColor,
borderRadius: BorderRadius.circular(buttonBorderRadius),
border: Border.all(
color: isActive ? buttonBorderColorActive : buttonBorderColorInactive,
width: buttonBorderWidth,
),
),
child: buildImageWidget(imageAsset),
),
onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tetrisdual/provider/data.dart';
import 'package:tetrisdual/screens/home.dart';
import 'package:provider/provider.dart';
import 'package:overlay_support/overlay_support.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((value) => runApp(MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (BuildContext context) => Data(),
child: Consumer<Data>(builder: (context, data, child) {
return OverlaySupport(
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Home(),
routes: {
Home.id: (context) => Home(),
},
),
);
}),
);
}
}
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Data extends ChangeNotifier {
// Configuration available parameters
List _availableParameters = [];
List get availableParameters => _availableParameters;
// Application default configuration
// Application current configuration
String getParameterValue(String parameterCode) {
switch (parameterCode) {
}
return '';
}
List getParameterAvailableValues(String parameterCode) {
switch (parameterCode) {
}
return [];
}
void setParameterValue(String parameterCode, String parameterValue) async {
switch (parameterCode) {
}
final prefs = await SharedPreferences.getInstance();
prefs.setString(parameterCode, parameterValue);
}
// Game data
bool _gameIsRunning = false;
bool _gameIsFinished = false;
bool get isGameRunning => _gameIsRunning;
void updateGameIsRunning(bool gameIsRunning) {
_gameIsRunning = gameIsRunning;
notifyListeners();
}
bool get isGameFinished => _gameIsFinished;
void updateGameIsFinished(bool gameIsFinished) {
_gameIsFinished = gameIsFinished;
notifyListeners();
}
void resetGame() {
_gameIsRunning = false;
_gameIsFinished = false;
notifyListeners();
}
}
import 'package:flutter/material.dart';
import 'package:tetrisdual/layout/game.dart';
import 'package:tetrisdual/layout/parameters.dart';
import 'package:tetrisdual/provider/data.dart';
import 'package:tetrisdual/utils/game_utils.dart';
import 'package:provider/provider.dart';
import 'package:overlay_support/overlay_support.dart';
class Home extends StatefulWidget {
static const String id = 'home';
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
Data myProvider = Provider.of<Data>(context);
double boardWidth = MediaQuery.of(context).size.width;
List<Widget> menuActions = [];
if (myProvider.isGameRunning) {
menuActions = [
TextButton(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.blue,
width: 4,
),
),
child: Image(
image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill,
),
),
onPressed: () => toast('Long press to quit game...'),
onLongPress: () => GameUtils.quitGame(myProvider),
),
];
}
return Scaffold(
appBar: AppBar(
actions: menuActions,
),
body: SafeArea(
child: Center(
child: myProvider.isGameRunning
? Game.buildGameWidget(myProvider, boardWidth)
: Parameters.buildParametersSelector(myProvider),
),
),
);
}
}
import 'package:tetrisdual/provider/data.dart';
class GameUtils {
static Future<void> quitGame(Data myProvider) async {
myProvider.updateGameIsRunning(false);
}
static Future<void> startNewGame(Data myProvider) async {
print('Starting game');
myProvider.resetGame();
myProvider.updateGameIsRunning(true);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment