开发ing经验关于游戏中寻路
2010-02-27 23:06
267 查看
任何的游戏几乎都需要寻路吸,最常用的则是A星寻路,这个算法在网络上可以找到很多的版本,然而,今天则是一起探讨寻路算法的问题。
在我们当前的正在开发的项目中,使用的就是A*算法,在正常的寻路中表现非常好,速度很快,但是实际过程中,用户则有可能点击一个不可能到达的点,那么这个时候有趣的问题就发生了,整个逻辑则会“顿”一下,当然了,这取决于运算方法和主要逻辑是不是在一起,这得另说。只说“顿”的情况,它的发生是因为这个点不可能到达,则我们强大的A*寻路把所有的点全部找个遍,实际情况则是这样的:在4000x3000的地图上,寻路循环进行了30万次,才只是找到一个近似路径而已,我们将这个部分做了修改,将寻路缩小到指定范围,如果超过这个范围则不在进行寻路,图例表示如下:
只对设定的范围内进行搜索,这也是比限定搜索长度要容易的方式,我尝试使用限定搜索的总长度,但是不怎么好,对于A*的算法代码改动太大,而使用设定范围,只需要在超出范围时候控制好即可。
关于直接寻路,我们会得到一个很不自然的路径,那么为什么不先进行直线行走,走到特定位置然后再按按照寻路点走呢,我们的项目中是这样的解决的,先使用向量计算,然后判定按照步长上的每个点是否在不可达点上,当出现这种情况,则调用寻路,虽然不能达到100%的平滑寻路,但是对于普通的行走已经足够应付,会走一个相对很爽的路径。
可能上述写的很杂乱,表述的问题其实很简单,有的时候我们研究和优化很多的代码,都是存在于实验室——一个完美的环境,而在真实环境将面临着用户乱点一通,或者提出为什么不是很平滑的移动的问题,这些问题有可能让我们需要将路重走一遍,而本篇则是我们项目当中的一篇更新邮件子内容。
关于限定范围中的部分写在寻路算法当中,由于代码过长,只能节选一部分
在我们当前的正在开发的项目中,使用的就是A*算法,在正常的寻路中表现非常好,速度很快,但是实际过程中,用户则有可能点击一个不可能到达的点,那么这个时候有趣的问题就发生了,整个逻辑则会“顿”一下,当然了,这取决于运算方法和主要逻辑是不是在一起,这得另说。只说“顿”的情况,它的发生是因为这个点不可能到达,则我们强大的A*寻路把所有的点全部找个遍,实际情况则是这样的:在4000x3000的地图上,寻路循环进行了30万次,才只是找到一个近似路径而已,我们将这个部分做了修改,将寻路缩小到指定范围,如果超过这个范围则不在进行寻路,图例表示如下:
只对设定的范围内进行搜索,这也是比限定搜索长度要容易的方式,我尝试使用限定搜索的总长度,但是不怎么好,对于A*的算法代码改动太大,而使用设定范围,只需要在超出范围时候控制好即可。
关于直接寻路,我们会得到一个很不自然的路径,那么为什么不先进行直线行走,走到特定位置然后再按按照寻路点走呢,我们的项目中是这样的解决的,先使用向量计算,然后判定按照步长上的每个点是否在不可达点上,当出现这种情况,则调用寻路,虽然不能达到100%的平滑寻路,但是对于普通的行走已经足够应付,会走一个相对很爽的路径。
可能上述写的很杂乱,表述的问题其实很简单,有的时候我们研究和优化很多的代码,都是存在于实验室——一个完美的环境,而在真实环境将面临着用户乱点一通,或者提出为什么不是很平滑的移动的问题,这些问题有可能让我们需要将路重走一遍,而本篇则是我们项目当中的一篇更新邮件子内容。
public List<Point> GetPath(double sx, double sy, double ex, double ey) { double vx = ex - sx; double vy = ey - sy; double mm = Math.Sqrt(vx * vx + vy * vy); vx = (vx / mm) * CGRoot.MapGridSize; vy = (vy / mm) * CGRoot.MapGridSize; List<Point> bufft = new List<Point>(); while (true) { if (Math.Sqrt((ex - sx) * (ex - sx) + (ey - sy) * (ey - sy)) < CGRoot.MapGridSize) { return bufft; } int x = (int)(sx / CGRoot.MapGridSize + vx); int y = (int)(sy / CGRoot.MapGridSize + vy); if (x >= m_MapData_Rank_Width) x = m_MapData_Rank_Width - 1; else if (x < 0) x = 0; if (y >= m_MapData_Rank_Height) y = m_MapData_Rank_Height - 1; else if (y < 0) y = 0; if (m_MapObstruct[y, x] == 0) { sx += vx; sy += vy; bufft.Add(new Point(sx, sy)); } else { break; } } //到此为止找到了一条通向目标点的直线,如果是直线,那么下面的不会进行 //如果不是,则会在停止的障碍点上开始寻路,直到目标 List<Point> buff = base.GetPath((int)sx / CGRoot.MapGridSize, (int)sy / CGRoot.MapGridSize, (int)ex / CGRoot.MapGridSize, (int)ey / CGRoot.MapGridSize); for (int i = 0; i < buff.Count; i++) { bufft.Add(new Point(buff[i].X * CGRoot.MapGridSize, buff[i].Y * CGRoot.MapGridSize)); } return bufft; }
关于限定范围中的部分写在寻路算法当中,由于代码过长,只能节选一部分
//在限定范围内进行处理,所以我们在处理之前就看是否是超出了范围。 off_x += father.x; off_y += father.y; if ((off_x < 0) || (off_x >= this.mapW) || (off_x < _rangeMinX) || (off_x >= _rangeMaxX)) { return false; } if ((off_y < 0) || (off_y >= this.mapH) || (off_y < _rangeMinY) || (off_y >= _rangeMaxY)) { return false; } if (this.map[off_x, off_y].block) { return false; } //下面的代码属于另外一个部分,类的成员,作为判定的限定参数 private static int maxFinderW = 50; private static int maxFinderH = 40; private int _rangeMinX = 0; private int _rangeMinY = 0; private int _rangeMaxX = 1; private int _rangeMaxY = 1; private int _sx { set { _rangeMinX = value - maxFinderW; _rangeMaxX = value + maxFinderW; } } private int _sy { set { _rangeMinY = value - maxFinderH; _rangeMaxY = value + maxFinderH; } }
相关文章推荐
- 开发ing经验关于游戏中寻路
- 关于游戏开发中的A*/A-star的寻路算法的问题
- 关于android游戏开发的一些基础和个人经验
- 开发者经验谈:如何一天时间搞定iOS游戏开发?
- Silverlight C# 游戏开发:关于精灵for Silverlight容器
- 【iOS-Cocos2d游戏开发】关于CCSpriteSheet报错问题
- unity3d开发2d游戏关于Assetbundle的使用
- 关于跨语言联合开发接口的经验(非技术,提交工作效率)
- Windows Phone 7 XNA开发之关于游戏组件 推荐
- 关于J2ME手机游戏开发的一些个人思考之起步篇
- 关于游戏开发中的碰撞检测(转)
- 关于怎样搭建HLML5游戏开发框架的方法
- Flash网络游戏开发入门经验共享
- 一名资深大牛10年时间总结出的一些有关于Java软件开发的经验
- 【Android2D游戏开发十五】关于Android 游戏开发中 OnTouchEvent() 触屏事件的性能优化笔记!
- 非专业游戏开发团队失败经验谈
- 关于Unity游戏开发方向找工作方面的一些个人看法
- 【Android开发经验】关于dip、dpi和分辨率的一些事
- 关于游戏开发的客户端/服务器端的版本控制
- Windows8 游戏开发教程-二、关于资源和工具(转)