AutotileLib

by Ter13
Fast, simple, abstract 47-state autojoining library
ID:2199673
 
In order to use autotile_lib, you need to first define a series of autotile_rules.

var
list/autotile_rules = list(
"rule"=list("id"=1)
)


turf.autotile_icon is a runtime icon that the turf will attempt to swap to. Provided that this is not null, the object will automatically swap to this icon file immediately upon creation. If the turf has an autotile_rule, and the icon_state is non-null, any turf swapping icons at creation using autotile_icon will have its icon-state reset to null. Autotile_icon should only be set if you need a turf to use a different icon for the map editor than in-game. Autotiles that have a non-null icon_state will not attempt to show their autotile state. This is to allow the placement of autotiles in the map editor that don't obey the joining rules at initialization, but will respond to neighbor changes at runtime.

turf.autotile_rule is the rule for joining a turf will use. The default of null won't use any rules. When set to a string, it will use the rule in global.autotile_rules by that name.

turf.join_id is the join_id for this turf. Autotile rules in the global.autotile_rules list are a list of join_ids that an autotile_rule will pair with. join_id is null by default, which means nothing will join with this turf. If set to a string, and that string matches a nearby autotile, this turf will be used for joining with that autotile.

turf.autotile_flags This variable stores the current state of nearby joins.

turf.autotile_reduce This variable determines which reduction algorithm to apply to the raw at256 format stored in autotile_flags. Whenever an autotile's join states are updated, this reduction algorithm is run against autotile_flags to get an icon_state to show. Three formats are currently supported, 15, 47, and 256. This defaults to 47. More reduction algorithms may be added in the future.

NORTH = 1
SOUTH = 2
EAST = 4
WEST = 8
NORTHEAST = 16
SOUTHEAST = 32
SOUTHWEST = 64
NORTHWEST = 128

This raw value is only stored. It isn't really used for anything longterm. It is reduced using a reduction algorithm to reduce it from at256 format to at47 format. These reduction algorithms can be accessed using at256_reduce47() or at256_reduce15().

turf.New() New() is overridden by this library on turfs. All turfs, even if they don't have an autotile rule look at their neighbors to determine their icon state.

turf.UpdateAutotile(Dir,turf/tile) This function performs an autotile update. if Dir and tile are supplied, this tile will attempt to update according to that direction (relative to self) using the autotile information stored on the tile supplied. If the arguments are left blank, however, all 8 tiles surrounding this one are tested and autotile_flags is updated.




Generating autotiles:

Autotile blanks must be in a DMI, and must be in this format:



This is a standard RPGMaker XP autotile format that's widely used across the web. The top-left tile is state 0, where nothing joins this tile. The top-right tile is all four join corners (state 15). The bottom group of 9 tiles are the outer edge states, the center of which is state 255.

This DMI can be animated using the DMI editor. The converter will preserve that animation in each individual tile.

Include the autotile library in your project and then compile and run the project in DEBUG mode.

The client verb GenAutotile() can be called from the command line. It will ask you to supply an icon to cut into the autotile47 format. It will perform the conversion and then ask you to save the resulting autotile icon somewhere on your hard drive. You can then use this icon file in your project.

Please note that this autotile library doesn't care about the tile size, so if you want to generate an autotile for a specific icon size, the icon must be exactly 3x4 tiles for that final icon size. You can cut up icons taller than your target autotile to create 3/4ths projection cubes too, but the formatting for that can be somewhat difficult to get right.

Special notes:

If you override turf/New(), you need to make certain that you call ..() to ensure that the autotile is updated. You should never, ever, ever under any circumstances sleep() in turf/New(), or it will break EVERYTHING. If you find yourself tempted to spawn() in turf/New(), you should look up StdLib::datum/PostInit().

You can manually set an object's icon_state in the map editor, and it will override pre-init autotiling. Any subsequent calls to UpdateAutotile() will override this map-set icon_state.

Supported formats:

At256 stores 256 unique states per autotile icon. This format will be used rarely.

(Image not available)

At47 stores 47 unique states per autotile icon.



At15 stores 16 unique states per autotile icon.




I've mocked up a template for the library, in case anyone wishes to make their own. The template fits a 32x32 map, but scale to your liking!
Any chance we can get a version where we can use this type of template instead of that one?

Example:

The key differnece is the top right is alot bigger then the current template
That template doesn't make sense to me. How does the engine divide up the three tiels on the bottom?

How does the format use the 1,1 and 1,2 (from the top-left)?
I think Tiled just picks one randomly between the 3 at the bottom as the middle one, mostly the hard part is the top right trying to make a 32x32 version out of the 64x64 that is for that spot and its inverted also, been triyng to fool around see if i can come up with something, with no good results.



If you can figure out a reasonable format for me, I can crunch the numbers and make it work.

The key problem that I see is that my importer expects that the tile size is determined by blank width/3 and height/4.

So adding optional additional tiles to this format is going to make the entire importer less user friendly.

Adding additional fill variants isn't a big problem, but it's still a problem. Currently, the entire algorithm assumes that there will only be 47 unique states in each autotile. I don't want to have to check the number of icon states in each file at world initialization to work out how many fill variants there are. Even then, I can't simply check the number. I'd have to create a stricter format in the icon_state naming convention to allow this.

The other issue is that the importer only assumes that states 0 through 46 are taken, and any icon_state that isn't one of the default 46 states is considered special at map init unless it's the null state. The null state is again, special for world init.

Tiled's format isn't bad per se. It's just one of three main standards:

RMVX ace format (Enterbrain):



RMXP format (Enterbrain):



The third is the format you are expressing interest in.


The reason I elected to use RMXP format is because it has no duplicate information, allowing the fewest seams and region repeats compared to VX format, and is more widely used.

I'm open to additional features, but I'm just not sure how to approach certain aspects of what you are asking for in a universal way that doesn't cause problems.
What if its alright if we do all that extra work to make it work, but not use the autotile as a feature of the game, only use it once to get the map done, and then use a map instancing where we save the map into a dmm mapfile with all the changes autotile did to the map, and then use that as the default map, if that makes any sense.
That does make sense, but it wouldn't be part of my lib at all, and at that point, your best bet would be to modify my code for your own purposes.
I was mainly talking about the extra work to make that set work with the autotilelib, not the map instancing part. But fair enought.
The only one i can think of is this one, every grid is of 32x32 size, instead of the middle one being in middle it goes to the left now and we add an extra row with the extra 3 tiles.

Let me show you an interesting trick.

You can actually use two different autotiles together by combining their rule sets to be a little more cooperative.

One real neat thing about autotilelib is that the implementation is incredibly flexible. Try playing around with different layouts for the tiles. There is always an reverse layout, and if you make your thinking of how the art assets work a little more flexible, you can make some interesting things work.



I typically do this to allow certain tiles to have diagonal edges and curved edges where needed.
Mah god you're a genius.
As always, if you have any complaints or suggestions about autotilelib, I'm more than willing to address them. Pop on by the forums some time, pop in a feature request, and I'll have Lummox mark it not feasible, or Nadrew mark it redundant.

Cheers. Hope this is working for you.