Flutter for OpenHarmony 实战碰撞检测算法与游戏结束处理文章目录Flutter for OpenHarmony 实战碰撞检测算法与游戏结束处理一、前言二、碰撞检测概述2.1 墙壁碰撞2.2 自身碰撞2.3 检测时机三、墙壁碰撞检测3.1 边界判断算法3.2 坐标越界示例3.3 代码实现四、自身碰撞检测4.1 蛇身遍历算法4.2 头部与身体比较4.3 时间复杂度分析五、碰撞响应机制5.1 游戏结束状态设置5.2 定时器清理流程5.3 UI状态更新六、完整代码实现七、测试用例八、总结社区支持一、前言碰撞检测是游戏开发中的核心机制。在贪吃蛇游戏中需要检测两种碰撞撞墙边界碰撞和撞自己自身碰撞。本文将详细讲解这两种碰撞的检测算法、游戏结束处理流程以及状态管理。二、碰撞检测概述贪吃蛇游戏中需要检测的碰撞类型2.1 墙壁碰撞蛇头超出网格边界x坐标 0 或 x ≥ 30y坐标 0 或 y ≥ 202.2 自身碰撞蛇头与蛇身任意一节坐标重合不包括蛇头本身索引02.3 检测时机每次蛇移动后在插入新头部之前检测void_update(){PointnewHead_getNewHead();// 计算新头部位置if(_checkCollision(newHead)){// 碰撞检测_gameOver();return;}snake.insert(0,newHead);// 无碰撞才插入}三、墙壁碰撞检测3.1 边界判断算法bool_checkCollision(Pointpoint){// 检查墙壁碰撞if(point.x0||point.xgridWidth||point.y0||point.ygridHeight){returntrue;}// 检查自身碰撞稍后讲解// ...returnfalse;}判断条件分析条件含义示例point.x 0超出左边界x-1point.x gridWidth超出右边界x30point.y 0超出上边界y-1point.y gridHeight超出下边界y20为什么使用而不是有效坐标范围0到gridWidth-1即0到29gridWidth30时x30已经超出边界所以判断条件是 x 303.2 坐标越界示例// 示例1蛇头在右边缘向右移动PointheadPoint(29,10);// 最右边directionDirection.right;PointnewHeadPoint(30,10);// 越界_checkCollision(newHead);// 返回true// 示例2蛇头在上边缘向上移动PointheadPoint(15,0);// 最上边directionDirection.up;PointnewHeadPoint(15,-1);// 越界_checkCollision(newHead);// 返回true3.3 代码实现完整的墙壁碰撞检测bool_checkCollision(Pointpoint){// 墙壁碰撞检测if(point.x0||point.xgridWidth||point.y0||point.ygridHeight){returntrue;}// 自身碰撞检测for(varsegmentinsnake){if(segment.xpoint.xsegment.ypoint.y){returntrue;}}returnfalse;}四、自身碰撞检测4.1 蛇身遍历算法// 自身碰撞检测for(varsegmentinsnake){if(segment.xpoint.xsegment.ysegment.y){returntrue;// 发现碰撞}}算法说明遍历snake列表中的每一节将新头部坐标与每节坐标比较如果x和y都相等说明碰撞返回true表示碰撞4.2 头部与身体比较重要蛇头移动到的新位置可能与蛇身的任意一节重合。// 示例蛇身坐标snake[Point(5,10),// 索引0当前头部Point(4,10),// 索引1第二节Point(3,10),// 索引2第三节];// 蛇向右移动新头部PointnewHeadPoint(6,10);// 检测newHead与snake[0/1/2]比较// (6,10) vs (5,10) → 不同// (6,10) vs (4,10) → 不同// (6,10) vs (3,10) → 不同// 结果无碰撞碰撞示例// 蛇绕成一圈snake[Point(5,10),Point(5,11),Point(5,12),Point(6,12),Point(7,12),];// 蛇头向上移动PointnewHeadPoint(5,9);// 然后向右、向下移动...PointnewHeadPoint(7,11);// 最终撞到自己的身体(7,11) 与 (7,12) 相邻但y不同4.3 时间复杂度分析for(varsegmentinsnake){// O(n)if(segment.xpoint.xsegment.ysegment.y){returntrue;}}时间复杂度O(n)n snake.length蛇的长度最坏情况遍历整个蛇身最好情况第一节就碰撞不太可能因为蛇头不会撞到当前头部位置优化思路蛇较短时100节O(n)可接受蛇很长时可以用HashSet存储身体坐标O(1)查询但贪吃蛇游戏中蛇一般不会太长O(n)足够五、碰撞响应机制5.1 游戏结束状态设置void_gameOver(){isGameOvertrue;gameTimer?.cancel();setState((){});}状态变化isGameOverfalse → true停止定时器更新UI显示游戏结束信息5.2 定时器清理流程void_gameOver(){isGameOvertrue;// 标记游戏结束gameTimer?.cancel();// 取消定时器setState((){});// 触发UI更新}为什么必须取消定时器定时器会持续触发_update()如果不取消会不断检测碰撞导致_gameOver()被重复调用浪费CPU资源定时器清理时机游戏结束时gameTimer?.cancel();速度变化时先cancel再重新创建组件销毁时dispose中cancel5.3 UI状态更新overrideWidgetbuild(BuildContextcontext){returnScaffold(body:Column(children:[Expanded(child:CustomPaint(painter:GamePainter(...),),),// 游戏结束时显示if(isGameOver)Container(child:Column(children:[Text(游戏结束!),Text(最终得分:$score),ElevatedButton(onPressed:()_initGame(),child:Text(重新开始),),],),),],),);}UI变化游戏区域定格在最后状态游戏结束面板从隐藏变为显示控制按钮隐藏isGameOver为true时不显示六、完整代码实现class_GameHomePageStateextendsStateGameHomePage{// ...bool_checkCollision(Pointpoint){// 墙壁碰撞检测if(point.x0||point.xgridWidth||point.y0||point.ygridHeight){returntrue;}// 自身碰撞检测for(varsegmentinsnake){if(segment.xpoint.xsegment.ypoint.y){returntrue;}}returnfalse;}void_gameOver(){isGameOvertrue;gameTimer?.cancel();setState((){});}void_update(){if(nextDirection!null){directionnextDirection!;}PointnewHead_getNewHead();// 碰撞检测if(_checkCollision(newHead)){_gameOver();return;}snake.insert(0,newHead);if(newHead.xfood!.xnewHead.yfood!.y){score10;if(speed80){speed-5;gameTimer?.cancel();_startGame();}_spawnFood();}else{snake.removeLast();}setState((){});}}七、测试用例测试1墙壁碰撞// 边界测试test(右边界碰撞,(){snake[Point(29,10)];directionDirection.right;PointnewHeadPoint(30,10);expect(_checkCollision(newHead),true);});test(上边界碰撞,(){snake[Point(15,0)];directionDirection.up;PointnewHeadPoint(15,-1);expect(_checkCollision(newHead),true);});测试2自身碰撞test(撞到身体,(){snake[Point(5,10),Point(4,10),Point(3,10),];// 蛇头移动到(3,10)与第三节重合PointnewHeadPoint(3,10);expect(_checkCollision(newHead),true);});八、总结本文讲解了碰撞检测算法墙壁碰撞检测坐标是否超出0-29和0-19范围自身碰撞遍历蛇身比较坐标游戏结束设置标志、取消定时器、更新UI时间复杂度O(n)n为蛇身长度关键要点碰撞检测在移动前执行防止无效移动定时器必须清理避免资源浪费使用isGameOver标志控制UI状态下篇预告《Flutter for OpenHarmony 实战食物生成算法与难度递增系统》社区支持欢迎加入开源 OpenHarmony 跨平台社区获取更多技术支持和资源社区论坛开源 OpenHarmony 跨平台开发者社区技术交流参与社区讨论分享开发经验如果本文对您有帮助欢迎点赞、收藏和评论。您的支持是我持续创作的动力