Flutter for OpenHarmony 实战_七巧板游戏图案模板与交互系统
本文介绍了Flutter开发七巧板游戏的图案模板与交互系统实现。主要内容包括:1)图案模板系统设计,包含多种难度模板和切换机制;2)使用CustomPainter渲染模板轮廓和图块,实现高光效果和重绘优化;3)交互系统采用手势识别和状态管理,优化选择流程和移动交互。系统通过精确的几何计算和流畅的交互体验,为玩家提供直观的七巧板拼图游戏。
Flutter for OpenHarmony 实战:七巧板游戏图案模板与交互系统
欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区
前言

七巧板游戏不仅需要精确的几何计算,还需要提供直观的图案模板和流畅的交互体验。本文将详细介绍图案模板系统的设计、CustomPainter渲染技术、手势识别机制、状态反馈系统以及性能优化策略。
一、图案模板系统
1.1 模板数据结构
class TangramPattern {
final String name;
final List<List<Offset>> outlines;
const TangramPattern({
required this.name,
required this.outlines,
});
}
每个图案模板包含名称和轮廓线列表,轮廓线用于提示玩家摆放位置。outlines是二维数组,每个子数组表示一个多边形区域。
1.2 正方形模板
static const TangramPattern square = TangramPattern(
name: '正方形',
outlines: [
[Offset(150, 200), Offset(250, 200), Offset(200, 250)],
[Offset(150, 200), Offset(250, 200), Offset(250, 300), Offset(150, 300)],
],
);
正方形是七巧板最经典的拼法,将7块图块完美拼合成一个正方形。两个轮廓分别对应大三角形的位置。
1.3 多种模板支持




