private bool HasEdge(int x, int y, Direction dir) { Room.Tile tile = room.GetTile(x, y); Room.Tile.TerrainType terrain = tile.Terrain; Room.SlopeDirection slope = (terrain == Room.Tile.TerrainType.Slope) ? room.IdentifySlope(x, y) : Room.SlopeDirection.Broken; if (terrain == Room.Tile.TerrainType.Solid) { return(true); } if (terrain == Room.Tile.TerrainType.Air || terrain == Room.Tile.TerrainType.ShortcutEntrance || terrain == Room.Tile.TerrainType.Floor) { return(false); } switch (dir) { case Direction.Up: return(slope == Room.SlopeDirection.DownRight || slope == Room.SlopeDirection.DownLeft); case Direction.Right: return(slope == Room.SlopeDirection.UpLeft || slope == Room.SlopeDirection.DownLeft); case Direction.Down: return(slope == Room.SlopeDirection.UpRight || slope == Room.SlopeDirection.UpLeft); case Direction.Left: return(slope == Room.SlopeDirection.DownRight || slope == Room.SlopeDirection.UpRight); } return(false); }
private void AddSlopeEdge(int x, int y, Room.SlopeDirection dir) { Vector2 mid = room.MiddleOfTile(x, y); int ind1 = -1; int ind2 = -1; switch (dir) { case Room.SlopeDirection.DownLeft: case Room.SlopeDirection.UpRight: ind2 = AddCorner(new Vector2(mid.x - 10f, mid.y + 10f)); ind1 = AddCorner(new Vector2(mid.x + 10f, mid.y - 10f)); break; case Room.SlopeDirection.DownRight: case Room.SlopeDirection.UpLeft: ind1 = AddCorner(new Vector2(mid.x - 10f, mid.y - 10f)); ind2 = AddCorner(new Vector2(mid.x + 10f, mid.y + 10f)); break; } edges.Add(ind1); edges.Add(ind2); }
private void CheckAgainstSlopesVertically() { //获取当前Pos对应的Tile IntVector2 tilePos = owner.room.GetTilePosition(pos); IntVector2 intVec = new IntVector2(0, 0); //获取当前Pos斜坡类型 Room.SlopeDirection slopeDir = owner.room.IdentifySlope(pos); //如果当前Pos地形不是斜坡 if (owner.room.GetTile(pos).Terrain != Room.Tile.TerrainType.Slope) { if (owner.room.IdentifySlope(tilePos.x - 1, tilePos.y) != Room.SlopeDirection.Broken && pos.x - slopeRad <= owner.room.MiddleOfTile(pos).x - 10.0) { slopeDir = owner.room.IdentifySlope(tilePos.x - 1, tilePos.y); intVec.x = -1; } else if (owner.room.IdentifySlope(tilePos.x + 1, tilePos.y) != Room.SlopeDirection.Broken && pos.x + slopeRad >= owner.room.MiddleOfTile(pos).x + 10.0) { slopeDir = owner.room.IdentifySlope(tilePos.x + 1, tilePos.y); intVec.x = 1; } else if (pos.y - (double)slopeRad < owner.room.MiddleOfTile(pos).y - 10.0) { if (owner.room.IdentifySlope(tilePos.x, tilePos.y - 1) != Room.SlopeDirection.Broken) { slopeDir = owner.room.IdentifySlope(tilePos.x, tilePos.y - 1); intVec.y = -1; } } else if (pos.y + (double)slopeRad > owner.room.MiddleOfTile(pos).y + 10.0 && owner.room.IdentifySlope(tilePos.x, tilePos.y + 1) != Room.SlopeDirection.Broken) { slopeDir = owner.room.IdentifySlope(tilePos.x, tilePos.y + 1); intVec.y = 1; } } if (slopeDir == Room.SlopeDirection.Broken) { return; } Vector2 tempVec = owner.room.MiddleOfTile(owner.room.GetTilePosition(pos) + intVec); int xSign = 0; float dist; int ySign; switch (slopeDir) { case Room.SlopeDirection.UpLeft: xSign = -1; dist = (float)(pos.x - (tempVec.x - 10.0) + (tempVec.y - 10.0)); ySign = -1; break; case Room.SlopeDirection.UpRight: xSign = 1; dist = (float)(20.0 - (pos.x - (tempVec.x - 10.0)) + (tempVec.y - 10.0)); ySign = -1; break; case Room.SlopeDirection.DownLeft: dist = (float)(20.0 - (pos.x - (tempVec.x - 10.0)) + (tempVec.y - 10.0)); ySign = 1; break; default: dist = (float)(pos.x - (tempVec.x - 10.0) + (tempVec.y - 10.0)); ySign = 1; break; } if (ySign == -1 && pos.y <= dist + (double)slopeRad + slopeRad) { pos.y = dist + slopeRad + slopeRad; contactPoint.y = -1; vel.x *= 1f - owner.surfaceFriction; vel.x += (float)(Mathf.Abs(vel.y) * (double)Mathf.Clamp(0.5f - owner.surfaceFriction, 0.0f, 0.5f) * xSign * 0.2); vel.y = 0.0f; onSlope = xSign; slopeRad = TerrainRad - 1f; } else { if (ySign != 1 || pos.y < dist - (double)slopeRad - slopeRad) { return; } pos.y = dist - slopeRad - slopeRad; contactPoint.y = 1; vel.y = 0.0f; vel.x *= 1f - owner.surfaceFriction; slopeRad = TerrainRad - 1f; } }
public void UpdateMapper(int iterations) { Room.Tile[,] tiles = _tiles; for (int i = 0; i < iterations; i++) { switch (state) { case MappingState.FindingEdges: { Room.Tile tile = tiles[_x, _y]; Room.Tile.TerrainType terrain = tile.Terrain; Room.SlopeDirection slope = (terrain == Room.Tile.TerrainType.Slope) ? room.IdentifySlope(_x, _y) : Room.SlopeDirection.Broken; if (HasEdge(_x, _y, Direction.Left) && !HasEdge(_x - 1, _y, Direction.Right)) { AddEdge(_x, _y, Direction.Left); } if (HasEdge(_x, _y, Direction.Down) && !HasEdge(_x, _y - 1, Direction.Up)) { AddEdge(_x, _y, Direction.Down); } if (HasEdge(_x, _y, Direction.Right) && !HasEdge(_x + 1, _y, Direction.Left)) { AddEdge(_x, _y, Direction.Right); } if (HasEdge(_x, _y, Direction.Up) && !HasEdge(_x, _y + 1, Direction.Down)) { AddEdge(_x, _y, Direction.Up); } if (slope != Room.SlopeDirection.Broken) { AddSlopeEdge(_x, _y, slope); } _x++; if (_x >= room.TileWidth) { _x = 0; _y++; if (_y >= room.TileHeight) { _y = corners.Count; state = MappingState.DuplicatingPoints; } } } break; case MappingState.DuplicatingPoints: { corners.Add(corners[_x]); _x++; if (_x >= _y) { state = MappingState.Done; _x = 0; _y = 0; } } break; case MappingState.Done: return; } } }
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); }