news 2026/9/3 8:09:29

Flutter for OpenHarmony 实战_吃豆人游戏迷宫生成与渲染系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter for OpenHarmony 实战_吃豆人游戏迷宫生成与渲染系统

Flutter for OpenHarmony 实战:吃豆人游戏迷宫生成与渲染系统

欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区

文章目录

  • Flutter for OpenHarmony 实战:吃豆人游戏迷宫生成与渲染系统
    • 前言
    • 一、迷宫数据结构设计
      • 1.1 迷宫布局表示
      • 1.2 豆子状态管理
    • 二、CustomPainter渲染系统
      • 2.1 画布坐标系设置
      • 2.2 墙壁绘制
      • 2.3 豆子绘制
    • 三、吃豆人角色绘制
      • 3.1 弧形绘制技术
      • 3.2 方向控制实现
      • 3.3 嘴巴动画系统
      • 3.4 眼睛细节绘制
    • 四、游戏循环与定时器
      • 4.1 双定时器系统
      • 4.2 定时器生命周期管理
    • 五、重绘优化策略
      • 5.1 精确的重绘控制
    • 六、UI界面设计
      • 6.1 状态栏设计
      • 6.2 游戏容器样式
    • 总结

前言

吃豆人游戏是经典的街机游戏,玩家需要在迷宫中控制角色吃掉所有豆子,同时躲避幽灵的追逐。本文将详细介绍如何使用Flutter for OpenHarmony实现吃豆人游戏的迷宫生成和渲染系统,包括迷宫数据结构设计、CustomPainter绘制技术、角色动画实现等核心技术点。

一、迷宫数据结构设计

1.1 迷宫布局表示

代码中使用15x15的二维数组表示迷宫布局:

staticconstint rows=15;staticconstint cols=15;// 0 = 空地, 1 = 墙, 2 = 豆子finalList<List<int>>initialMaze=[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,2,2,2,2,2,2,1,2,2,2,2,2,2,1],[1,2,1,1,2,1,2,2,2,1,2,1,1,2,1],[1,2,2,2,2,1,2,1,2,1,2,2,2,2,1],[1,2,1,1,2,1,2,1,2,1,2,1,1,2,1],[1,2,2,2,2,2,2,2,2,2,2,2,2,2,1],[1,2,1,1,2,1,1,1,1,1,2,1,1,2,1],[1,2,2,2,2,1,0,0,0,1,2,2,2,2,1],[1,2,1,1,2,1,1,1,1,1,2,1,1,2,1],[1,2,2,2,2,2,2,2,2,2,2,2,2,2,1],[1,2,1,1,2,1,2,1,2,1,2,1,1,2,1],[1,2,2,2,2,1,2,1,2,1,2,2,2,2,1],[1,2,1,1,2,1,2,2,2,1,2,1,1,2,1],[1,2,2,2,2,2,2,1,2,2,2,2,2,2,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],];

这种设计将迷宫的每个单元格用整数表示,数字0、1、2分别对应空地、墙壁和豆子,简洁明了地表达了游戏场景的完整信息。

1.2 豆子状态管理

代码使用布尔二维数组单独管理豆子状态:

lateList<List<bool>>dots;dots=List.generate(rows,(i)=>List.generate(cols,(j)=>maze[i][j]==2));

通过遍历迷宫数组,将所有值为2的位置标记为true,这样可以独立控制每个位置的豆子是否被吃掉,而不影响原始迷宫布局。

二、CustomPainter渲染系统

2.1 画布坐标系设置

staticconstdouble cellSize=20.0;@overridevoidpaint(Canvascanvas,Sizesize){finalcellWidth=size.width/cols;finalcellHeight=size.height/rows;}

将画布动态划分为15x15的网格,每个单元格的尺寸根据画布总尺寸计算,确保在不同屏幕尺寸下都能正确显示。

2.2 墙壁绘制

if(maze[y][x]==1){finalrect=Rect.fromLTWH(x*cellWidth,y*cellHeight,cellWidth,cellHeight,);finalpaint=Paint()..color=Colors.blue.shade700..style=PaintingStyle.fill;canvas.drawRect(rect,paint);}

遍历迷宫数组,遇到值为1的位置时,使用Rect.fromLTWH创建矩形区域,然后用深蓝色填充,形成迷宫的墙壁效果。

2.3 豆子绘制

