Flixel-compatible tilemap autoset

(Jacob Albano) #1

Attention @miguelmurca! Your request has been granted. Doesn’t have all the bells and whistles, but it should be helpful anyway.

private function autoSet(tilemap:Tilemap, grid:Grid):void 
    for (var col:int = 0; col < grid.columns; col++) 
        for (var row:int = 0; row < grid.rows; row++) 
            if (!grid.getTile(col, row)) continue;
            var index:int = 0;
            if (grid.getTile(col, row - 1)) index += 1;
            if (grid.getTile(col + 1, row)) index += 2;
            if (grid.getTile(col, row + 1)) index += 4;
            if (grid.getTile(col - 1, row)) index += 8;
            tilemap.setTile(col, row, index);

Load your solid values into a Grid, create a Tilemap to set, and pass them both to the function. You should be good to go. It uses the tileset format defined here, which is what Flixel uses.

For example:

And a sample of the result:


(Mike Evmm) #2

Hell yeah! :thumbsup: (there should totally be a pull request, if there isn’t already.)

(Jacob Albano) #3

I’m open to creating a pull request, but I’d want to know how this would be best integrated. A method on Tilemap, probably? We’d also need to specify the tileset format somewhere in the documentation.

(Mike Evmm) #4

static function on the Tilemap class, perhaps?

(Ultima2876) #5

This is awesome. How is the code so small and efficient!? :slight_smile:

(azrafe7) #6

Very nice and compact!

needs extra checks for col/row out of bounds (either in the inner loop or directly in Grid.getTile())

(Jacob Albano) #7

It’s a really interesting technique which I can’t take any credit for. The basic idea is that any tile can have four tiles around it that dictate what it should be. Each direction is assigned a power of two (1, 2, 4, 8), and added to a total if a tile is found there. That total becomes an index; for example, if a tile has no neighbors, its total is 0, whereas if it has a neighbor on every side its total is 15 (1 + 2 + 4 + 8). As you can see, the first tile in the set (index 0) is used for a standalone cell, and the sixteenth tile is used for a cell that’s completely surrounded.

Grid.getTile() already does its own bounds checking; it just returns false if you try to get a tile outside of the grid. :wink:

I think I’d be more likely to make it an instance function à la Tilemap.loadFromString(). That way you would only have to pass one parameter instead of two.

(azrafe7) #8

Ooohh… it does it indirectly, and I’m finding it out only now o.O?

Looking at the code I assumed it didn’t, and that an extra check was needed.

Then I tested

	var bmd:BitmapData = new BitmapData(10, 10);
	trace(bmd.getPixel32(-1, -1));

expecting an exception… and instead I got 0 traced out.

Aaaand that’s when I headed to read the doc of BitmapData.getPixel32(). :no_mouth:

(Jacob Albano) #9

That is weird. Especially since (if I’m not mistaken) BitmapData.setPixel32() does indeed throw an exception.

(azrafe7) #10

Well, tested that too afterwards and… surprise!

EDIT: to clarify the :no_mouth:, it was my bad to assume it would throw an exception.

(Jacob Albano) #11


I just tested it too.

Good job Flash.

(Zachary Lewis) #12

From the documentation on BitmapData.getPixel32():


Number - A number that represent an ARGB pixel value. If the (x, y) coordinates are outside the bounds of the image, 0 is returned. If the bitmap was created as an opaque bitmap and not a transparent one, then this method will return an error code of -1.

(Mike Evmm) #13

Hey, I did something with it! (Press any key to generate new room) And it’s in HaXe(Punk)! https://dl.dropboxusercontent.com/u/24607148/Random%20Room%20Experiment/embed.html
(I suppose that means it’s not really related to FlashPunk, but as @flashpunknovice once put it, this is where I cut my teeth! (Also the port’s minimal))

(David Williams) #14

Dear Lord, why wasn’t this around 2 years ago?!

I had a giant list of "else if"s that used the same basic ideology, but took forever to type out. This is awesome!