| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- import 'package:flutter/material.dart';
- import 'package:gobang/models/chess.dart';
- import 'package:gobang/models/position.dart';
- import 'package:gobang/themes/app_colors.dart';
- import 'package:gobang/utils/constants.dart';
- /// 棋盘 + 棋子绘制;最后一手支持缩放入场与高亮光圈。
- class BoardPainter extends CustomPainter {
- BoardPainter({
- required this.pieces,
- required this.version,
- this.lastMoveScale = 1,
- this.lastMovePulse = 0,
- });
- final List<Position> pieces;
- final int version;
- final double lastMoveScale;
- final double lastMovePulse;
- @override
- void paint(Canvas canvas, Size size) {
- final cell = size.width / (kBoardSize - 1);
- final bg = Paint()
- ..shader = const LinearGradient(
- begin: Alignment.topLeft,
- end: Alignment.bottomRight,
- colors: [
- AppColors.woodLight,
- AppColors.woodMid,
- AppColors.woodDark,
- ],
- ).createShader(Offset.zero & size);
- final rrect = RRect.fromRectAndRadius(
- Offset.zero & size,
- const Radius.circular(12),
- );
- canvas.drawRRect(rrect, bg);
- final line = Paint()
- ..style = PaintingStyle.stroke
- ..color = const Color(0x66FFFFFF)
- ..strokeWidth = 1;
- for (var i = 0; i < kBoardSize; i++) {
- final o = cell * i;
- canvas.drawLine(Offset(0, o), Offset(size.width, o), line);
- canvas.drawLine(Offset(o, 0), Offset(o, size.height), line);
- }
- // 星位
- final star = Paint()..color = const Color(0xFF3D2B1F);
- for (final p in const [
- Offset(3, 3),
- Offset(3, 11),
- Offset(7, 7),
- Offset(11, 3),
- Offset(11, 11),
- ]) {
- canvas.drawCircle(
- Offset(p.dx * cell, p.dy * cell),
- 3,
- star,
- );
- }
- final radius = cell / 2 - 2;
- final fill = Paint()..style = PaintingStyle.fill;
- final lastIndex = pieces.length - 1;
- for (var i = 0; i < pieces.length; i++) {
- final p = pieces[i];
- final isLast = i == lastIndex;
- final center = Offset(p.dx, p.dy);
- final scale = isLast ? lastMoveScale.clamp(0.0, 1.2) : 1.0;
- final r = radius * scale;
- if (isLast && lastMovePulse > 0) {
- final ring = Paint()
- ..style = PaintingStyle.stroke
- ..strokeWidth = 2.5
- ..color = AppColors.lastMark.withValues(
- alpha: 0.85 * lastMovePulse,
- );
- canvas.drawCircle(center, radius * (1.15 + 0.45 * lastMovePulse), ring);
- }
- // 棋子阴影
- canvas.drawCircle(
- center.translate(1.2, 1.8),
- r,
- Paint()..color = const Color(0x44000000),
- );
- final isWhite = p.chess is WhiteChess;
- fill.shader = RadialGradient(
- center: const Alignment(-0.35, -0.4),
- radius: 0.95,
- colors: isWhite
- ? const [Color(0xFFFFFFFF), Color(0xFFD8D8D8)]
- : const [Color(0xFF4A4A4A), Color(0xFF111111)],
- ).createShader(Rect.fromCircle(center: center, radius: r));
- if (p.chessShape.shape == 1) {
- canvas.drawCircle(center, r, fill);
- } else {
- canvas.drawRRect(
- RRect.fromRectAndRadius(
- Rect.fromCircle(center: center, radius: r),
- Radius.circular(r * 0.2),
- ),
- fill,
- );
- }
- fill.shader = null;
- if (isLast && scale > 0.85) {
- final mark = Paint()
- ..style = PaintingStyle.fill
- ..color = AppColors.lastMark;
- final s = radius * 0.28;
- final path = Path()
- ..moveTo(center.dx, center.dy - s)
- ..lineTo(center.dx - s * 0.9, center.dy + s * 0.7)
- ..lineTo(center.dx + s * 0.9, center.dy + s * 0.7)
- ..close();
- canvas.drawPath(path, mark);
- }
- }
- }
- @override
- bool shouldRepaint(covariant BoardPainter oldDelegate) {
- return oldDelegate.version != version ||
- oldDelegate.lastMoveScale != lastMoveScale ||
- oldDelegate.lastMovePulse != lastMovePulse;
- }
- }
|