bool Intersects(CCRect first, RectWithDirection second) { //判断两个rect是否有重叠 return first.UpperRight.X > second.Left && first.LowerLeft.X < second.Left + second.Width && first.UpperRight.Y > second.Bottom && first.LowerLeft.Y < second.Bottom + second.Height; }
public void PopulateFrom(CCTileMap tileMap) { //得到瓦片地图里面的瓦片信息,比如说哪些瓦片可以与entity接触,具体是瓦片的哪个方向的面可以接触 collisions=new List<RectWithDirection> (); //每个小瓦片的边长加上0.5,这样碰撞时就不会陷进去才弹出 tileDimensionWidth = (int)(tileMap.TileTexelSize.Width + .5f); tileDimensionHeight = (int)(tileMap.TileTexelSize.Height + .5f); mBrickLayer = tileMap.LayerNamed ("BrickLayer"); TileMapPropertyFinder finder = new TileMapPropertyFinder (tileMap); foreach (var propertyLocation in finder.GetPropertyLocations()) { //如果在这个位置的瓦片是一个固体 if (propertyLocation.Properties.ContainsKey ("SolidCollision")) { //worldX worldY 是每个瓦片的中心的坐标 float centerX = propertyLocation.WorldX; float centerY = propertyLocation.WorldY; //得到每个小瓦片的左边界和下边界 float left = centerX - tileDimensionWidth/2.0f; float bottom = centerY - tileDimensionHeight/2.0f; //在那个点构造一个小瓦片 RectWithDirection rectangle = new RectWithDirection { Left = left, Bottom = bottom, Width = tileDimensionWidth, Height = tileDimensionHeight, tiledMapCoordinate=propertyLocation.TileCoordinates }; //得到地图上所有的固体小块 collisions.Add (rectangle); } } // Sort by XAxis to speed future searches: //collisions是把整个瓦片地图按每个瓦片的左边的坐标进行排序的list //在每一个左边坐标有一列的瓦片 //debug看一下 collisions = collisions.OrderBy(item=>item.Left).ToList(); // now let's adjust the directions that these point //调整每个小块的角度 for (int i = 0; i < collisions.Count; i++) { var rect = collisions [i]; // By default rectangles can reposition objects in all directions: int valueToAssign = (int)Directions.All; //15 float centerX = rect.CenterX; float centerY = rect.CenterY; // If there are collisions on the sides, then this // rectangle can no longer repositon objects in that direction. // 一开始小瓦片的方向valueToAssign可能是所有的方向,每次减去一种不可能的方向值,最后得到的就是正确的方向的值的和 //direction是这个实体瓦片暴露在外,可以与entity接触的方向 //比如说瓦片地图里的地面,方向就为up if (HasCollisionAt (centerX - tileDimensionWidth, centerY)) { valueToAssign -= (int)Directions.Left; } if (HasCollisionAt (centerX + tileDimensionWidth, centerY)) { valueToAssign -= (int)Directions.Right; } if (HasCollisionAt (centerX, centerY + tileDimensionHeight)) { valueToAssign -= (int)Directions.Up; } if (HasCollisionAt (centerX, centerY - tileDimensionHeight)) { valueToAssign -= (int)Directions.Down; } rect.Directions = (Directions)valueToAssign; //更新瓦片列表中的瓦片的方向 collisions [i] = rect; } for (int i = collisions.Count - 1; i > -1; i--) { //经过筛选后,遍历删除那些没有方向的瓦片 if (collisions [i].Directions == Directions.None) { collisions.RemoveAt (i); } } }
List<CCVector2> GetSeparatingVector(CCRect first, RectWithDirection second) { //返回一个向量,是player在碰撞之后反方向移动的向量 List<CCVector2> separation = new List<CCVector2> { CCVector2.Zero, CCVector2.Zero, CCVector2.Zero, CCVector2.Zero }; // Only calculate separation if the rectangles intersect if (Intersects(first, second)) { // The intersectionRect returns the rectangle produced // by overlapping the two rectangles. // This is protected by partitioning and deep collision, so it // won't happen too often - it's okay to do a ToRect here //得到两个rect重叠部分的rect var intersectionRect = first.Intersection (second.ToRect()); float minDistance = float.PositiveInfinity; float firstCenterX = first.Center.X; float firstCenterY = first.Center.Y; float secondCenterX = second.Left + second.Width / 2.0f; float secondCenterY = second.Bottom + second.Height / 2.0f; //second的方向和想要判断的方向(左)取交集,如果和想要判断的方向(左)一致,且第一个的中心点在第二个的中心点的(左边) //则当碰撞时,player可以向想要的方向移动 bool canMoveLeft = (second.Directions & Directions.Left) == Directions.Left && firstCenterX < secondCenterX; bool canMoveRight = (second.Directions & Directions.Right) == Directions.Right && firstCenterX > secondCenterX; bool canMoveDown = (second.Directions & Directions.Down) == Directions.Down && firstCenterY < secondCenterY; bool canMoveUp = (second.Directions & Directions.Up) == Directions.Up && firstCenterY > secondCenterY; if (canMoveLeft) { //左重叠 //得到重叠的rect的X方向边长 float candidate = first.UpperRight.X - second.Left; if (candidate > 0) { minDistance = candidate; //x方向移动回到地图实体瓦片的外面,y方向不动 separation [0] = new CCVector2 (-minDistance, 0); } } if (canMoveRight) { //右重叠 float candidate = (second.Left + second.Width) - first.LowerLeft.X; if (candidate > 0) { minDistance = candidate; //向右移动 separation [1] = new CCVector2 (minDistance, 0); } } //其他方向同理 if (canMoveUp) { float candidate = (second.Bottom + second.Height) - first.Origin.Y; if (candidate > 0) { minDistance = candidate; separation [2] = new CCVector2 (0, minDistance); } } if (canMoveDown) { float candidate = first.UpperRight.Y - second.Bottom; if (candidate > 0) { minDistance = candidate; separation [3] = new CCVector2 (0, -minDistance); } } if ((intersectionRect.UpperRight.X > (second.Left + first.Size.Width)) && (intersectionRect.LowerLeft.X < (second.Left + second.Width - first.Size.Width))) { separation [0] = new CCVector2 (0, 0); separation [1] = new CCVector2 (0, 0); } } //左后返回player移动的vector return separation; }