if(dots[y][x]){finalcenter=Offset(x*cellWidth+cellWidth/2,y*cellHeight+cellHeight/2,);finalpaint=Paint()..color=Colors.yellow..style=PaintingStyle.fill;canvas.drawCircle(center,cellWidth/8,paint);}

豆子使用黄色圆形表示,圆心位于单元格中心,半径为单元格宽度的1/8,这个比例保证了豆子大小适中,既清晰可见又不会过大。

三、吃豆人角色绘制

3.1 弧形绘制技术

吃豆人角色的核心是一个带有张嘴动画的扇形:

finalpacmanCenter=Offset(pacmanX*cellWidth+cellWidth/2,pacmanY*cellHeight+cellHeight/2,);finalpacmanPaint=Paint()..color=Colors.yellow..style=PaintingStyle.fill;finalstartAngle=_getPacmanStartAngle();finalsweepAngle=_getPacmanSweepAngle();canvas.drawArc(Rect.fromCircle(center:pacmanCenter,radius:cellWidth/2.2),startAngle,sweepAngle,true,pacmanPaint,);

使用drawArc方法绘制扇形,第一个参数是扇形的外接圆,第二个参数是起始角度,第三个参数是扫过的角度,第四个参数true表示使用圆心形成扇形。

3.2 方向控制实现

根据移动方向计算扇形的起始角度:

double_getPacmanStartAngle(){finalbaseAngle=pacmanDirection*pi/2;returnbaseAngle+mouthOpen*pi/180;}

四个方向分别对应不同的baseAngle值:0对应向上(0弧度),1对应向右(π/2弧度),2对应向下(π弧度),3对应向左(3π/2弧度)。加上mouthOpen角度后,嘴巴就会朝向移动方向。

3.3 嘴巴动画系统

嘴巴的张合动画通过定时器实现:

int mouthOpen=0;int mouthDirection=1;voidupdateMouth(){setState((){mouthOpen+=mouthDirection;if(mouthOpen>=45||mouthOpen<=0){mouthDirection*=-1;}});}

mouthOpen在0到45度之间往复变化,每次增加或减少mouthDirection,当达到边界值时将direction乘以-1实现反转。这个定时器每200毫秒执行一次,形成流畅的张嘴动画效果。

3.4 眼睛细节绘制

finaleyeOffset=Offset(pacmanCenter.dx+cellWidth/6*cos(_getPacmanEyeAngle()),pacmanCenter.dy+cellWidth/6*sin(_getPacmanEyeAngle()),);finaleyePaint=Paint()..color=Colors.black..style=PaintingStyle.fill;canvas.drawCircle(eyeOffset,cellWidth/15,eyePaint);double_getPacmanEyeAngle(){returnpacmanDirection*pi/2-pi/2;}

眼睛的位置使用三角函数计算,距离圆心为cellWidth/6,角度比移动方向少π/2(90度),使眼睛始终位于扇形开口方向,增强角色的方向感。

四、游戏循环与定时器

4.1 双定时器系统

代码使用两个独立的定时器分别控制吃豆人和幽灵:

Timer?gameTimer;Timer?ghostTimer;gameTimer=Timer.periodic(constDuration(milliseconds:200),(timer){if(!gameOver&&!won){movePacman();updateMouth();}});ghostTimer=Timer.periodic(constDuration(milliseconds:300),(timer){if(!gameOver&&!won){moveGhosts();checkCollisions();}});

吃豆人每200毫秒移动一次,幽灵每300毫秒移动一次,这种时间差异让玩家的速度略快于幽灵,增加了游戏的公平性和可玩性。

4.2 定时器生命周期管理

@overridevoiddispose(){gameTimer?.cancel();ghostTimer?.cancel();super.dispose();}

在组件销毁时取消所有定时器,避免内存泄漏和资源浪费。

五、重绘优化策略

5.1 精确的重绘控制

@overrideboolshouldRepaint(PacManPainteroldDelegate){returnoldDelegate.pacmanX!=pacmanX||oldDelegate.pacmanY!=pacmanY||oldDelegate.pacmanDirection!=pacmanDirection||oldDelegate.mouthOpen!=mouthOpen||oldDelegate.ghosts!=ghosts;}

只在关键状态变化时才重绘,避免每帧都重绘带来的性能开销。这种细粒度的重绘控制是游戏性能优化的关键。

