当小舞邂逅巴雷特蓝莓:一段跨越次元的甜蜜风暴

核心内容摘要

白鹿小白兔蹦出来了吗?揭秘森林深处的奇遇!
探秘“秘密教学”:知识的另一面,智慧的低语

OVA向日葵:当夜幕降临,金色花海悄然绽放

Flutter for OpenHarmony 实战碰撞检测算法与游戏结束处理文章目录Flutter for OpenHarmony 实战碰撞检测算法与游戏结束处理

前言

碰撞检测概述

1 墙壁碰撞

2 自身碰撞

3 检测时机

墙壁碰撞检测

1 边界判断算法

2 坐标越界示例

3 代码实现

自身碰撞检测

1 蛇身遍历算法

2 头部与身体比较

3 时间复杂度分析

碰撞响应机制

1 游戏结束状态设置

2 定时器清理流程

3 UI状态更新

完整代码实现

测试用例

八、

总结社区支持

前言碰撞检测是游戏开发中的核心机制。

在贪吃蛇游戏中需要检测两种碰撞撞墙边界碰撞和撞自己自身碰撞。

本文将详细讲解这两种碰撞的检测算法、游戏结束处理流程以及状态管理。

碰撞检测概述贪吃蛇游戏中需要检测的碰撞类型

1 墙壁碰撞蛇头超出网格边界x坐标 0 或 x ≥ 30y坐标 0 或 y ≥

2

2 自身碰撞蛇头与蛇身任意一节坐标重合不包括蛇头本身索引

0

3 检测时机每次蛇移动后在插入新头部之前检测void_update(){PointnewHead_getNewHead();// 计算新头部位置if(_checkCollision(newHead)){// 碰撞检测_gameOver();return;}snake.insert(0,newHead);// 无碰撞才插入}

墙壁碰撞检测

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

3

2 坐标越界示例// 示例1蛇头在右边缘向右移动PointheadPoint(29,

;// 最右边directionDirection.right;PointnewHeadPoint(30,

;// 越界_checkCollision(newHead);// 返回true// 示例2蛇头在上边缘向上移动PointheadPoint(15,

;// 最上边directionDirection.up;PointnewHeadPoint(15,-

;// 越界_checkCollision(newHead);// 返回true

3 代码实现完整的墙壁碰撞检测bool_checkCollision(Pointpoint){// 墙壁碰撞检测if(point.x0||point.xgridWidth||point.y0||point.ygridHeight){returntrue;}// 自身碰撞检测for(varsegmentinsnake){if(segment.xpoint.xsegment.ypoint.y){returntrue;}}returnfalse;}

自身碰撞检测

1 蛇身遍历算法// 自身碰撞检测for(varsegmentinsnake){if(segment.xpoint.xsegment.ysegment.y){returntrue;// 发现碰撞}}算法说明遍历snake列表中的每一节将新头部坐标与每节坐标比较如果x和y都相等说明碰撞返回true表示碰撞

2 头部与身体比较重要蛇头移动到的新位置可能与蛇身的任意一节重合。

// 示例蛇身坐标snake[Point(5,

,// 索引0当前头部Point(4,

,// 索引1

Point(3,

,// 索引2

];// 蛇向右移动新头部PointnewHeadPoint(6,

;// 检测newHead与snake[0/1/2]比较// (6,

vs (5,

→ 不同// (6,

vs (4,

→ 不同// (6,

vs (3,

→ 不同// 结果无碰撞碰撞示例// 蛇绕成一圈snake[Point(5,

,Point(5,

,Point(5,

,Point(6,

,Point(7,

,];// 蛇头向上移动PointnewHeadPoint(5,

;// 然后向右、向下移动...PointnewHeadPoint(7,

;// 最终撞到自己的身体(7,

与 (7,

相邻但y不同

3 时间复杂度分析for(varsegmentinsnake){// O(n)if(segment.xpoint.xsegment.ysegment.y){returntrue;}}时间复杂度O(n)n snake.length蛇的长度最坏情况遍历整个蛇身最好情况

就碰撞不太可能因为蛇头不会撞到当前头部位置优化思路蛇较短时100节O(n)可接受蛇很长时可以用HashSet存储身体坐标O(

查询但贪吃蛇游戏中蛇一般不会太长O(n)足够

碰撞响应机制

1 游戏结束状态设置void_gameOver(){isGameOvertrue;gameTimer?.cancel();setState((){});}状态变化isGameOverfalse → true停止定时器更新UI显示游戏结束信息

2 定时器清理流程void_gameOver(){isGameOvertrue;// 标记游戏结束gameTimer?.cancel();// 取消定时器setState((){});// 触发UI更新}为什么必须取消定时器定时器会持续触发_update()如果不取消会不断检测碰撞导致_gameOver()被重复调用浪费CPU资源定时器清理时机游戏结束时gameTimer?.cancel();速度变化时先cancel再重新创建组件销毁时dispose中cancel

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(speed

{speed-5;gameTimer?.cancel();_startGame();}_spawnFood();}else{snake.removeLast();}setState((){});}}

测试用例测试1墙壁碰撞// 边界测试test(右边界碰撞,(){snake[Point(29,

];directionDirection.right;PointnewHeadPoint(30,

;expect(_checkCollision(newHead),true);});test(上边界碰撞,(){snake[Point(15,

];directionDirection.up;PointnewHeadPoint(15,-

;expect(_checkCollision(newHead),true);});测试2自身碰撞test(撞到身体,(){snake[Point(5,

,Point(4,

,Point(3,

,];// 蛇头移动到(3,

重合PointnewHeadPoint(3,

;expect(_checkCollision(newHead),true);});

八、

总结本文讲解了碰撞检测算法墙壁碰撞检测坐标是否超出

范围自身碰撞遍历蛇身比较坐标游戏结束设置标志、取消定时器、更新UI时间复杂度O(n)n为蛇身长度关键要点碰撞检测在移动前执行防止无效移动定时器必须清理避免资源浪费使用isGameOver标志控制UI状态下篇预告《Flutter for OpenHarmony 实战食物生成算法与难度递增系统》社区支持欢迎加入开源 OpenHarmony 跨平台社区

获取更多技术支持和资源社区论坛开源 OpenHarmony 跨平台开发者社区技术交流参与社区讨论分享开发经验如果本文对您有帮助欢迎点赞、收藏和评论。

您的支持是我持续创作的动力

9.1视频平台安装-9.1视频平台安装应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123