• 游戏之寻路算法


          玩游戏的人,都知道游戏中有自动寻路功能,鼠标点击想要到达的终点,主角则会自动走最短的一条路当然同时躲避障碍物,好了,不用多说,直接看效果吧(直观)。

         

         绿色表示起点,红色表示终点,蓝色表示障碍物,而会动的表示从起点运动到终点的轨迹。

         上面用的是寻路算法之曼哈顿算法,具体的表述可以参看http://hi.baidu.com/myfcag/blog/item/48bd91fd012a0bf6fd037fc5.html。别人翻译的很好,完全可以根据他的表述实现自己的寻路算法。下面再贴一张游戏的截面(特别申明:中的素材全部来源于网络 )

        

         截图的效果不太好,不过可以看到主角在后面的移动中可以穿过草丛,因为这里还没加上障碍物的定位和寻路代码,这一部分主要是看看效果,在以后的时间里会贴出完整的代码。(是不是发现游戏的人物是仙剑二中的主角,仙剑经典啊!)

        贴上完整的寻路代码(下面的代码加入了一些在实际应用中的限制程序,理解主要的思想就OK了):

    代码
            /// <summary>
            
    /// 寻路
            
    /// </summary>
            public List<Point> PathFinding(Point startPos, Point endPos)
            {
                List
    <Point> ps = new List<Point>();
                
    int width = Matrix.GetLength(0);
                
    int height = Matrix.GetLength(1);
                
    //起点
                startEB = new Entity(startPos);
                startEB.Par 
    = null;
                
    //终点
                endEB = new Entity(endPos);
                
    //起点加入到开始列表中
                startList.Add(startEB.Pos, startEB);

                Entity s 
    = startList[startEB.Pos]; //起点

                
    if (s.Pos == endEB.Pos) return ps;

                
    //起点的八方向(为代码方便阅读,将8个方向单独处理)
                Entity temp = new Entity();
                Point point 
    = new Point();
                
    bool upBarrier = false;
                
    bool downBarrier = false;
                
    bool leftBarrier = false;
                
    bool rightBarrier = false;
                
    while (s != null)
                {
                    
    #region 初始化
                    upBarrier 
    = false;
                    downBarrier 
    = false;
                    leftBarrier 
    = false;
                    rightBarrier 
    = false;
                    
    #endregion

                    
    //****右
                    point = new Point(s.Pos.X + 1, s.Pos.Y);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!startList.ContainsKey(point))
                        {
                            temp 
    = new Entity(point); //(*待判断是否越界)
                            temp.Par = s;
                            temp.G 
    = 1;
                            temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                            temp.F 
    = temp.G + temp.H;
                            startList.Add(point, temp);
                        }
                        
    else //格子已经包括在开始列表中
                        {
                            Entity exist 
    = startList[point];
                            
    if (s.G + 1 < exist.G)
                            {
                                exist.Par 
    = s;
                                exist.G 
    = 1;
                                exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                exist.F 
    = exist.G + exist.H;
                            }
                        }
                    }
                    
    else
                    {
                        
    if (barrier.ContainsKey(point)) //右边有障碍物
                        {
                            rightBarrier 
    = true;
                        }
                    }

                    
    //****上
                    point = new Point(s.Pos.X, s.Pos.Y - 1);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!startList.ContainsKey(point))
                        {
                            temp 
    = new Entity(point);
                            temp.Par 
    = s;
                            temp.G 
    = 1;
                            temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                            temp.F 
    = temp.G + temp.H;
                            startList.Add(point, temp);
                        }
                        
    else
                        {
                            Entity exist 
    = startList[point];
                            
    if (s.G + 1 < exist.G)
                            {
                                exist.Par 
    = s;
                                exist.G 
    = 1;
                                exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                exist.F 
    = exist.G + exist.H;
                            }
                        }
                    }
                    
    else
                    {
                        
    if (barrier.ContainsKey(point)) //上边有障碍物
                        {
                            upBarrier 
    = true;
                        }
                    }

                    
    //****左
                    point = new Point(s.Pos.X - 1, s.Pos.Y);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!startList.ContainsKey(point))
                        {
                            temp 
    = new Entity(point);
                            temp.Par 
    = s;
                            temp.G 
    = 1;
                            temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                            temp.F 
    = temp.G + temp.H;
                            startList.Add(point, temp);
                        }
                        
    else
                        {
                            Entity exist 
    = startList[point];
                            
    if (s.G + 1 < exist.G)
                            {
                                exist.Par 
    = s;
                                exist.G 
    = 1;
                                exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                exist.F 
    = exist.G + exist.H;
                            }
                        }
                    }
                    
    else
                    {
                        
    if (barrier.ContainsKey(point))  //左边有障碍物
                        {
                            leftBarrier 
    = true;
                        }
                    }

                    
    //****下
                    point = new Point(s.Pos.X, s.Pos.Y + 1);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!startList.ContainsKey(point))
                        {
                            temp 
    = new Entity(point);
                            temp.Par 
    = s;
                            temp.G 
    = 1;
                            temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                            temp.F 
    = temp.G + temp.H;
                            startList.Add(point, temp);
                        }
                        
    else
                        {
                            Entity exist 
    = startList[point];
                            
    if (s.G + 1 < exist.G)
                            {
                                exist.Par 
    = s;
                                exist.G 
    = 1;
                                exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                exist.F 
    = exist.G + exist.H;
                            }
                        }
                    }
                    
    else
                    {
                        
    if (barrier.ContainsKey(point))
                        {
                            downBarrier 
    = true;
                        }
                    }

                    
    //****右上
                    point = new Point(s.Pos.X + 1, s.Pos.Y - 1);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!rightBarrier && !upBarrier)
                        {
                            
    if (!startList.ContainsKey(point))
                            {
                                temp 
    = new Entity(new Point(s.Pos.X + 1, s.Pos.Y - 1));
                                temp.Par 
    = s;
                                temp.G 
    = 1.4;
                                temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                temp.F 
    = temp.G + temp.H;
                                startList.Add(point, temp);
                            }
                            
    else
                            {
                                Entity exist 
    = startList[point];
                                
    if (s.G + 1.4 < exist.G)
                                {
                                    exist.Par 
    = s;
                                    exist.G 
    = 1.4;
                                    exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                    exist.F 
    = exist.G + exist.H;
                                }
                            }
                        }
                    }

                    
    //****右下
                    point = new Point(s.Pos.X + 1, s.Pos.Y + 1);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!rightBarrier && !downBarrier)
                        {
                            
    if (!startList.ContainsKey(point))
                            {
                                temp 
    = new Entity(point);
                                temp.Par 
    = s;
                                temp.G 
    = 1.4;
                                temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                temp.F 
    = temp.G + temp.H;
                                startList.Add(point, temp);
                            }
                            
    else
                            {
                                Entity exist 
    = startList[point];
                                
    if (s.G + 1.4 < exist.G)
                                {
                                    exist.Par 
    = s;
                                    exist.G 
    = 1.4;
                                    exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                    exist.F 
    = exist.G + exist.H;
                                }
                            }
                        }
                    }

                    
    //****左上
                    point = new Point(s.Pos.X - 1, s.Pos.Y - 1);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!leftBarrier && !upBarrier)
                        {
                            
    if (!startList.ContainsKey(point))
                            {
                                temp 
    = new Entity(point);
                                temp.Par 
    = s;
                                temp.G 
    = 1.4;
                                temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                temp.F 
    = temp.G + temp.H;
                                startList.Add(point, temp);
                            }
                            
    else
                            {
                                Entity exist 
    = startList[point];
                                
    if (s.G + 1.4 < exist.G)
                                {
                                    exist.Par 
    = s;
                                    exist.G 
    = 1.4;
                                    exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                    exist.F 
    = exist.G + exist.H;
                                }
                            }
                        }
                    }

                    
    //****左下
                    point = new Point(s.Pos.X - 1, s.Pos.Y + 1);
                    
    if (!barrier.ContainsKey(point) && !closeList.ContainsKey(point) && (point.X < width && point.Y < height)) //排除障碍物
                    {
                        
    if (!leftBarrier && !downBarrier)
                        {
                            
    if (!startList.ContainsKey(point))
                            {
                                temp 
    = new Entity(point);
                                temp.Par 
    = s;
                                temp.G 
    = 1.4;
                                temp.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                temp.F 
    = temp.G + temp.H;
                                startList.Add(point, temp);
                            }
                            
    else
                            {
                                Entity exist 
    = startList[point];
                                
    if (s.G + 1.4 < exist.G)
                                {
                                    exist.Par 
    = s;
                                    exist.G 
    = 1.4;
                                    exist.H 
    = Math.Abs(point.X - endEB.Pos.X) + Math.Abs(point.Y - endEB.Pos.Y);
                                    exist.F 
    = exist.G + exist.H;
                                }
                            }
                        }
                    }

                    
    //从开始列表中删除起点,并将其加到关闭列表中
                    if (startList.ContainsKey(s.Pos))
                    {
                        startList.Remove(s.Pos);
                    }
                    
    if (!closeList.ContainsKey(s.Pos))
                    {
                        closeList.Add(s.Pos, s);
                    }

                    
    //寻找F值最低的
                    double fMin = Double.MaxValue ;
                    
    foreach (KeyValuePair<Point, Entity> key in startList)
                    {
                        
    if (key.Value.F <= fMin)
                        {
                            fMin 
    = key.Value.F;
                            temp 
    = key.Value;
                        }
                    }

                    
    //将最低的从开始列表中删除,加载到关闭列表中 
                    if (startList.ContainsKey(temp.Pos))
                    {
                        startList.Remove(temp.Pos);
                    }
                    
    if (!closeList.ContainsKey(temp.Pos))
                    {
                        closeList.Add(temp.Pos, temp);
                    }

                    
    //判断是否需要继续查找
                    if (closeList.ContainsKey(endEB.Pos) || startList.Count <= 0)
                    {
                        
    //如果F值最低的点就是目标点,停止查找
                        s = null;
                    }
                    
    else
                    {
                        s 
    = temp;
                    }
                }

                
    //返回值
                return ps;
            }

           由于实际需要,在代码中加了少许的修改,理解主要实现的思路即可!!!

  • 相关阅读:
    UML建模语言
    iOS 键盘挡住UITextField
    IOS架构师之路:我对IOS架构的点点认识(大纲)
    自己动手写处理器之第四阶段(1)——第一条指令ori的实现
    【Android Studio】studio学习系列(一) 从eclipse导入project
    Android二维码开源项目zxing编译
    第九十六题(编写strcpy 函数)
    oracle子查询
    打印池
    咏南中间件和开发框架介绍文档下载
  • 原文地址:https://www.cnblogs.com/wangyong/p/1699510.html
Copyright © 2020-2023  润新知