Skip to content

Instantly share code, notes, and snippets.

@securas
Created August 6, 2020 15:02
Show Gist options
  • Save securas/a123280ab1196eac4e13fa062407891c to your computer and use it in GitHub Desktop.
Save securas/a123280ab1196eac4e13fa062407891c to your computer and use it in GitHub Desktop.
A custom godot autotiler for blocks
tool
extends TileSet
const EMPTY_AUTOTILE = Vector2( 4, 0 )
var block_tiles = [ "blocks" ]
func _forward_subtile_selection(autotile_id : int, _bitmask : int, tilemap : Object, tile_location : Vector2 ):
if block_tiles.find( tile_get_name( autotile_id ) ) < 0:
return null#._forward_subtile_selection( autotile_id, bitmask, tilemap, tile_location )
tilemap = tilemap as TileMap
var cur_tile_coord = tilemap.get_cell_autotile_coord( tile_location.x, tile_location.y )
#----------------------------------
# check if current tile can be changed
#----------------------------------
var cur_tile_bitmask = autotile_get_bitmask( autotile_id, cur_tile_coord )
#----------------------------------
# relevant adjacent tiles
#----------------------------------
# top left
if tilemap.get_cellv( tile_location - Vector2.ONE ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x - 1, tile_location.y - 1 )
var relbit = autotile_get_bitmask( autotile_id, coord )
var mask_from_top_left : bool = relbit & BIND_BOTTOMRIGHT
if mask_from_top_left:
return EMPTY_AUTOTILE
# top
if tilemap.get_cellv( tile_location + Vector2.UP ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x, tile_location.y - 1 )
var relbit = autotile_get_bitmask( autotile_id, coord )
var mask_from_top : bool = relbit & BIND_BOTTOMLEFT
if mask_from_top:
return EMPTY_AUTOTILE
# left
if tilemap.get_cellv( tile_location + Vector2.LEFT ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x - 1, tile_location.y )
var relbit = autotile_get_bitmask( autotile_id, coord )
var mask_from_left : bool = relbit & BIND_TOPRIGHT
if mask_from_left:
return EMPTY_AUTOTILE
#----------------------------------
# check possible masks for new tile
#----------------------------------
var allowed_mask = [ 1, 0, 0, 0 ]
# right
if tilemap.get_cellv( tile_location + Vector2.RIGHT ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x + 1, tile_location.y )
var bits = autotile_get_bitmask( autotile_id, coord )
if bits == BIND_TOPLEFT:
allowed_mask[1] = 1
elif bits == ( BIND_TOPLEFT + BIND_BOTTOMLEFT ):
if tilemap.get_cellv( tile_location + Vector2.DOWN ) == autotile_id:
var coord2 = tilemap.get_cell_autotile_coord( tile_location.x, tile_location.y + 1 )
var bits2 = autotile_get_bitmask( autotile_id, coord2 )
if bits2 == BIND_TOPLEFT:
allowed_mask[1] = 1
allowed_mask[2] = 1
allowed_mask[3] = 1
# bottom
if tilemap.get_cellv( tile_location + Vector2.DOWN ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x, tile_location.y + 1 )
var bits = autotile_get_bitmask( autotile_id, coord )
if bits == BIND_TOPLEFT:
allowed_mask[2] = 1
elif bits == ( BIND_TOPLEFT + BIND_TOPRIGHT ):
if tilemap.get_cellv( tile_location + Vector2.RIGHT ) == autotile_id:
var coord2 = tilemap.get_cell_autotile_coord( tile_location.x + 1, tile_location.y )
var bits2 = autotile_get_bitmask( autotile_id, coord2 )
if bits2 == BIND_TOPLEFT:
allowed_mask[1] = 1
allowed_mask[2] = 1
allowed_mask[3] = 1
# remove impossible flags
# top right
if tilemap.get_cellv( tile_location + Vector2( 1, -1 ) ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x + 1, tile_location.y - 1 )
var bits = autotile_get_bitmask( autotile_id, coord )
if bits & BIND_BOTTOMLEFT:
allowed_mask[1] = 0
# bottom left
if tilemap.get_cellv( tile_location + Vector2( -1, 1 ) ) == autotile_id:
var coord = tilemap.get_cell_autotile_coord( tile_location.x - 1, tile_location.y + 1 )
var bits = autotile_get_bitmask( autotile_id, coord )
if bits & BIND_TOPRIGHT:
allowed_mask[2] = 0
var amask = allowed_mask[0] + \
allowed_mask[1] * BIND_TOPRIGHT + \
allowed_mask[2] * BIND_BOTTOMLEFT + \
allowed_mask[3] * BIND_BOTTOMRIGHT
# priority to current tile
if cur_tile_bitmask != BIND_TOPLEFT and cur_tile_bitmask & ( ~amask ):
return cur_tile_coord
var compatible_tiles = find_tilecoord_with_mask( autotile_id, amask )
# select random tile
return compatible_tiles[ randi() % compatible_tiles.size() ]
func find_tilecoord_with_mask( id : int, tmask : int ) -> Array:
var tsize = tile_get_region( id ).size / autotile_get_size( id ).round()
var compatible_tiles = []
for x in range( tsize.x ):
for y in range( tsize.y ):
var coord = Vector2( x, y )
var curmask = autotile_get_bitmask( id, coord )
if curmask != 0 and not( curmask & ( ~tmask ) ):
compatible_tiles.append( coord )
return compatible_tiles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment