Code archives/Miscellaneous/2d Map Builder
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This tool takes an image and based on settings (ie. tile size) chops it up to build a 2d map file and tile image file for scrolling/arcade games from it. It's a good tool to grab images if you are doing a remake! Notes: The tool takes a .png image and creates a .bmp (Blitz can't natively write .pngs) tile map, a basic data file and a Monkey code file. All files will be dumped to a subfolder called Map. v2.0 changes Updated to properly pad tiles when scaling. You can now create a 'Config.ini' file to adjust some of the features. Include any of the following depending on your requirements: ScaleTiles=True|False TileWidth=32 TileHeight=32 TilePadding=0|1 MapPadding=True|False Tile padding will create the required border (1 = 1 pixel) around each tile. Map padding will create an 'empty' one cell border around the map This tool is really for my own use, but a good place to store it for later, plus someone may get some use from it! | |||||
;------------------------------------------------------------------------------------------------------------------------------------------
; MapBuilder
; v2.0
; Matthew Smith 2001, 2011, 2013
;------------------------------------------------------------------------------------------------------------------------------------------
AppTitle "Map Builder v2.0 - Matthew Smith"
Graphics 640, 480, 16, 2
Global MapName$
MapName$=Input$("Enter filename of level gfx: ")
If (MapName = "") Then End
Dim TileMap(1, 1) ;Map Information
Global MapSizeX
Global MapSizeY
;Adjust these items depending on game
Global ScaleTiles = True
Global TileWidth = 32 ;Tile Sizes
Global TileHeight = 32
Global TilePadding = 1 ;Padding added to tile
Global MapPadding = False ;Padding added to map (1 cell border)
Global gfxMap
Global gfxTileStore
Global gfxTileCompareStore
Dim ColorTiles(1, 1)
Const CompareAtOnce = 250
Global TilesMax = 0 ;Number of Tiles Created
;Read Ini File
ReadIniFile()
;Build
SetGfxMapInfo()
CreateBlankTile()
BuildMap()
;Finalise
FreeImage gfxTileStore
FreeImage gfxTileCompareStore
FreeImage gfxMap
EndGraphics
End
Function SetGfxMapInfo()
;Load image
gfxMap = LoadImage(MapName + ".png")
;Get size of map (tiles)
MapSizeX = Int(ImageWidth(gfxMap) / TileWidth)
MapSizeY = Int(ImageHeight(gfxMap) / TileHeight)
;Set map size
ClearMap(MapSizeX, MapSizeY)
;Set tile image store
FreeImage gfxTileStore
gfxTileStore = CreateImage(TileWidth, TileHeight, 512)
;Set comparison tile image store
FreeImage gfxTileCompareStore
gfxTileCompareStore = CreateImage(TileWidth * (CompareAtOnce + 1), TileHeight)
;Set counter
TilesMax = 0
End Function
Function ClearMap(sizeX, sizeY)
Local x, y
;Resize
Dim TileMap(sizeX, sizeY)
;Process
For x = 0 To sizeX
For y = 0 To sizeY
TileMap(x, y) = -1
Next
Next
End Function
Function CreateBlankTile()
;Prepare
SetBuffer(BackBuffer())
ClsColor(0, 0, 0)
Cls
;Copy blank tile and set value in map
DrawBlockRect(gfxMap, 0, 0, TileWidth, TileHeight, TileWidth, TileHeight)
TileMap(0, 0) = 0
;Inc counter
TilesMax = TilesMax + 1
End Function
Function CreateTile(BX, BY)
;Prepare
SetBuffer(ImageBuffer(gfxTileStore, TilesMax))
;Copy tile and set value in map
DrawBlockRect(gfxMap, 0, 0, (BX * TileWidth), (BY * TileHeight), TileWidth, TileHeight)
TileMap(BX, BY) = TilesMax
;Inc counter
TilesMax = TilesMax + 1
;Finalise
SetBuffer(BackBuffer())
End Function
Function PrepareMapComparison(BX, BY, TC)
Local counter
Local compare
Local index
;Set buffer
SetBuffer(ImageBuffer(gfxTileCompareStore))
;Clear comparison image
Color 0, 0, 0
Cls
;Get map tile
DrawBlockRect(gfxMap, 0, 0, (BX * TileWidth), (BY * TileHeight), TileWidth, TileHeight)
;Get total tiles to compare
compare = TC + CompareAtOnce
If (TC + CompareAtOnce > TilesMax) Then compare = TilesMax
;Get stored tile(s) to compare
counter = 1
For index = TC To compare - 1
DrawBlock(gfxTileStore, TileWidth * counter, 0, index)
counter = counter + 1
Next
;Copy into Backbuffer
SetBuffer(BackBuffer())
Cls
;Draw
DrawBlock(gfxTileCompareStore, 0, 16)
End Function
Function DisplayMap()
Local x, y
;Process
For y = 0 To MapSizeY - 1
For x = 0 To MapSizeX - 1
If (TileMap(x, y) <> -1) Then
DrawBlock(gfxTileStore, x * TileWidth, 100 + (y * TileHeight), TileMap(x, y))
End If
Next
Next
;Draw
DrawBlock gfxMap, 260, 100
End Function
Function BuildMap()
Local BX, BY, TC, TB, TileCount
Local counter# = 0
Local matchIndex = -1
Local totalTiles# = (MapSizeX * MapSizeY)
; Work Thru Loaded Map
For BY = 0 To MapSizeY - 1
For BX = 0 To MapSizeX - 1
;Trap ESC key
If KeyDown(1) Then Return
;Prepare
TC = 0
;Process
For TC = 0 To TilesMax - 1 Step CompareAtOnce
;Prepare comparision
PrepareMapComparison(BX, BY, TC)
;Update display summary
Color 255, 255, 255
Text 0, 0, "X" + Right$("000" + (BX + 1), 3) + " Y" + Right$("000" + (BY + 1), 3) + " (" + MapSizeX + "x" + MapSizeY + ") " + Right$(" " + Int((counter / totalTiles) * 100), 3) + "%"
Text 320, 0, "Found:" + Right$("0000" + TilesMax, 4)
;Text 296, 0, "TF" + Right$("00000" + TilesMax, 5) + "/" + Right$("00000" + Int(counter), 5)
Flip
;Validate if exists
matchIndex = CompareTiles(TC)
If (matchIndex <> -1) Then
;Store result
TileMap(BX, BY) = matchIndex
Exit
End If
Next
;No match found?, if so create new tile
If (matchIndex = -1) Then CreateTile(BX, BY)
;Increment counter
counter = counter + 1
Next
Next
;Save Map and Tiles
SaveTiles()
SaveTileMapData()
SaveTileMapMonkey()
;Set finalised message
Color 255, 255, 255
Text(0, 120, "Process complete! Press any key to exit...")
Flip
;Wait
WaitKey
End Function
;Returns the index of the matching tile if found
Function CompareTiles(TC)
Local x, y, index
Local compare
Local counter
Local ct
Dim ColorTiles(3, CompareAtOnce)
;Prepare
SetBuffer(ImageBuffer(gfxTileCompareStore))
;Set number of tiles to compare
compare = TC + CompareAtOnce
If (TC + CompareAtOnce > TilesMax) Then compare = TilesMax
;Search for existing tile match
For y = 0 To TileHeight - 1
For x = 0 To TileWidth - 1
;Get image
GetColor x, y
ColorTiles(1, 0) = ColorRed()
ColorTiles(2, 0) = ColorGreen()
ColorTiles(3, 0) = ColorBlue()
;Process
counter = 1
For ct = TC To compare - 1
If (ColorTiles(0, counter) <> -1) Then
;Get tile store image
GetColor x + (TileWidth * counter), y
ColorTiles(1, counter) = ColorRed()
ColorTiles(2, counter) = ColorGreen()
ColorTiles(3, counter) = ColorBlue()
;Validate
If (ColorTiles(1, 0) <> ColorTiles(1, counter) Or ColorTiles(2, 0) <> ColorTiles(2, counter) Or ColorTiles(3, 0) <> ColorTiles(3, counter)) Then
ColorTiles(0, counter) = -1
End If
End If
;Increment
counter = counter + 1
Next
Next
Next
;Validate
counter = 1
For index = TC To compare - 1
;Match?, if so return tile index
If (ColorTiles(0, counter) <> -1) Then Return index
;Increment
counter = counter + 1
Next
;Not found
Return -1
End Function
Function SaveTiles()
Local BT
Local TX, TY
Local BX, BY
Local TC
Local gfxTileFinalStore
Local finalImageWidth = 320
Local finalTileWidth = TileWidth
Local finalTileHeight = TileHeight
;Scale
If (ScaleTiles) Then
;finalImageWidth = finalImageWidth * 2
finalTileWidth = finalTileWidth * 2
finalTileHeight = finalTileHeight * 2
End If
;Create store
FreeImage gfxTileFinalStore
TX = finalImageWidth / TileWidth
TY = Int((TilesMax - 1) / TX) + 1
gfxTileFinalStore = CreateImage(TX * (finalTileWidth + (TilePadding * 2)), TY * (finalTileHeight + (TilePadding * 2)))
;Set buffer
SetBuffer(ImageBuffer(gfxTileFinalStore))
Color 0, 0, 0
Cls
;Output tiles to store
TC = 0
For BY = 0 To TY - 1
For BX = 0 To TX - 1
If TC <= TilesMax - 1
;Grab image
SetBuffer(ImageBuffer(gfxTileStore,TC))
Local gfxTile = CreateImage(TileWidth, TileHeight)
GrabImage(gfxTile,0,0)
;Scale?
If (ScaleTiles) Then gfxTile = ScaleImageFast(gfxTile, 2.0, 2.0)
;Store
SetBuffer(ImageBuffer(gfxTileFinalStore))
DrawBlock(gfxTile, BX * (finalTileWidth + (TilePadding * 2)) + TilePadding, (BY * (finalTileHeight + (TilePadding * 2)) + TilePadding))
End If
TC = TC + 1
Next
Next
;Save tiles to file
CreateFolder("map")
SaveImage(gfxTileFinalStore, "map\" + MapName + ".bmp")
;Finalise
SetBuffer(BackBuffer())
FreeImage gfxTileFinalStore
End Function
Function SaveTileMapData()
Local fileName$ = "map\" + MapName + ".tiles.map"
Local x, y
;Create file
CreateFolder("map")
Local file = WriteFile(fileName)
;Pad map?
Local msX = MapSizeX
Local msY = MapSizeY
If (MapPadding) Then msX = msX + 2
If (MapPadding) Then msY = msY + 2
;Scale tiles sizes?
Local tsX = TileWidth
Local tsY = TileHeight
If (ScaleTiles) Then tsX = (tsX * 2)
If (ScaleTiles) Then tsY = (tsY * 2)
;Output map summary
WriteString(file, MapName + ".png") ;Tile filename
WriteInt(file, TilesMax) ;Total tiles
WriteInt(file, msX) ;Map Size
WriteInt(file, msY)
WriteInt(file, tsX) ;Tile Size
WriteInt(file, tsY)
;Output padding - top row?
If (MapPadding) Then WritePaddingRowData(file)
;Output map
For y = 0 To MapSizeY - 1
;Padding
If (MapPadding) Then WriteInt(file, 0)
For x = 0 To MapSizeX - 1
WriteInt(file, TileMap(x, y))
Next
;Padding
If (MapPadding) Then WriteInt(file, 0)
Next
;Output padding - bottom row?
If (MapPadding) Then WritePaddingRowData(file)
;Close
CloseFile(file)
End Function
Function SaveTileMapMonkey()
Local fileName$ = "map\" + MapName + ".tiles.monkey.txt"
Local x, y
;Create file
CreateFolder("map")
Local file = WriteFile(fileName)
;Pad map?
Local msX = MapSizeX
Local msY = MapSizeY
If (MapPadding) Then msX = msX + 2
If (MapPadding) Then msY = msY + 2
;Scale tiles sizes?
Local tsX = TileWidth
Local tsY = TileHeight
If (ScaleTiles) Then tsX = (tsX * 2)
If (ScaleTiles) Then tsY = (tsY * 2)
;Output map summary
WriteLine(file, "'#Region " + Chr(34) + " MapData " + Chr(34))
WriteLine(file, " 'Map summary")
WriteLine(file, " 'Map dump file: " + MapName + ".png")
WriteLine(file, " Field TilesMax:Int=" + TilesMax)
WriteLine(file, " Field MapSizeX:Int=" + msX)
WriteLine(file, " Field MapSizeY:Int=" + msY)
WriteLine(file, " Field TileWidth:Int=" + tsX)
WriteLine(file, " Field TileHeight:Int=" + tsY)
WriteLine(file, "")
WriteLine(file, " 'Map Data")
WriteLine(file, " Field TileMap:=[")
;Output padding - top row?
If (MapPadding) Then WritePaddingRowMonkey(file)
;Output Map
For y = 0 To MapSizeY - 1
Local mapRow$ = ""
;Padding?
If (MapPadding) Then mapRow = "0"
;Build row data
For x = 0 To MapSizeX - 1
If (Len(mapRow) > 0) Then mapRow = mapRow + ","
mapRow = mapRow + Str(TileMap(x, y))
Next
;Padding?
If (MapPadding) Then mapRow = mapRow + ",0"
;Append to end of row?
Select MapPadding
Case True
mapRow = mapRow + ","
Case False
If (y < MapSizeY - 1) Then mapRow = mapRow + ","
If (y = MapSizeY - 1) Then mapRow = mapRow + "]"
End Select
;Finalise
mapRow = " " + mapRow
;Write row
WriteLine(file, mapRow)
Next
;Output padding - botton row?
If (MapPadding > 0) Then WritePaddingRowMonkey(file, True)
;Finalise
WriteLine(file, "")
WriteLine(file, "'#End Region")
;Close
CloseFile(file)
End Function
Function WritePaddingRowData(file)
Local x
;Get width
Local width = MapSizeX
If (MapPadding) Then width = width + 2
;Write
For x = 0 To width - 1
WriteInt(file, 0)
Next
End Function
Function WritePaddingRowMonkey(file, isLast=False)
Local paddingRow$ = ""
Local x
;Get width
Local width = MapSizeX
If (MapPadding) Then width = width + 2
;Build row data
For x = 0 To width - 1
If (Len(paddingRow) > 0) Then paddingRow = paddingRow + ","
paddingRow = paddingRow + "0"
Next
;Append to end of row?
If (Not isLast) Then paddingRow = paddingRow + ","
If (isLast) Then paddingRow = paddingRow + "]"
;Finalise
paddingRow = " " + paddingRow
;Write row
WriteLine(file, paddingRow)
End Function
Function CreateFolder(path$)
Local folder$ = SystemProperty("appdir") + path
CreateDir(folder)
End Function
;sswift - Scales the image without blurring
Function ScaleImageFast(SrcImage, ScaleX#, ScaleY#)
Local SrcWidth, SrcHeight
Local DestWidth, DestHeight
Local ScratchImage, DestImage
Local SrcBuffer, ScratchBuffer, DestBuffer
Local X1, Y1, X2, Y2
;Get the width and height of the source image.
SrcWidth = ImageWidth(SrcImage)
SrcHeight = ImageHeight(SrcImage)
;Calculate the width and height of the dest image.
DestWidth = Floor(SrcWidth * ScaleX#)
DestHeight = Floor(SrcHeight * ScaleY#)
;If the image does not need to be scaled, just copy the image and exit the function.
If (SrcWidth = DestWidth) And (SrcHeight = DestHeight) Then Return CopyImage(SrcImage)
;Create a scratch image that is as tall as the source image, and as wide as the destination image.
ScratchImage = CreateImage(DestWidth, SrcHeight)
;Create the destination image.
DestImage = CreateImage(DestWidth, DestHeight)
;Get pointers to the image buffers.
SrcBuffer = ImageBuffer(SrcImage)
ScratchBuffer = ImageBuffer(ScratchImage)
DestBuffer = ImageBuffer(DestImage)
;Duplicate columns from source image to scratch image.
For X2 = 0 To DestWidth-1
X1 = Floor(X2 / ScaleX#)
CopyRect X1, 0, 1, SrcHeight, X2, 0, SrcBuffer, ScratchBuffer
Next
;Duplicate rows from scratch image to destination image.
For Y2 = 0 To DestHeight-1
Y1 = Floor(Y2 / ScaleY#)
CopyRect 0, Y1, DestWidth, 1, 0, Y2, ScratchBuffer, DestBuffer
Next
;Free the scratch image.
FreeImage ScratchImage
;Return the new image.
Return DestImage
End Function
Function ReadIniFile()
Local fileName$="Config.ini"
Local stream = ReadFile(fileName)
Local l$,flag$,value$
;Validate
If (Not stream) Then Return
;Scan
While Not Eof(stream)
l = ReadLine(stream)
flag = Upper(GetIniFlag(l))
value = GetIniValue(l)
;Validate
Select Upper(value)
Case "TRUE"
value = 1
Case "FALSE"
value = 0
Default
;DO nothing
End Select
;Assign
Select flag
Case "SCALETILES"
ScaleTiles = value
Case "TILEWIDTH"
TileWidth = value
Case "TILEHEIGHT"
TileHeight = value
Case "TILEPADDING"
TilePadding = value
Case "MAPPADDING"
MapPadding = value
Default
;DO nothing
End Select
Wend
;Finalise
CloseFile(stream)
End Function
Function GetIniFlag$(l$)
Local pos = Instr(l,"=")
If (pos = 0) Then Return l
Return Mid(l,1,pos-1)
End Function
Function GetIniValue$(l$)
Local pos = Instr(l,"=")
If (pos = 0) Then Return ""
Return Mid(l,pos + 1,Len(l) - pos)
End Function |
Comments
None.
Code Archives Forum