//垂直碰撞检测:原理同上 public static TerrainCollisionData VerticalCollision(Room room, TerrainCollisionData cd) { IntVector2 lastTile = room.GetTilePosition(cd.lastPos); int count = 0; //速度大于0:向上移动 if (cd.vel.y > 0.0) { int y1 = room.GetTilePosition(new Vector2(0.0f, (float)(cd.pos.y + (double)cd.rad))).y; int y2 = room.GetTilePosition(new Vector2(0.0f, cd.lastPos.y + cd.rad)).y; int x1 = room.GetTilePosition(new Vector2((float)(cd.pos.x - (double)cd.rad + 1.0), 0.0f)).x; int x2 = room.GetTilePosition(new Vector2((float)(cd.pos.x + (double)cd.rad - 1.0), 0.0f)).x; bool @checked = false; for (int y = y2; y <= y1 && !@checked; ++y) { for (int x = x1; x <= x2 && !@checked; ++x) { if (room.GetTile(x, y).Terrain == Room.Tile.TerrainType.Solid && room.GetTile(x, y - 1).Terrain != Room.Tile.TerrainType.Solid && (lastTile.y < y || room.GetTile(cd.lastPos).Terrain == Room.Tile.TerrainType.Solid)) { cd.pos.y = y * 20f - cd.rad; cd.vel.y = 0.0f; cd.contactPoint.y = 1; @checked = true; } ++count; if (count > MaxRepeats) { Debug.Log("!!!!! sharedphysics emergency breakout of terrain check!"); @checked = true; } } } } //速度小于0:向下移动 else if (cd.vel.y < 0.0) { int y1 = room.GetTilePosition(new Vector2(0.0f, (float)(cd.pos.y - (double)cd.rad))).y; int y2 = room.GetTilePosition(new Vector2(0.0f, cd.lastPos.y - cd.rad)).y; int x1 = room.GetTilePosition(new Vector2((float)(cd.pos.x - (double)cd.rad + 1.0), 0.0f)).x; int x2 = room.GetTilePosition(new Vector2((float)(cd.pos.x + (double)cd.rad - 1.0), 0.0f)).x; bool @checked = false; for (int y = y2; y >= y1 && !@checked; --y) { for (int x = x1; x <= x2 && !@checked; ++x) { if (SolidFloor(room, x, y, cd.goThroughFloors, cd.lastPos) && !SolidFloor(room, x, y + 1, cd.goThroughFloors, cd.lastPos) && (lastTile.y > y || room.GetTile(cd.lastPos).Terrain == Room.Tile.TerrainType.Solid)) { cd.pos.y = (float)((y + 1.0) * 20.0) + cd.rad; cd.vel.y = 0.0f; cd.contactPoint.y = -1; @checked = true; } ++count; if (count > MaxRepeats) { Debug.Log("!!!!! sharedphysics emergency breakout of terrain check!"); @checked = true; } } } } return(cd); }
public static TerrainCollisionData SlopesVertically(Room room, TerrainCollisionData cd) { IntVector2 tilePos = room.GetTilePosition(cd.pos); IntVector2 intVec = new IntVector2(0, 0); Room.SlopeDirection slopeDir = room.IdentifySlope(cd.pos); //如果目标地形不是Slope if (room.GetTile(cd.pos).Terrain != Room.Tile.TerrainType.Slope) { //左边Tile斜坡类型不是Broken && 碰撞体与左边Tile发生碰撞:(碰撞体Center - 碰撞半径).X < 当前Tile边界Pos.X if (room.IdentifySlope(tilePos.x - 1, tilePos.y) != Room.SlopeDirection.Broken && cd.pos.x - (double)cd.rad <= room.MiddleOfTile(cd.pos).x - 10.0) { slopeDir = room.IdentifySlope(tilePos.x - 1, tilePos.y); intVec.x = -1; } //右边检测同上 else if (room.IdentifySlope(tilePos.x + 1, tilePos.y) != Room.SlopeDirection.Broken && cd.pos.x + (double)cd.rad >= room.MiddleOfTile(cd.pos).x + 10.0) { slopeDir = room.IdentifySlope(tilePos.x + 1, tilePos.y); intVec.x = 1; } //下边检测同上 else if (cd.pos.y - (double)cd.rad < room.MiddleOfTile(cd.pos).y - 10.0 && room.IdentifySlope(tilePos.x, tilePos.y - 1) != Room.SlopeDirection.Broken) { slopeDir = room.IdentifySlope(tilePos.x, tilePos.y - 1); intVec.y = -1; } //上边检测同上 else if (cd.pos.y + (double)cd.rad > room.MiddleOfTile(cd.pos).y + 10.0 && room.IdentifySlope(tilePos.x, tilePos.y + 1) != Room.SlopeDirection.Broken) { slopeDir = room.IdentifySlope(tilePos.x, tilePos.y + 1); intVec.y = 1; } } //如果斜坡类型不是损坏类型 if (slopeDir != Room.SlopeDirection.Broken) { //得到碰撞的tile Vector2 tile = room.MiddleOfTile(room.GetTilePosition(cd.pos) + intVec); float dist; int sign; switch (slopeDir) { //上左、上右斜坡,碰撞由上到下 case Room.SlopeDirection.UpLeft: dist = (float)(cd.pos.x - (tile.x - 10.0) + (tile.y - 10.0)); sign = -1; break; case Room.SlopeDirection.UpRight: dist = (float)(20.0 - (cd.pos.x - (tile.x - 10.0)) + (tile.y - 10.0)); sign = -1; break; case Room.SlopeDirection.DownLeft: dist = (float)(20.0 - (cd.pos.x - (tile.x - 10.0)) + (tile.y - 10.0)); sign = 1; break; default: dist = (float)(cd.pos.x - (tile.x - 10.0) + (tile.y - 10.0)); sign = 1; break; } if (sign == -1 && cd.pos.y <= dist + (double)cd.rad + cd.rad) { cd.pos.y = dist + cd.rad + cd.rad; } else if (sign == 1 && cd.pos.y >= dist - (double)cd.rad - cd.rad) { cd.pos.y = dist - cd.rad - cd.rad; } } return(cd); }
//水平碰撞检测 public static TerrainCollisionData HorizontalCollision(Room room, TerrainCollisionData cd) { //获取前一帧Tile位置 IntVector2 lastTile = room.GetTilePosition(cd.lastPos); int count = 0; //速度大于零:向右移动 if (cd.vel.x > 0.0) { //获取当前帧、前一帧(位置+半径)的Tile信息 int x1 = room.GetTilePosition(new Vector2(cd.pos.x + cd.rad, 0.0f)).x; int x2 = room.GetTilePosition(new Vector2(cd.lastPos.x + cd.rad, 0.0f)).x; int y1 = room.GetTilePosition(new Vector2(0.0f, (float)(cd.pos.y + (double)cd.rad - 1.0))).y; int y2 = room.GetTilePosition(new Vector2(0.0f, (float)(cd.pos.y - (double)cd.rad + 1.0))).y; bool @checked = false; //从左到右、从上到下遍历地形 for (int x = x2; x <= x1 && !@checked; ++x) { for (int y = y2; y <= y1 && !@checked; ++y) { if (room.GetTile(x, y).Terrain == Room.Tile.TerrainType.Solid && room.GetTile(x - 1, y).Terrain != Room.Tile.TerrainType.Solid && (lastTile.x < x || room.GetTile(cd.lastPos).Terrain == Room.Tile.TerrainType.Solid)) { //修改碰撞数据 cd.pos.x = x * 20f - cd.rad; cd.vel.x = 0.0f; cd.contactPoint.x = 1; @checked = true; } //碰撞次数阈值检测 ++count; if (count > MaxRepeats) { Debug.Log("!!!!! sharedphysics emergency breakout of terrain check!"); @checked = true; } } } } //速度小于零:向左移动 : 检测方式同上 else if (cd.vel.x < 0.0) { int x1 = room.GetTilePosition(new Vector2(cd.pos.x - cd.rad, 0.0f)).x; int x2 = room.GetTilePosition(new Vector2(cd.lastPos.x - cd.rad, 0.0f)).x; int y1 = room.GetTilePosition(new Vector2(0.0f, (float)(cd.pos.y + cd.rad - 1.0))).y; int y2 = room.GetTilePosition(new Vector2(0.0f, (float)(cd.pos.y - cd.rad + 1.0))).y; bool @checked = false; for (int x = x2; x >= x1 && !@checked; --x) { for (int y = y2; y <= y1 && !@checked; ++y) { if (room.GetTile(x, y).Terrain == Room.Tile.TerrainType.Solid && room.GetTile(x + 1, y).Terrain != Room.Tile.TerrainType.Solid && (lastTile.x > x || room.GetTile(cd.lastPos).Terrain == Room.Tile.TerrainType.Solid)) { cd.pos.x = (float)((x + 1.0) * 20.0) + cd.rad; cd.vel.x = 0.0f; cd.contactPoint.x = -1; @checked = true; } ++count; if (count > MaxRepeats) { Debug.Log("!!!!! sharedphysics emergency breakout of terrain check!"); @checked = true; } } } } return(cd); }