In this section, you will be adding new code to the MapBuilder API that was created in an earlier lesson. The additional code you will add will help improve your generation algorithm so you can check neighboring tiles for specific patterns that will allow you to spawn a tile to improve the look of the map.
Add Type Enum
Having an easy way of accessing some of the tiles from the Tiles data table will help later when checking the value of a tile in the map. An Enum is a table that will have a list of values that can be accessed using a constant. For example, MapBuilder.Type.WallCorner would return the id value. This is much better than typing Tiles[3] which does not give any clue as to which tile it is. As more tiles get added to the data table, this will be far more useful.
When defining the MapBuilder table, add a new property called Type that can be set to an empty table for now.
Manually adding all the types to the Type table would be tedious. So what you can do, is loop over all the rows in the Tiles data table and add them automatically to the Type table. The key value from the row will be the key that will act as the constant, and the value will be the id from the row.
local MapBuilder = {
Type = {}
}
for key, row inpairs(TILES) do MapBuilder.Type[row.key] = row.id
endCode language:Lua(lua)
Create GetTile Function
Create a new function called GetTile. This function will receive the map, row, and column which will try to find the row and column passed in. Because there is a chance of the row or column being out of bounds, this will handle that case as well by making sure the foundRow exists.
Create a new function called GetNeighbors. This function will return a table that contains the tiles for the cardinal directions. By adding or taking away from either the row or column values, you can get the North, South, East, and West tiles from the current tile in the loop found in the Spawn function.
functionMapBuilder.GetNeighbors(map, row, column)return {
NORTH = MapBuilder.GetTile(map, row - 1, column),
SOUTH = MapBuilder.GetTile(map, row + 1, column),
EAST = MapBuilder.GetTile(map, row, column + 1),
WEST = MapBuilder.GetTile(map, row, column - 1)
}
endCode language:Lua(lua)
Create CheckForWallCorner Function
Create a new function called CheckForWallCorner. This function is going to look for a pattern by going around the cardinal directions. Now that you have a way to get the neighbors of a tile, you can check if those neighbors match the 3 tile corner pattern. As you work around the cardinal directions, the tile rotation will also need to be rotated so the spawned tile faces the correct way. The function will return the tileRow, the rotation, and a boolean to indicate a floor tile should be spawned as well.
Looking at the first pattern check, let us break it down to see what it is checking.
A check to the WEST is done first to see if that neighbor is a wall.
A check to the NORTH is done to see if that neighbor is a wall.
The current tile in the loop is checked to make sure it is not a wall.
A check to the EAST is done to make sure it is not nil.
A check to the SOUTH is done to make sure it is not nil.
The nil checking is to make sure that a tile exists. If you don’t do these checks, your map will still generate, but you will see some Wall Corners appear in spots that don’t make sense.
Tile Rotation
If the children of your tile have been rotated, then the rotation for the Z will be different for you. Change the rotation Z value until you find which values work for your tile.
functionMapBuilder.CheckForWallCorner(map, neighbors, row, col)local tileRow = nillocal rotation = Rotation.New()
if neighbors.WEST == MapBuilder.Type.Wall and neighbors.NORTH == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.EAST ~= niland neighbors.SOUTH ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 0elseif neighbors.NORTH == MapBuilder.Type.Wall and neighbors.EAST == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.WEST ~= niland neighbors.SOUTH ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 90elseif neighbors.EAST == MapBuilder.Type.Wall and neighbors.SOUTH == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.NORTH ~= niland neighbors.WEST ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 180elseif neighbors.SOUTH == MapBuilder.Type.Wall and neighbors.WEST == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.EAST ~= niland neighbors.NORTH ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 270endreturn tileRow, rotation, trueendCode language:Lua(lua)
Create SpawnExtraTile Function
There will be cases where an extra tile will need to be spawned with the current tile. For example, when spawning a Wall Corner tile, a Floor tile will need to be spawned as well, or there will be a hole in the floor. In this case, the function will just be spawning a Floor tile, but this may change later as the algorithm improves.
Create a new function called SpawnExtraTile. This function will take in the params table from the Spawn function so it can reuse those options.
The Spawn function will need to be updated so it can get the neighbors and work out if a wall corner should be spawned or not. Most of this code is the same, the only difference is that it is calling a few functions from within the Spawn function, and checking to make sure it can spawn an extra tile.
local ASCIIParser = require(script:GetCustomProperty("ASCIIParser"))
local TILES = require(script:GetCustomProperty("Tiles"))
local MapBuilder = {
Type = {}
}
for key, row inpairs(TILES) do MapBuilder.Type[row.key] = row.id
endfunctionMapBuilder.Build(opts)local map, mapStr = ASCIIParser.BuildMap(opts.map, opts.width, opts.height)
MapBuilder.Spawn(map, opts.width, opts.height, opts.size, opts.container)
endfunctionMapBuilder.GetTile(map, row, col)local foundRow = map[row]
if foundRow thenreturn foundRow[col]
endreturnnilendfunctionMapBuilder.GetNeighbors(map, row, column)return {
NORTH = MapBuilder.GetTile(map, row - 1, column),
SOUTH = MapBuilder.GetTile(map, row + 1, column),
EAST = MapBuilder.GetTile(map, row, column + 1),
WEST = MapBuilder.GetTile(map, row, column - 1)
}
endfunctionMapBuilder.CheckForWallCorner(map, neighbors, row, col)local tileRow = nillocal rotation = Rotation.New()
if neighbors.WEST == MapBuilder.Type.Wall and neighbors.NORTH == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.EAST ~= niland neighbors.SOUTH ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 0elseif neighbors.NORTH == MapBuilder.Type.Wall and neighbors.EAST == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.WEST ~= niland neighbors.SOUTH ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 90elseif neighbors.EAST == MapBuilder.Type.Wall and neighbors.SOUTH == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.NORTH ~= niland neighbors.WEST ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 180elseif neighbors.SOUTH == MapBuilder.Type.Wall and neighbors.WEST == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.EAST ~= niland neighbors.NORTH ~= nilthen tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 270endreturn tileRow, rotation, trueendfunctionMapBuilder.SpawnExtraTile(params, container) params.scale.z = 1 params.rotation = Rotation.New()
container:SpawnSharedAsset(TILES[MapBuilder.Type.Floor].tile, params)
endfunctionMapBuilder.Spawn(map, width, height, size, container)ifnot Environment.IsServer() thenreturnendfor row = 1, height dofor col = 1, width dolocal neighbors = MapBuilder.GetNeighbors(map, row, col)
local tileRow, rotation, spawnFloor = MapBuilder.CheckForWallCorner(map, neighbors, row, col)
if tileRow == nilthen tileRow = TILES[map[row][col]]
endif tileRow ~= nilthenlocal scale = Vector3.New(size / 100, size / 100, size / 100)
if tileRow.floorthen scale.z = 1endlocal x = -(row * size) + (height * size) / 2local y = (col * size) - (width * size) / 2local params = {
scale = scale,
position = Vector3.New(x, y, 0),
rotation = rotation
}
container:SpawnSharedAsset(tileRow.tile, params)
if(spawnFloor) then MapBuilder.SpawnExtraTile(params, container)
endendendendendreturn MapBuilder
Code language:Lua(lua)
Test the Game
Test the game to make sure that corners are now using a different tile. You will see dead ends are using the wall corner tile as well. This will be addressed in the next lesson.
This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.
Strictly Necessary Cookies
Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.
If you disable this cookie, we will not be able to save your preferences. This means that every time you visit this website you will need to enable or disable cookies again.
3rd Party Cookies
This website uses Google Analytics to collect anonymous information such as the number of visitors to the site, and the most popular pages.
Keeping this cookie enabled helps us to improve our website.
Please enable Strictly Necessary Cookies first so that we can save your preferences!