I had no clue what to call this. This could be used as the basis for terrain generation in tilemap games. Given a grid where a tile is either on/off, it'll determine which image to use to form a consistent path or edge. Think of a map editor where you place grass tiles and it automatically calculates the edges. Because I did not want to create a million images, this example only looks at adjacent tiles and not diagonals. This gives 16 possible combinations.
I use an animated sprite and change its frame based on the surrounding tiles whether occupied or not. The tile has an initial value of 0 and increments by the amount shown below of the surrounding tiles if occupied.
I've attached two tilesets I made; some purple blobs and a pipe set. Just click around the screen and the pipes will connect themselves.
// show all errors
SetErrorMode(2)
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
global _screenWidth = 1024
global _screenHeight = 768
SetVirtualResolution( _screenWidth, _screenHeight ) // doesn't have to match the window
//baseSpr = createSprite(loadImage("blobs.png"))
//setSpriteAnimation(baseSpr, 64, 64, 16)
baseSpr = createSprite(loadImage("pipes.png"))
setSpriteAnimation(baseSpr, 256, 256, 16)
setSpriteSize(baseSpr, 64, 64)
setSpriteVisible(baseSpr, 0)
// Hashmap would be better but this is what we got
dim frameRefs[16] as integer
frameRefs[0] = 0
frameRefs[1] = 2
frameRefs[2] = 8
frameRefs[3] = 10
frameRefs[4] = 16
frameRefs[5] = 18
frameRefs[6] = 24
frameRefs[7] = 26
frameRefs[8] = 64
frameRefs[9] = 66
frameRefs[10] = 72
frameRefs[11] = 74
frameRefs[12] = 80
frameRefs[13] = 82
frameRefs[14] = 88
frameRefs[15] = 90
Type MapObj
spr as integer
active as integer
EndType
// Change these if you change resolution because AGK stupid
#CONSTANT MAP_WIDTH = _screenWidth / 64
#CONSTANT MAP_HEIGHT = _screenHeight / 64
global temp = 0
dim map[MAP_WIDTH, MAP_HEIGHT] as MapObj
for x = 0 to MAP_WIDTH-1
for y = 0 to MAP_HEIGHT-1
map[x, y].spr = cloneSprite(baseSpr)
SetSpritePosition(map[x, y].spr, x*64, y*64)
next y
next x
// Grid color
c = MakeColor(80,80,80)
do
render()
// Draw grid
for x = 0 to 1024 step 64
drawLine(x, 0, x, 768, c, c)
next x
for y = 0 to 768 step 64
drawLine(0, y, 1024, y, c, c)
next y
// Map coordinates
tx = floor(getRawMouseX() / 64)
ty = floor(getRawMouseY() / 64)
// Place map tile
if GetRawMouseLeftState() = 1
if map[tx, ty].active = 0
map[tx, ty].active = 1
calcImage(tx, ty, 1)
setSpriteVisible(map[tx, ty].spr, 1)
endif
endif
// Erase map tile
if GetRawMouseRightState() = 1
if map[tx, ty].active = 1
reset(tx, ty)
endif
endif
render2DFront()
Sync()
loop
// Clears a map tile
function reset(x, y)
map[x, y].active = 0
setSpriteVisible(map[x, y].spr, 0)
// Recalculate surrounding map tiles
if y > 0 then calcImage(x,y-1,0)
if x < MAP_WIDTH-1 then calcImage(x+1,y,0)
if x > 0 then calcImage(x-1,y,0)
if y < MAP_HEIGHT-1 then calcImage(x,y+1,0)
endfunction
function calcImage(x, y, n)
i = 0
if y > 0 : i = i + map[x, y-1].active * 2 : if n=1 then calcImage(x,y-1,0) : endif
if x < MAP_WIDTH-1 : i = i + map[x+1, y].active * 16 : if n=1 then calcImage(x+1,y,0) : endif
if x > 0 : i = i + map[x-1, y].active * 8 : if n=1 then calcImage(x-1,y,0) : endif
if y < MAP_HEIGHT-1 : i = i + map[x, y+1].active * 64 : if n=1 then calcImage(x,y+1,0) : endif
for j = 0 to frameRefs.length-1
if frameRefs[j] = i
setSpriteFrame(map[x, y].spr, j+1)
exit
endif
next j
endfunction