final List<TangramPattern> patterns = [
TangramPattern.square, // 正方形 - 基础
TangramPattern.cat, // 猫 - 中等
TangramPattern.house, // 房子 - 中等
TangramPattern.boat, // 船 - 困难
];
提供4个基础图案模板,按难度递进排列。这种设计让新手从简单的正方形开始,逐步挑战更复杂的图案。
1.4 模板切换机制
void _nextPattern() {
setState(() {
currentPatternIndex = (currentPatternIndex! + 1) % patterns.length;
});
}
使用取模运算实现循环切换,到达最后一个模板后回到第一个。这种无限循环设计让玩家可以反复练习。
二、PatternPainter渲染
2.1 模板轮廓绘制
class PatternPainter extends CustomPainter {
final TangramPattern pattern;
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.grey.shade300
..style = PaintingStyle.stroke
..strokeWidth = 2
..strokeJoin = StrokeJoin.round;
for (var outline in pattern.outlines) {
final path = Path();
path.moveTo(outline[0].dx, outline[0].dy);
for (int i = 1; i < outline.length; i++) {
path.lineTo(outline[i].dx, outline[i].dy);
}
path.close();
canvas.drawPath(path, paint);
}
}
}
使用灰色虚线绘制模板轮廓,strokeJoin.round使拐角更平滑。每个轮廓使用Path绘制,moveTo移动到起点,lineTo连接各点,close闭合路径。
2.2 模板名称显示
final textPainter = TextPainter(
text: TextSpan(
text: pattern.name,
style: const TextStyle(
color: Colors.grey,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(canvas, Offset(20, 20));
在左上角绘制模板名称,提示当前目标图案。使用TextPainter进行文本绘制,这是Flutter中处理文本的标准方式。
2.3 重绘优化
bool shouldRepaint(PatternPainter oldDelegate) {
return oldDelegate.pattern != pattern;
}
只在模板变化时重绘,避免不必要的性能消耗。
三、TangramPainter渲染
3.1 图块绘制
class TangramPainter extends CustomPainter {
final List<TangramPiece> pieces;
final TangramPiece? selectedPiece;
void paint(Canvas canvas, Size size) {
for (var piece in pieces) {
final path = Path();
path.moveTo(piece.vertices[0].dx, piece.vertices[0].dy);
for (int i = 1; i < piece.vertices.length; i++) {
path.lineTo(piece.vertices[i].dx, piece.vertices[i].dy);
}
path.close();
final paint = Paint()
..color = piece.color
..style = PaintingStyle.fill;
canvas.drawPath(path, paint);
}
}
}
遍历所有图块,使用Path绘制多边形并填充颜色。先moveTo到第一个顶点,然后lineTo连接其他顶点,最后close闭合路径。
3.2 边框绘制
final strokePaint = Paint()
..color = piece == selectedPiece ? Colors.white : Colors.black
..style = PaintingStyle.stroke
..strokeWidth = piece == selectedPiece ? 3 : 2;
canvas.drawPath(path, strokePaint);
根据选中状态使用不同颜色和粗细绘制边框。选中:白色3像素,未选中:黑色2像素。
3.3 高光效果
if (piece == selectedPiece) {
final highlightPaint = Paint()
..color = Colors.yellow.withValues(alpha: 0.5)
..style = PaintingStyle.stroke
..strokeWidth = 6;
canvas.drawPath(path, highlightPaint);
}
选中图块额外绘制黄色半透明高光,宽度6像素,增强视觉反馈。
四、交互系统设计
4.1 手势识别
GestureDetector(
onPanStart: _handlePanStart,
onPanUpdate: _handlePanUpdate,
onPanEnd: _handlePanEnd,
child: CustomPaint(...),
)
使用GestureDetector捕获拖拽手势,提供流畅的触摸交互。onPanStart检测选择,onPanUpdate处理移动,onPanEnd结束操作。
4.2 选择流程优化
for (int i = pieces.length - 1; i >= 0; i--) {
if (_isPointInPiece(localPosition, pieces[i])) {
setState(() {
selectedPiece = pieces[i];
pieces.removeAt(i);
pieces.add(selectedPiece!);
});
break;
}
}
从上层到底层检测,选择第一个包含点击点的图块,并将其移到数组末尾(最上层)。这种设计确保选中的图块始终显示在最前面。
4.3 移动交互
void _handlePanUpdate(DragUpdateDetails details) {
if (selectedPiece == null || dragStartPosition == null) return;
final delta = details.localPosition - dragStartPosition!;
setState(() {
for (int i = 0; i < selectedPiece!.vertices.length; i++) {
selectedPiece!.vertices[i] = selectedPiece!.vertices[i] + delta;
}
dragStartPosition = details.localPosition;
});
}
计算与上一帧的偏移量,更新所有顶点位置,实现整体移动。
五、状态反馈系统
5.1 视觉反馈层次
选中图块有三层视觉反馈:
- 边框颜色:白色vs黑色
- 边框粗细:3像素vs2像素
- 外发光效果:黄色半透明高光
5.2 提示信息
Text(
selectedPiece != null ? '已选中: ${selectedPiece!.name}' : '点击图块选中,拖拽移动,使用按钮旋转翻转',
style: const TextStyle(fontSize: 14),
textAlign: TextAlign.center,
)
底部显示当前选中图块名称或操作提示,帮助玩家了解当前状态。
5.3 层次管理
pieces.removeAt(i);
pieces.add(selectedPiece!);
选中时将图块移到数组末尾,确保绘制在最上层。
六、性能优化
6.1 shouldRepaint实现
bool shouldRepaint(TangramPainter oldDelegate) {
return oldDelegate.selectedPiece != selectedPiece;
}
只在选中状态变化时重绘,避免频繁的无效重绘。
6.2 快速排斥实验
在碰撞检测中首先排除明显不相交的情况,提高检测效率。
6.3 逆序遍历
for (int i = pieces.length - 1; i >= 0; i--) {
从最上层开始检测,选中第一个符合条件的图块,避免遍历所有图块。
总结
本文详细介绍了七巧板游戏的图案模板和交互系统。从模板设计到渲染技术,从手势识别到状态反馈,每个技术点都为创造直观易用的游戏体验做出了贡献。通过这些技术的综合应用,实现了功能完整且交互流畅的七巧板游戏。
更多推荐

所有评论(0)