zoukankan      html  css  js  c++  java
  • 格子寻路

    package dc.framework.pathfinder.grid
    {
    	import dc.framework.pathfinder.PathGrid;
    	import dc.framework.pathfinder.PathGridMap;
    	
    	import flash.geom.Rectangle;
    
    	/**
    	 * 键盘走路
    	 * @anchor hannibal
    	 * 2013-10-30下午6:09:30
    	 */	
    	public class GridPathfinder
    	{
    		static private var m_instance:GridPathfinder;
    		/**
    		 * 寻路时的步长 
    		 */		
    		static public const STEP_LENGTH:uint = 4;
    		static public const NEARST_STEP:int = 15;
    		/**
    		 * 寻路成功时的目标点 
    		 */		
    		private var m_targetPos_X:Number;
    		private var m_targetPos_Y:Number;
    		
    		private var m_last_pos_x:Number;
    		private var m_last_pos_y:Number;
    		
    		private var m_temp_collide_rect:Rectangle;
    		//TODO:test
    		//private var m_shape:Shape;
    		
    		//1-right;2-down;3-left;4-up
    		private var m_walkDir:int = 0;
    		
    		/**地图障碍数据*/
    		private var m_grid_map:PathGridMap = null; 
    		private var m_cur_grid:PathGrid = null;
    		/**************************************************************************/
    		/*公共方法																  */
    		/**************************************************************************/
    		public function GridPathfinder()
    		{
    			m_temp_collide_rect = new Rectangle();
    			m_targetPos_X = 0;
    			m_targetPos_Y = 0;
    		}
    		static public function get instance():GridPathfinder
    		{
    			if(m_instance == null)
    			{
    				m_instance = new GridPathfinder();
    			}
    			return m_instance;
    		}
    		public function setup(grid_map:PathGridMap):void
    		{
    			m_grid_map = grid_map; 
    			
    			m_targetPos_X = 0;
    			m_targetPos_Y = 0;
    		}
    		
    		public function destroy():void
    		{
    			
    		}
    		
    		/**
    		 * 寻路接口 
    		 * @param cur_x
    		 * @param cur_y
    		 * @param target_x
    		 * @param target_y
    		 * @param walkDir
    		 * @return 
    		 * 
    		 */		
    		public function search(cur_x:Number, cur_y:Number, target_x:Number, target_y:Number, Number, height:Number):Boolean
    		{
    			if(m_grid_map == null)
    			{
    				return false;
    			}
    			m_walkDir = 0;
    			m_cur_grid = null;
    			
    			//步长个数
    			var stepCount:int = 0;
    			
    			//上一步的位置
    			m_last_pos_x = cur_x;
    			m_last_pos_y = cur_y;
    			
    			//步长增长方向
    			var x_step_inc:Number = 0;
    			var y_step_inc:Number = 0;
    			
    			var i:int;
    			var bFind:Boolean = false;
    			
    			//上下
    			if(Math.abs(cur_y - target_y) > Math.abs(cur_x - target_x))
    			{
    				//上
    				if(cur_y > target_y)
    				{
    					stepCount = Math.abs(cur_y - target_y)/STEP_LENGTH;//TODO,存在误差,不过为了速度,先忽视
    					y_step_inc = -STEP_LENGTH;
    					m_walkDir = 4;
    				}
    				else//下
    				{
    					stepCount = Math.abs(cur_y - target_y)/STEP_LENGTH;
    					y_step_inc = STEP_LENGTH;
    					m_walkDir = 2;
    				}
    			}
    				//左右
    			else
    			{
    				//左
    				if(cur_x > target_x)
    				{
    					stepCount = Math.abs(cur_x - target_x)/STEP_LENGTH;
    					x_step_inc = -STEP_LENGTH;	
    					m_walkDir = 3;
    				}
    				else//右
    				{
    					stepCount = Math.abs(cur_x - target_x)/STEP_LENGTH;
    					x_step_inc = STEP_LENGTH;	
    					m_walkDir = 1;
    				}
    			}
    			m_temp_collide_rect.width = width;
    			m_temp_collide_rect.height = height;
    			
    			m_cur_grid = m_grid_map.getNodeByPostion(cur_x, cur_y);
    			if(m_cur_grid == null)
    			{
    				return false;
    			}
    			
    			//开始寻路,每次移动一个步长
    			for(i=1; i<stepCount; i++)//从1开始,当前位置不判断
    			{
    				if(_isWalkableRect(cur_x+x_step_inc*i, cur_y+y_step_inc*i))
    				{
    					m_last_pos_x=cur_x + x_step_inc*i;
    					m_last_pos_y=cur_y + y_step_inc*i;
    					
    					bFind = true;
    				}
    				else
    				{
    					if(i == 1)
    					{//第一步就不能走:找最优路径
    						bFind = findNearestPath(cur_x, cur_y, cur_x + x_step_inc, cur_y + y_step_inc, stepCount);
    					}
    					m_targetPos_X = m_last_pos_x;
    					m_targetPos_Y = m_last_pos_y;
    					
    					break;
    				}
    			}
    			if(bFind && i==stepCount)
    			{
    				m_targetPos_X = m_last_pos_x;
    				m_targetPos_Y = m_last_pos_y;
    			}
    			return bFind;
    		}
    		
    		/**************************************************************************/
    		/*公共属性																  */
    		/**************************************************************************/
    		public function getTargetPos_X():Number
    		{
    			return this.m_targetPos_X;
    		}
    		public function getTargetPos_Y():Number
    		{
    			return this.m_targetPos_Y;
    		}
    		/**************************************************************************/
    		/*私有方法																  */
    		/**************************************************************************/
    		/**
    		 * 是否可行走
    		 * @param x
    		 * @param y
    		 * @return 
    		 * 
    		 */		
    		private function _isWalkableRect(x:Number, y:Number):Boolean
    		{
    			m_temp_collide_rect.x = x - m_temp_collide_rect.width*0.5;
    			m_temp_collide_rect.y = y - m_temp_collide_rect.height*0.5/*+10*/;
    	
    			var grid:PathGrid = m_grid_map.getNodeByPostion(x, y);
    			//在障碍里面
    			if(grid == null || !grid.walkable)
    			{
    				return false;
    			}
    
    			var i:int;
    			var j:int;
    			var grid_row:int = grid.row;
    			var grid_col:int = grid.col;
    			var tempTile:PathGrid;
    			switch(m_walkDir)
    			{//1-right;2-down;3-left;4-up
    				case 1:
    					//TODO:现在没有根据人物大小和格子大小做判断
    					for(j=0; j<3; j++)
    					{
    						tempTile = m_grid_map.getNode(grid_col+1, grid_row-1+j);
    						if(tempTile == null)
    						{
    							return false;
    						}
    						if(!tempTile.walkable && tempTile.rect_collide.intersects(m_temp_collide_rect))
    						{
    							return false;
    						}
    					}
    					return true;
    					
    				case 2:
    					for(j=0; j<3; j++)
    					{
    						tempTile = m_grid_map.getNode(grid_col-1+j, grid_row+1);
    						if(tempTile == null)
    						{
    							return false;
    						}
    						if(!tempTile.walkable && tempTile.rect_collide.intersects(m_temp_collide_rect))
    						{
    							return false;
    						}
    					}
    					return true;
    					
    				case 3:
    					for(j=0; j<3; j++)
    					{
    						tempTile = m_grid_map.getNode(grid_col-1, grid_row-1+j);
    						if(tempTile == null)
    						{
    							return false;
    						}
    						if(!tempTile.walkable && tempTile.rect_collide.intersects(m_temp_collide_rect))
    						{
    							return false;
    						}
    					}
    					return true;
    					
    				case 4:
    					for(j=0; j<3; j++)
    					{
    						tempTile = m_grid_map.getNode(grid_col-1+j, grid_row-1);
    						if(tempTile == null)
    						{
    							return false;
    						}
    						if(!tempTile.walkable && tempTile.rect_collide.intersects(m_temp_collide_rect))
    						{
    							return false;
    						}
    					}
    					return true;
    			}
    			return false;
    		}
    		/**
    		 * 查找最近可通过的路径 
    		 * 
    		 */		
    		private function findNearestPath(cur_x:Number, cur_y:Number, temp_x:Number, temp_y:Number, stepCount:int):Boolean
    		{
    			var sign:int = 1;
    			var i:int = 0;
    			var j:int = 0;
    			var temp_cur_x:Number;
    			var temp_cur_y:Number;
    			var temp_last_x:Number;
    			var temp_last_y:Number;
    			switch(m_walkDir)
    			{//1-right;2-down;3-left;4-up
    				case 1:
    				case 3:
    					for(i = 0; i<NEARST_STEP; i++)
    					{
    						for(j = 0; j < 2; j++)
    						{
    							sign = -sign;
    							temp_cur_y = cur_y + sign*i*STEP_LENGTH;
    							temp_last_y = temp_y + sign*i*STEP_LENGTH;
    							if(_isWalkableRect(cur_x, temp_cur_y))
    							{
    								if(_isWalkableRect(temp_x, temp_last_y))
    								{
    									m_last_pos_x = cur_x;
    									m_last_pos_y = temp_cur_y;
    									return true;
    								}	
    							}
    							else
    							{
    								return false;
    							}
    						}
    					}
    					break;
    				
    				case 2:
    				case 4:
    					for(i = 0; i<NEARST_STEP; i++)
    					{
    						for(j = 0; j < 2; j++)
    						{
    							sign = -sign;
    							temp_cur_x = cur_x + sign*i*STEP_LENGTH;
    							temp_last_x = temp_x + sign*i*STEP_LENGTH;
    							if(_isWalkableRect(temp_cur_x, cur_y))
    							{
    								if(_isWalkableRect(temp_last_x, temp_y))
    								{
    									m_last_pos_x = temp_cur_x;
    									m_last_pos_y = temp_y;
    									return true;
    								}
    							}	
    							else
    							{
    								return false;
    							}
    						}
    					}
    					break;
    			}
    			return false;
    		}
    	}
    }
    
  • 相关阅读:
    dubbo踩坑
    windows下面使用protobuf
    解决端口占用的问题
    建设检验
    统计学资料整理
    java cpu 负载高分析
    演讲/汇报
    管理和领导
    css渐变动画
    vue组件之间互相传值:父传子,子传父
  • 原文地址:https://www.cnblogs.com/lancidie/p/3479883.html
Copyright © 2011-2022 走看看