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

Use painters to draw game parameters selectors

parent 3fdd9059
No related branches found
No related tags found
1 merge request!21Resolve "Use painter to draw game parameters"
Pipeline #4966 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