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

Merge branch '25-use-painter-to-draw-game-parameters' into 'master'

Resolve "Use painter to draw game parameters"

Closes #25

See merge request !21
parents 3fdd9059 95b8bb3d
No related branches found
No related tags found
1 merge request!21Resolve "Use painter to draw game parameters"
Pipeline #4969 passed
......@@ -4,20 +4,30 @@ class DefaultGameSettings {
'colorsCount',
];
static const int defaultBoardSizeValue = 10;
static const int boardSizeValueSmall = 6;
static const int boardSizeValueMedium = 10;
static const int boardSizeValueLarge = 14;
static const int boardSizeValueExtraLarge = 20;
static const int defaultBoardSizeValue = boardSizeValueMedium;
static const List<int> allowedBoardSizeValues = [
6,
10,
14,
20,
boardSizeValueSmall,
boardSizeValueMedium,
boardSizeValueLarge,
boardSizeValueExtraLarge,
];
static const int defaultColorsCountValue = 6;
static const int colorsCountValueLow = 5;
static const int colorsCountValueMedium = 6;
static const int colorsCountValueHigh = 7;
static const int colorsCountValueVeryHigh = 8;
static const int defaultColorsCountValue = colorsCountValueMedium;
static const List<int> allowedColorsCountValues = [
5,
6,
7,
8,
colorsCountValueLow,
colorsCountValueMedium,
colorsCountValueHigh,
colorsCountValueVeryHigh,
];
static List<int> getAvailableValues(String parameterCode) {
......
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:jeweled/config/default_game_settings.dart';
import 'package:jeweled/utils/color_extensions.dart';
import 'package:jeweled/utils/color_theme.dart';
class ParameterPainter extends CustomPainter {
const ParameterPainter({
required this.code,
required this.value,
required this.isSelected,
});
final String code;
final int value;
final bool isSelected;
@override
void paint(Canvas canvas, Size size) {
// force square
final double canvasSize = min(size.width, size.height);
const Color borderColorEnabled = Colors.blue;
const Color borderColorDisabled = Colors.white;
// "enabled/disabled" border
final paint = Paint();
paint.style = PaintingStyle.stroke;
paint.color = this.isSelected ? borderColorEnabled : borderColorDisabled;
paint.strokeJoin = StrokeJoin.round;
paint.strokeWidth = 20 / 100 * canvasSize;
canvas.drawRect(Rect.fromPoints(Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
// content
switch (code) {
case 'colorsCount':
paintColorsCountParameterItem(value, canvas, canvasSize);
break;
case 'boardSize':
paintBoardSizeParameterItem(value, canvas, canvasSize);
break;
default:
print('Unknown parameter: ' + code + '/' + value.toString());
paintUnknownParameterItem(value, canvas, canvasSize);
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
// "unknown" parameter -> simple bock with text
void paintUnknownParameterItem(final int value, final Canvas canvas, final double size) {
final textSpan = TextSpan(
text: '?' + '\n' + value.toString(),
style: const TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
),
);
final textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(
canvas,
Offset(
(size - textPainter.width) * 0.5,
(size - textPainter.height) * 0.5,
),
);
}
void paintBoardSizeParameterItem(final int value, final Canvas canvas, final double size) {
Color backgroundColor = Colors.grey;
int gridWidth = 1;
switch (value) {
case DefaultGameSettings.boardSizeValueSmall:
backgroundColor = Colors.green;
gridWidth = 2;
break;
case DefaultGameSettings.boardSizeValueMedium:
backgroundColor = Colors.orange;
gridWidth = 3;
break;
case DefaultGameSettings.boardSizeValueLarge:
backgroundColor = Colors.red;
gridWidth = 4;
break;
case DefaultGameSettings.boardSizeValueExtraLarge:
backgroundColor = Colors.purple;
gridWidth = 5;
break;
default:
print('Wrong value for boardSize parameter value: ' + value.toString());
}
final paint = Paint();
paint.strokeJoin = StrokeJoin.round;
paint.strokeWidth = 3 / 100 * size;
// Colored background
paint.color = backgroundColor;
paint.style = PaintingStyle.fill;
canvas.drawRect(Rect.fromPoints(Offset(0, 0), Offset(size, size)), paint);
// Mini grid
final borderColor = Colors.grey.shade800;
final double cellSize = size / 7;
final double origin = (size - gridWidth * cellSize) / 2;
for (int row = 0; row < gridWidth; row++) {
for (int col = 0; col < gridWidth; col++) {
final Offset topLeft = Offset(origin + col * cellSize, origin + row * cellSize);
final Offset bottomRight = topLeft + Offset(cellSize, cellSize);
final squareColor = Color(ColorTheme.getColorCode(col + row * gridWidth));
paint.color = squareColor;
paint.style = PaintingStyle.fill;
canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
paint.color = borderColor;
paint.style = PaintingStyle.stroke;
canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
}
}
}
void paintColorsCountParameterItem(final int value, final Canvas canvas, final double size) {
Color backgroundColor = Colors.grey;
switch (value) {
case DefaultGameSettings.colorsCountValueLow:
backgroundColor = Colors.green;
break;
case DefaultGameSettings.colorsCountValueMedium:
backgroundColor = Colors.orange;
break;
case DefaultGameSettings.colorsCountValueHigh:
backgroundColor = Colors.red;
break;
case DefaultGameSettings.colorsCountValueVeryHigh:
backgroundColor = Colors.purple;
break;
default:
print('Wrong value for colorsCount parameter value: ' + value.toString());
}
final paint = Paint();
paint.strokeJoin = StrokeJoin.round;
paint.strokeWidth = 3 / 100 * size;
// Colored background
paint.color = backgroundColor;
paint.style = PaintingStyle.fill;
canvas.drawRect(Rect.fromPoints(Offset(0, 0), Offset(size, size)), paint);
// Colors preview
const List<Offset> positions = [
Offset(0, 0),
Offset(1, 0),
Offset(2, 0),
Offset(2, 1),
Offset(2, 2),
Offset(1, 2),
Offset(0, 2),
Offset(0, 1),
];
final double padding = 4 / 100 * size;
final double margin = 3 / 100 * size;
final double width = ((size - 2 * padding) / 3) - 2 * margin;
for (int colorIndex = 0; colorIndex < value; colorIndex++) {
final Offset position = positions[colorIndex];
final Offset topLeft = Offset(padding + margin + position.dx * (width + 2 * margin),
padding + margin + position.dy * (width + 2 * margin));
final Offset bottomRight = topLeft + Offset(width, width);
final squareColor = Color(ColorTheme.getColorCode(colorIndex));
paint.color = squareColor;
paint.style = PaintingStyle.fill;
canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
final borderColor = squareColor.darken(20);
paint.color = borderColor;
paint.style = PaintingStyle.stroke;
canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
}
// centered text value
final textSpan = TextSpan(
text: value.toString(),
style: TextStyle(
color: Colors.black,
fontSize: size / 4,
fontWeight: FontWeight.bold,
),
);
final textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(
canvas,
Offset(
(size - textPainter.width) * 0.5,
(size - textPainter.height) * 0.5,
),
);
}
}
......@@ -5,55 +5,53 @@ import 'package:jeweled/config/default_game_settings.dart';
import 'package:jeweled/cubit/game_cubit.dart';
import 'package:jeweled/cubit/settings_cubit.dart';
import 'package:jeweled/models/game_settings.dart';
import 'package:jeweled/ui/painters/parameter_painter.dart';
class Parameters extends StatelessWidget {
const Parameters({super.key});
static const double separatorHeight = 2.0;
static const double blockMargin = 3.0;
static const double blockPadding = 2.0;
static const Color buttonBackgroundColor = Colors.white;
static const Color buttonBorderColorActive = Colors.blue;
static const Color buttonBorderColorInactive = Colors.white;
static const double buttonBorderWidth = 10.0;
static const double buttonBorderRadius = 8.0;
static const double buttonPadding = 0.0;
static const double buttonMargin = 0.0;
@override
Widget build(BuildContext context) {
final double displayWidth = MediaQuery.of(context).size.width;
final double separatorHeight = 8.0;
return BlocBuilder<SettingsCubit, SettingsState>(
builder: (BuildContext context, SettingsState settingsState) {
final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
final SettingsCubit settingsCubit = BlocProvider.of<SettingsCubit>(context);
final List<Widget> lines = [];
final List<Widget> lines = [
SizedBox(height: separatorHeight),
];
DefaultGameSettings.availableParameters.forEach((code) {
final List<dynamic> availableValues = DefaultGameSettings.getAvailableValues(code);
final List<int> availableValues = DefaultGameSettings.getAvailableValues(code);
if (availableValues.length > 1) {
final List<Widget> parameterButtons = [];
final int currentValue = settingsCubit.getParameterValue(code);
final double itemWidth = displayWidth / availableValues.length - 25;
final dynamic currentValue = settingsCubit.getParameterValue(code);
final List<Widget> parameterButtons = [];
availableValues.forEach((value) {
final bool isActive = (value == currentValue);
final String imageAsset = code + '_' + value.toString();
final Widget parameterButton = 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,
margin: EdgeInsets.all(0),
padding: EdgeInsets.all(0),
child: CustomPaint(
size: Size(itemWidth, itemWidth),
willChange: false,
painter: ParameterPainter(
code: code,
value: value,
isSelected: isActive,
),
isComplex: true,
),
child: buildImageWidget(imageAsset),
),
onPressed: () => settingsCubit.setParameterValue(code, value),
);
......@@ -61,30 +59,20 @@ class Parameters extends StatelessWidget {
parameterButtons.add(parameterButton);
});
lines.add(Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
lines.add(Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: parameterButtons,
),
],
));
lines.add(SizedBox(height: separatorHeight));
}
});
return Container(
child: Column(
children: [
SizedBox(height: separatorHeight),
Column(
lines.add(SizedBox(height: separatorHeight));
lines.add(buildStartNewGameButton(gameCubit, settingsState.settings));
return Column(
children: lines,
),
SizedBox(height: separatorHeight),
buildStartNewGameButton(gameCubit, settingsState.settings),
],
),
);
},
);
......@@ -115,6 +103,9 @@ class Parameters extends StatelessWidget {
}
static Container buildStartNewGameButton(GameCubit gameCubit, GameSettings settings) {
const double blockMargin = 3.0;
const double blockPadding = 2.0;
return Container(
margin: EdgeInsets.all(blockMargin),
padding: EdgeInsets.all(blockPadding),
......
......@@ -40,10 +40,8 @@ class ColorTheme {
if (value != null && itemColors.containsKey(skin) && null != itemColors[skin]) {
List<int> skinColors = itemColors[skin] ?? [];
if (skinColors.length > value) {
return (skinColors[value % getColorsCount()]) | 0xFF000000;
}
}
return defaultItemColor | 0xFF000000;
}
......
......@@ -3,7 +3,7 @@ description: Jeweled Game
publish_to: 'none'
version: 0.0.18+18
version: 0.0.19+19
environment:
sdk: '^3.0.0'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment