private VertexArray GenerateCliffVertices(SurfaceContainer surface, int[] pos) { VertexArray vA = new VertexArray(PrimitiveType.Triangles); int[] cXY = new int[] { pos[0] * Props.chunkSize, pos[1] * Props.chunkSize }; for (int i = 0; i < Props.chunkSize; i++) { for (int j = 0; j < Props.chunkSize; j++) { //the current tile in the loop byte currentTile = surface.GetTileFromWorldInt(pos, i, j); #region Skip tile determination if (currentTile != 0) { continue; } #endregion //hash algo int variantX = i * 266489917 + 374761393; variantX = (variantX << 17) | (variantX >> 15); variantX += j * 266489917; variantX *= 668265263; variantX ^= variantX >> 15; variantX *= 246822519; variantX = Math.Abs(variantX); //origin that vertices will be defined relative to int oX = (cXY[0] + i) * Props.tileSize; int oY = (cXY[1] + j) * Props.tileSize; int value = 0; int variant = variantX % 4; //variant is determine by whether the transition is into an impassable tile value += (surface.GetTileFromWorldInt(pos, i - 1, j - 1) != 0) ? 1 : 0; //top left value += (surface.GetTileFromWorldInt(pos, i, j - 1) != 0) ? 2 : 0; //top center value += (surface.GetTileFromWorldInt(pos, i + 1, j - 1) != 0) ? 4 : 0; //top right value += (surface.GetTileFromWorldInt(pos, i - 1, j) != 0) ? 8 : 0; //left value += (surface.GetTileFromWorldInt(pos, i + 1, j) != 0) ? 16 : 0; //right value += (surface.GetTileFromWorldInt(pos, i - 1, j + 1) != 0) ? 32 : 0; //bottom left value += (surface.GetTileFromWorldInt(pos, i, j + 1) != 0) ? 64 : 0; //bottom center value += (surface.GetTileFromWorldInt(pos, i + 1, j + 1) != 0) ? 128 : 0; //bottom right //Virtual mapping of surrounding tiles // 1 2 3 // 4 0 5 // 6 7 8 //bitflag values of surrounding tiles // 1 2 4 // 8 0 16 // 32 64 128 //need specific checks for if left and right exist simultaneously //if top and bottom exist simultaneously //if two corners exist (u shape) in any config //if four corners exist in any config if (value == 0) { continue; //no surrounding tiles of tiletype } if (((value & 24) + (value & 2)) == 2) { //top fade AppendQuadVerticesCliff(vA, oX, oY, 0, 0, variant, cliffShade, cliffBounds); } if (((value & 24) + (value & 64)) == 64) { //bottom fade AppendQuadVerticesCliff(vA, oX, oY, 4, 0, variant, cliffShade, cliffBounds); } if (((value & 66) + (value & 8)) == 8) { //left fade AppendQuadVerticesCliff(vA, oX, oY, 8, 0, variant, cliffShade, cliffBounds); } if (((value & 66) + (value & 16)) == 16) { //right fade AppendQuadVerticesCliff(vA, oX, oY, 12, 0, variant, cliffShade, cliffBounds); } if ((value & 10) == 10) { //inside corner topleft AppendQuadVerticesCliff(vA, oX, oY, 0, 1, variant, cliffShade, cliffBounds); } else if (((value & 1) + (value & 10)) == 1) { //outside corner topleft AppendQuadVerticesCliff(vA, oX, oY, 0, 2, variant, cliffShade, cliffBounds); } if ((value & 18) == 18) { //inside corner topright AppendQuadVerticesCliff(vA, oX, oY, 4, 1, variant, cliffShade, cliffBounds); } else if (((value & 4) + (value & 18)) == 4) { //outside corner topright AppendQuadVerticesCliff(vA, oX, oY, 4, 2, variant, cliffShade, cliffBounds); } if ((value & 72) == 72) { //inside corner bottomleft AppendQuadVerticesCliff(vA, oX, oY, 8, 1, variant, cliffShade, cliffBounds); } else if (((value & 32) + (value & 72)) == 32) { //outside corner bottomleft AppendQuadVerticesCliff(vA, oX, oY, 8, 2, variant, cliffShade, cliffBounds); } if ((value & 80) == 80) { //inside corner bottomright AppendQuadVerticesCliff(vA, oX, oY, 12, 1, variant, cliffShade, cliffBounds); } else if (((value & 128) + (value & 80)) == 128) { //outside corner bottomright AppendQuadVerticesCliff(vA, oX, oY, 12, 2, variant, cliffShade, cliffBounds); } } } return(vA); }
public PathNode GetPath(SurfaceContainer surface, Vector2 start, Vector2 target, int pathTimeout, Base.CollisionLayer unwalkableMask, Base.CollisionLayer collisionMask, float frictionFactor) { this.frictionFactor = frictionFactor; int frictionMask = (int)(collisionMask & Base.CollisionLayer.Terrain); //a nonzero value means the pathcost is higher for lower frictions frictionMask = frictionMask / (1 + frictionMask); //Normalize the frictionmask to 0 or 1 using +1 trick int[] startCoords = surface.WorldToAbsoluteTileCoords(start.x, start.y); int[] endCoords = surface.WorldToAbsoluteTileCoords(target.x, target.y); float heuristic = CalculateHeuristic(startCoords, endCoords); PathNode startNode = new PathNode(null, 0, 0, heuristic, startCoords); List <PathNode> openList = new List <PathNode>(); List <PathNode> closedList = new List <PathNode>(); PathNode endNode = null; openList.Add(startNode); while (openList.Count > 0 && pathTimeout > 0) { pathTimeout--; PathNode curNode = null; int removeIndex = 0; for (int i = 0; i < openList.Count; i++) { if (curNode == null || openList[i].cost < curNode.cost) { removeIndex = i; curNode = openList[i]; } } openList.RemoveAt(removeIndex); closedList.Add(curNode); if (pathTimeout == 0 || (curNode.coords[0] == endCoords[0] && curNode.coords[1] == endCoords[1])) { endNode = curNode; break; } for (int i = curNode.coords[0] - 1; i <= curNode.coords[0] + 1; i++) { for (int j = curNode.coords[1] - 1; j <= curNode.coords[1] + 1; j++) { bool ignore = false; if (i < 0 || j < 0) //Check if coords are outside worldSize { ignore = true; } if (ignore == false) //else check that coords are not already in closedList { for (int k = 0; k < closedList.Count; k++) { if (closedList[k].coords[0] == i && closedList[k].coords[1] == j) { ignore = true; break; } } } if (ignore == false) //else check that coords are not already in openList { for (int k = 0; k < openList.Count; k++) { if (openList[k].coords[0] == i && openList[k].coords[1] == j) { ignore = true; break; } } } if (!ignore) //if neither of the preceding conditiosn set ignore to false, add tile to open list on path search { Tile tile = tileCollection.GetTerrainTile(surface.GetTileFromWorldInt(i, j)); int solidMask = (int)((unwalkableMask & collisionMask) & tile.collisionMask); // a zero value when the tile is walkable if (solidMask == 0) { int[] coords = new int[] { i, j }; PathNode newNode = new PathNode(curNode, frictionMask * (frictionFactor * (1 / tile.frictionModifier)), curNode.begin + 1, CalculateHeuristic(coords, endCoords), coords); openList.Add(newNode); } } } } } return(endNode); }
public VertexArray[] GenerateTerrainVertices(SurfaceContainer surface, int[] pos) { VertexArray[] terrainVertexArray = new VertexArray[terrainTiles.Count]; terrainVertexArray[0] = GenerateCliffVertices(surface, pos); for (int curType = 1; curType < terrainTiles.Count; curType++) { Tile tile = terrainTiles[curType]; terrainVertexArray[curType] = new VertexArray(PrimitiveType.Triangles); int[] cXY = new int[] { pos[0] * Props.chunkSize, pos[1] * Props.chunkSize }; for (int i = 0; i < Props.chunkSize; i++) { for (int j = 0; j < Props.chunkSize; j++) { //the current tile in the loop byte currentTile = surface.GetTileFromWorldInt(pos, i, j); if (currentTile > curType) { continue; } //hash algo int variantX = i * 266489917 + 374761393; variantX = (variantX << 17) | (variantX >> 15); variantX += j * 266489917; variantX *= 668265263; variantX ^= variantX >> 15; variantX *= 246822519; variantX = Math.Abs(variantX); //origin that vertices will be defined relative to int oX = (cXY[0] + i) * Props.tileSize; int oY = (cXY[1] + j) * Props.tileSize; #region Regular tile variant determination if (currentTile == curType) { int variantRegular = variantX % 8; //Append regular tile variation AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 0, variantRegular, tile.shade, tile.textureRect); continue; } #endregion int value = 0; int variant = variantX % 6; //variant is determine by whether the transition is into an impassable tile if (currentTile != 0 && impassableTileTypes.Contains(currentTile)) { variant += 6; } value += (surface.GetTileFromWorldInt(pos, i - 1, j - 1) == curType) ? 1 : 0; //top left value += (surface.GetTileFromWorldInt(pos, i, j - 1) == curType) ? 2 : 0; //top center value += (surface.GetTileFromWorldInt(pos, i + 1, j - 1) == curType) ? 4 : 0; //top right value += (surface.GetTileFromWorldInt(pos, i - 1, j) == curType) ? 8 : 0; //left value += (surface.GetTileFromWorldInt(pos, i + 1, j) == curType) ? 16 : 0; //right value += (surface.GetTileFromWorldInt(pos, i - 1, j + 1) == curType) ? 32 : 0; //bottom left value += (surface.GetTileFromWorldInt(pos, i, j + 1) == curType) ? 64 : 0; //bottom center value += (surface.GetTileFromWorldInt(pos, i + 1, j + 1) == curType) ? 128 : 0; //bottom right if (value == 0) { continue; //no surrounding tiles of tiletype } if (((value & 24) + (value & 2)) == 2) { //top fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 2, variant, tile.shade, tile.textureRect); } if (((value & 24) + (value & 64)) == 64) { //bottom fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 2, variant, tile.shade, tile.textureRect); } if (((value & 66) + (value & 8)) == 8) { //left fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 3, variant, tile.shade, tile.textureRect); } if (((value & 66) + (value & 16)) == 16) { //right fade AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 3, variant, tile.shade, tile.textureRect); } if ((value & 10) == 10) { //inside corner topleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 4, variant, tile.shade, tile.textureRect); } else if (((value & 1) + (value & 10)) == 1) { //outside corner topleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 6, variant, tile.shade, tile.textureRect); } if ((value & 18) == 18) { //inside corner topright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 4, variant, tile.shade, tile.textureRect); } else if (((value & 4) + (value & 18)) == 4) { //outside corner topright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 6, variant, tile.shade, tile.textureRect); } if ((value & 72) == 72) { //inside corner bottomleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 5, variant, tile.shade, tile.textureRect); } else if (((value & 32) + (value & 72)) == 32) { //outside corner bottomleft AppendQuadVertices(terrainVertexArray[curType], oX, oY, 0, 7, variant, tile.shade, tile.textureRect); } if ((value & 80) == 80) { //inside corner bottomright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 5, variant, tile.shade, tile.textureRect); } else if (((value & 128) + (value & 80)) == 128) { //outside corner bottomright AppendQuadVertices(terrainVertexArray[curType], oX, oY, 12, 7, variant, tile.shade, tile.textureRect); } } } } return(terrainVertexArray); }