Created
January 13, 2025 21:59
-
-
Save PlugFox/a74b5b478f357d79d301086ac869db68 to your computer and use it in GitHub Desktop.
Flutter chess example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:math' as math; | |
import 'dart:ui'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/gestures.dart'; | |
import 'package:flutter/rendering.dart'; | |
import 'package:flutter/scheduler.dart'; | |
import 'package:flutter/services.dart'; | |
class _Binding = BindingBase | |
with | |
GestureBinding, | |
SchedulerBinding, | |
ServicesBinding, | |
PaintingBinding, | |
SemanticsBinding, | |
RendererBinding; | |
/// Биндинь - соединение между движком Flutter и движком рендеринга | |
final binding = () { | |
final instance = _Binding()..deferFirstFrame(); | |
return instance; | |
}(); | |
void main() { | |
final dispatcher = binding.platformDispatcher; | |
final views = dispatcher.views; | |
if (views.isEmpty) { | |
SystemNavigator.pop(); | |
return; | |
} | |
final view = views.first; | |
// Получаем информацию о размерах экрана | |
final windowSize = view.physicalSize; | |
final pixelRatio = view.devicePixelRatio; | |
final logicalSize = windowSize / pixelRatio; | |
// Создаем рекордер для записи команд рисования | |
final recorder = PictureRecorder(); | |
final canvas = Canvas(recorder); | |
// Определяем размеры и положение шахматной доски | |
// Центрируем доску на экране | |
final boardSize = math.min(logicalSize.width, logicalSize.height) * 0.8; | |
final rect = Rect.fromCenter( | |
center: Offset(logicalSize.width / 2, logicalSize.height / 2), | |
width: boardSize, | |
height: boardSize, | |
); | |
// Рисуем доску и фигуры | |
drawChessboard(canvas, rect); | |
drawPieces(canvas, rect); | |
drawBoardBorder(canvas, rect); | |
drawCoordinates(canvas, rect); | |
// Создаем PictureLayer и сохраняем в нем результат рисования | |
final pictureLayer = PictureLayer(rect)..picture = recorder.endRecording(); | |
// Создаем корневой слой и добавляем в него наш PictureLayer | |
final rootLayer = OffsetLayer()..append(pictureLayer); | |
// Создаем сцену и отправляем ее на отрисовку | |
final sceneBuilder = SceneBuilder() | |
..pushClipRect(rect) // Обрезаем всё за пределами доски | |
..pop(); | |
final scene = rootLayer.buildScene(sceneBuilder); | |
view.render(scene); | |
// Добавляем обработчик изменения размера окна | |
dispatcher | |
..onError = (error, stackTrace) { | |
print('! Error: $error\n$stackTrace'); // ignore: avoid_print | |
return true; | |
} | |
..onMetricsChanged = () { | |
// ... | |
} | |
..onLocaleChanged = () { | |
// ... | |
} | |
..onDrawFrame = () { | |
// ... | |
} | |
..onViewFocusChange = (event) { | |
// ... | |
}; | |
binding.allowFirstFrame(); | |
} | |
void drawChessboard(Canvas canvas, Rect rect) { | |
final paint = Paint(); | |
final cellSize = rect.width / 8; | |
// Рисуем базовый фон доски | |
canvas.drawRect(rect, Paint()..color = const Color(0xFFE5C9A7)); | |
// Рисуем темные клетки | |
paint.color = const Color(0xFF7A4F31); | |
for (var row = 0; row < 8; row++) { | |
for (var col = 0; col < 8; col++) { | |
if ((row + col) % 2 == 1) { | |
canvas.drawRect( | |
Rect.fromLTWH( | |
rect.left + col * cellSize, | |
rect.top + row * cellSize, | |
cellSize, | |
cellSize, | |
), | |
paint, | |
); | |
} | |
} | |
} | |
} | |
void drawPieces(Canvas canvas, Rect rect) { | |
final cellSize = rect.width / 8; | |
final paint = Paint() | |
..style = PaintingStyle.fill | |
..strokeWidth = 2.0; | |
const black = Color(0xFF000000), white = Color(0xFFFFFFFF); | |
// Функция для рисования фигуры | |
void Function({required bool isWhite}) drawPiece(int col, int row) => | |
({required isWhite}) { | |
final center = Offset( | |
rect.left + (col + 0.5) * cellSize, | |
rect.top + (row + 0.5) * cellSize, | |
); | |
paint.color = isWhite ? white : black; | |
// Рисуем базовую форму фигуры (упрощенно) | |
canvas.drawCircle(center, cellSize * 0.4, paint); | |
// Добавляем обводку | |
paint | |
..style = PaintingStyle.stroke | |
..color = isWhite ? black : white; | |
canvas.drawCircle(center, cellSize * 0.4, paint); | |
paint.style = PaintingStyle.fill; | |
}; | |
// Расставляем фигуры начальной позиции | |
for (var col = 0; col < 8; col++) { | |
// Черные пешки | |
drawPiece(col, 1)(isWhite: false); | |
// Белые пешки | |
drawPiece(col, 6)(isWhite: true); | |
} | |
// Расставляем основные фигуры | |
for (var col = 0; col < 8; col++) { | |
drawPiece(col, 0)(isWhite: false); // Черные фигуры | |
drawPiece(col, 7)(isWhite: true); // Белые фигуры | |
} | |
} | |
void drawBoardBorder(Canvas canvas, Rect rect) { | |
final paint = Paint() | |
..color = const Color(0xFF4A3728) | |
..style = PaintingStyle.stroke | |
..strokeWidth = 4.0; | |
// Рисуем внешнюю рамку | |
canvas.drawRect(rect, paint); | |
} | |
void drawCoordinates(Canvas canvas, Rect rect) { | |
final textStyle = TextStyle( | |
color: const Color(0xFF000000), | |
fontSize: rect.width / 30, | |
fontWeight: FontWeight.bold, | |
); | |
final cellSize = rect.width / 8; | |
// Рисуем буквы (a-h) | |
for (var i = 0; i < 8; i++) { | |
final letter = String.fromCharCode('a'.codeUnitAt(0) + i); | |
final textSpan = TextSpan(text: letter, style: textStyle); | |
final textPainter = TextPainter( | |
text: textSpan, | |
textDirection: TextDirection.ltr, | |
)..layout(); | |
textPainter.paint( | |
canvas, | |
Offset( | |
rect.left + i * cellSize + cellSize / 2 - textPainter.width / 2, | |
rect.bottom + 5, | |
), | |
); | |
} | |
// Рисуем цифры (1-8) | |
for (var i = 0; i < 8; i++) { | |
final number = (8 - i).toString(); | |
final textSpan = TextSpan(text: number, style: textStyle); | |
final textPainter = TextPainter( | |
text: textSpan, | |
textDirection: TextDirection.ltr, | |
)..layout(); | |
textPainter.paint( | |
canvas, | |
Offset( | |
rect.left - textPainter.width - 5, | |
rect.top + i * cellSize + cellSize / 2 - textPainter.height / 2, | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment