2017-02-27

Fettler - the path to random map generation

While the blog has been a bit quiet, I've been working on some new features for Fettler.

The first part was a Python script that will go through the masks directory, load each image, and figure out what parts of each edge are floor and which are wall.  It's actually a little smarter, it looks at the whole image and figures out which openings are connected to the rest of the openings on each tile.  While that last bit of info isn't being used yet, it might come in handy down the road.

The connected-ness is determined by converting the images into a grid of nodes (basically a low-res black & white bitmap) and then doing a flood-fill from each of the edge openings to figure what you can reach from that edge.  The "fingerprint" just a list of each of the edge squares and what it connects is saved as a json file for use by the second part.

The second part attempts to generate random map of tiles, using the fingerprints to make sure the edges of adjacent tiles match up.  First stab at this uses a backtracking algorithm, so it tries all of the tiles in a given spot, and if it can't place any it goes back tot he previous tile placed, switches it for the next one that fits there, then tries move forward again.

The issue is that with nearly a thousand possible tiles in each spot, the backtracking algorithm is really limited to backtracking at most two or three tiles.  Any more than that and the number of iterations is too big -- three steps of backtracking is a billion tile combinations.  So the question then becomes what order to place the tiles.  If we do any sort of scan-line placement (rows across left to right, working top to bottom, for example), then it might become necessary to unwind a whole row, which is too much if the row is more than 2 or 3 tiles.

With a horizontal or diagonal scanline placement, then, the random generation can sometimes get stuck.  There are a few pairs of edge combinations that don't exist in the tileset, which leads to too much unwinding being needed.  I've currently got a timeout set so if it goes a few seconds without completing it just bails out and starts over.  Not elegant, but it works.

This can be mitigated a bit with a snake or spiral placement patter, so at every tile is always next the previous tile that was placed.  I'm going to add this next.

Here's one random map:


Here's a bigger 12x20 tile map (each tile being 6x6 squares):

And here is a 30x30:


Since overall connected-ness isn't factored in, there are a fair number of isolated segments, though if you consider putting "secret doors" in a few walls, it works pretty well.  Its output is a list of tiles, so you can always go tweak the tiles to add/remove/edit individual tiles before making the map.

The other limitation is that some not-quite-aligned-to-corners edges will end up matched to ones that are aligned.
A lot of the time this can be fixed manually by putting in a tile that does align.  Removing this type of tile for the available set would work, too.

My other plan is to make it so that instead of generating the map from textured tiles, the map can be assembled into one large mask, then the mask given the texture and edges as the tiles are.  This will leave the generated shape, but clean up the missing edge lines.

I'm also going to explore something that attempts a bit more random placement but allows for removing of other already-placed tiles when it can't fit stuff next to them.  It wouldn't be guaranteed to find a solution, but it might actually end up more likely to complete the map when the pure backtracking algorithm ends up getting stuck.


2017-02-18

Fettler v1.0


A free dungeon tile set generator

Magic is impressive, but now Minsc leads. Free tiles for everyone!

Overview

Fettler is a series of Bash scripts. It can apply a grid to a floor and wall texture using a tile "mask" to easily create useful tiles for Roll20, other VTT systems, or where-ever you can make use of modular tile geomorphs. It has the ability to generate a large number of pre-defined masks for you, as well as some grids.


Once you have masks, textures, and a grid, you just need to run the script to generate a full set of tiles.

My hope is that these scripts make building and re-skinning a tile library much easier tasks.  If you make cool tile sets (and the textures allow it), share them with others!  If you make new masks, share them too!  If you add to the mask script, share it and let me know so I can include more masks in future updates!

Requirements

-Windows with Cygwin (tested), or anything with Bash (other platforms untested)
-ImageMagick

Installation

Download (with some textures, 11.8 MB) or get from GitHub (does not include any textures).
Unzip and untar.
Check that you have ImageMagick set up correctly. From Bash, the command:
 magick convert logo: logo.png