六、UI界面设计

6.1 状态栏设计

AppBar(backgroundColor:Colors.blue.shade900,title:constText('吃豆人游戏',style:TextStyle(color:Colors.yellow,fontWeight:FontWeight.bold)),actions:[Center(child:Padding(padding:constEdgeInsets.only(right:16),child:Text('得分:$score生命:$lives',style:constTextStyle(color:Colors.white,fontSize:16,fontWeight:FontWeight.bold,),),),),],)

使用深蓝色背景和黄色标题营造街机风格,右侧实时显示得分和生命值,让玩家随时了解游戏状态。

6.2 游戏容器样式

Container(decoration:BoxDecoration(border:Border.all(color:Colors.blue.shade700,width:3),borderRadius:BorderRadius.circular(8),),child:CustomPaint(size:constSize(cols*cellSize,rows*cellSize),painter:PacManPainter(maze:maze,dots:dots,pacmanX:pacmanX,pacmanY:pacmanY,pacmanDirection:pacmanDirection,mouthOpen:mouthOpen,ghosts:ghosts,),),)

游戏区域使用3像素的蓝色边框和8像素圆角,与整体设计风格保持一致。

总结

本文详细介绍了吃豆人游戏的迷宫生成和渲染系统,从数据结构设计到CustomPainter绘制,从角色动画到游戏循环,完整展示了使用Flutter for OpenHarmony开发经典游戏的完整技术路径。通过这些技术实现,我们能够创建出视觉效果出色、运行流畅的游戏体验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 22:09:55

Python全栈入门到实战【基础篇 16】字符串核心进阶:格式化方法(%/format/f-string)

在Python编程中,拼接或格式化字符串是高频操作——比如输出用户信息、生成动态文本、拼接带变量的日志内容等。直接用+拼接字符串不仅代码冗余,还容易出现类型不匹配问题,而Python提供的字符串格式化方法能高效解决这类问题。 本节系统讲解Python中4种主流的字符串格式化方…

作者头像 李华
网站建设 2026/9/2 22:09:58

消费即挖矿:区块链商城如何用智能合约重构万亿级返利经济

引言&#xff1a;一场静默的消费生态重构当传统电商平台的"双11"战报逐渐失去吸引力&#xff0c;当消费者对复杂优惠规则产生审美疲劳&#xff0c;一场由区块链技术驱动的消费革命正在悄然兴起。据DappRadar最新数据显示&#xff0c;2025年全球区块链商城DAPP日活用户…

作者头像 李华
网站建设 2026/9/3 0:57:16

ComponentOne Blazor Charts利用趋势线识别关键数据模式

利用趋势线识别关键数据模式---ComponentOne Blazor Charts 2026年2月4日趋势线揭示潜在模式&#xff0c;阐明长期趋势&#xff0c;并将图表数据转化为清晰、可操作的见解&#xff0c;从而加快决策速度。ComponentOne Blazor Charts图表中的趋势线是一种分析工具&#xff0c;它…

作者头像 李华
网站建设 2026/9/2 22:09:00

超声波技术对萨拉米香肠品质的影响

超声波技术对萨拉米香肠品质的影响 第一章 研究背景与研究目标 萨拉米香肠作为典型的发酵肉制品&#xff0c;其品质形成依赖于发酵成熟过程中的微生物代谢、蛋白质降解与脂肪氧化。传统工艺成熟周期长、品质均一性差&#xff0c;且易受杂菌污染&#xff0c;制约生产效率与产品稳…

作者头像 李华
网站建设 2026/9/2 6:02:42

排序(2)

先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01; ^ _ ^ ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的支持就是我坚持下去的动力&#xff0c;点赞后不要忘记关注我哦 个人主页&#xff1a;伯明翰java 文章专栏&#xff1a;数据结构和算法 如有错误&#xff0…

作者头像 李华
网站建设 2026/9/2 22:14:29

本科生必看!全网顶尖的AI论文平台 —— 千笔·专业论文写作工具

你是否曾为论文选题发愁&#xff0c;反复修改却总对结果不满意&#xff1f;是否在查重和格式上花费大量时间却收效甚微&#xff1f;面对繁重的学术任务&#xff0c;很多同学都感到力不从心。而如今&#xff0c;一款专为学生打造的AI论文写作工具——千笔AI&#xff0c;正悄然改…

作者头像 李华