should produce the logo.png file. If it does not, Fettler scripts will not work.
Personally, I found it easier to get the Windows Binary Release build (currently ImageMagick-7.0.4-10-Q16-x64-dll.exe) of ImageMagick working correctly with Cygwin.

Usage

From a Bash prompt, you should cd into the directory Fettler is installed in. Here's how to use them:

setenv.sh

This is optional, but included for convenience if you need something to set your PATH to include ImageMagick if it's not there already. Edit to point to your ImageMagick path, and source with:
 . ./setenv.sh

fettler-grids.sh

Creates a set of overlay grids. When used, the overlay will appear on the floor, but not the wall. You can just run it:
 ./fettler-grids.sh
and it will generate a bunch of grid files and put them in the "grids" sub-directory.

fettler-masks.sh

Creates a set of tile masks, white for walls, black for floor. Edit the script if you want to change whether it outputs rotated versions - many seamless tiles won't still tile when rotated, so having rotated masks will generate extra, already rotated versions of tiles that need it. Run with:
 ./fettler-masks.sh
and it will generate a bunch of masks files and put them in the "masks" sub-directory.

fettler-tiles.sh

Applies a grid to a set of masks, using a wall and floor texture. You will want to edit this to set the textures you want, as well as a few other options. Once you've set what you want, run:
 ./fettler-tiles.sh
and it will create a tile file for every mask file and put them in  the "output" sub-directory.

fettler-jpgs.sh

Converts a directory of pngs to jpgs. This is optional, but if you want more compressed version of the tiles, this will mass convert them. Run:
 ./fettler-jpgs.sh
and it will convert all the pngs in "output" and put all of them them into the "output_jpg" sub-directory.

Known issues

-Sometime ImageMagick (at least the Win64 build I have) hangs trying to process jpgs when loading textures. Converting the jpgs to pngs solves the issue.

Possible future plans

-Move some of the options to env. variables and/or command-line options, so scripts don't need to be edited directly.
-Add a "liquid" layer, another layer mask that applies a texture between the floor and wall layers, for making sewers, lava channels, etc.
-Add option for using single larger map-sized mask for making a single map file.
-Expand built-in support to options other than 6x6
-Windows batch file support, and/or some other more cross-platform support, like Python.
-Some sort of "decoration" support for doors, etc.
-... other suggestions?

Resources

Check Twitter and this blog for updates!
@400goblins

Some sources for seamless tileable textures:
http://opengameart.org/content/100-seamless-textures
http://www.swtexture.com/
http://duion.com/art/textures
http://www.deviantart.com/browse/all/?section=&global=1&q=seamless+tile&offset=0
and doctorfree's mkseamless.sh:
https://github.com/doctorfree/Scripts

2017-02-14

Tilemaker Preview


If you use virtual table-tops, like Roll20, you've probably used map tiles.  Sometimes you can find whole maps that work for your needs, but when you want to build a map yourself, having tiles will help you quickly assemble a custom map.  For structures like dungeons, tiles can save a ton of time over building the whole structure.

I've built a script that automates a lot of the work of building a tile set.  In short, you give it two texture images (one for the walls, one for the floor), and it generates a set of tiles using those images. The tiles are generated from a set of template images.  You can use whatever template images you want, but this includes a script that will generate a few hundred useful ones for you.





The script lets you (optionally) apply a grid just to the floor and not over the walls - this makes for less visual clutter and makes it easier to tell the floor from the wall.  In Roll20 you can drop the opacity of the map's grid so you'll just see the tiles' grid.

The included templates are for 6x6 unit tiles.  Since not all textures are tileable when rotated/flipped, it can optionally generate those versions.  Templates and tiles can be generated at any size.

There are still a few more features I want to implement before releasing it, but here's a sample set of about 960 tiles created at 70 pixels per square.

Tileset sample: tilemaker_test_set.zip (55.7MB)

Enjoy!  Let me know if you have any comments on the shapes.