Skip to content

Instantly share code, notes, and snippets.

@oscarcs
Created December 16, 2014 11:55
Show Gist options
  • Save oscarcs/848fef0e2c16f0dd3201 to your computer and use it in GitHub Desktop.
Save oscarcs/848fef0e2c16f0dd3201 to your computer and use it in GitHub Desktop.
Manage a grid of FlxTilemaps
package ;
import flixel.FlxG;
import flixel.tile.FlxTilemap;
import flixel.util.FlxPoint;
/**
* Class for management of an array of tilemaps.
*/
class TilemapGrid
{
/**
* Width in number of tilemaps.
*/
public var width:Int;
/**
* Height in number of tilemaps.
*/
public var height:Int;
/**
* Number of tiles across the whole grid.
*/
public var widthInTiles:Int;
/**
* Number of tiles down the whole grid.
*/
public var heightInTiles:Int;
private var imageData:Dynamic;
private var sizeOfTilemap:Int;
private var masterTileArray:Array<Int>;
/**
* Active status by index for tilemaps.
*/
public var activeMap:Array<Bool>;
/**
* The actual array of tilemaps.
*/
public var tilemapArray:Array<FlxTilemap>;
private var tileSize:Int = 16;
/**
* New TilemapGrid.
* @param w Width in tilemaps (not tiles!)
* @param h Height in tilemaps (not tiles!)
* @param SizeOfTilemap Width & height of each tilemap
* @param ImageData The image to use for tilemaps.
*/
public function new(w:Int, h:Int, SizeOfTilemap:Int, ImageData:Dynamic)
{
width = w;
height = h;
sizeOfTilemap = SizeOfTilemap;
imageData = ImageData;
widthInTiles = width * sizeOfTilemap;
heightInTiles = height * sizeOfTilemap;
masterTileArray = [for (i in 0...(widthInTiles * heightInTiles)) 0];
activeMap = [];
for (i in 0...(width * height)) { activeMap[i] = false; }
tilemapArray = [for (i in 0...(width * height)) null];
}
/**
* Set tile by point.
* @param tile_x
* @param tile_y
* @param value
*/
public function setTile(tile_x:Int, tile_y:Int, value:Int)
{
masterTileArray[ pointToIndex(new FlxPoint(tile_x, tile_y), widthInTiles) ] = value;
var c = determineTilemapFromTile(tile_x, tile_y);
if (activeMap[c])
{
//set that tilemap's tile specifically since it's onscreen / loaded already
if (tilemapArray[c] != null)
{
var p = globalToLocal(tile_x, tile_y);
tilemapArray[c].setTile(Std.int(p.x), Std.int(p.y), value, true);
}
}
}
/**
* Set tile by index.
* @param index
* @param value
*/
public function setTileByIndex(index:Int, value:Int)
{
masterTileArray[index] = value;
var point = indexToPoint(index, widthInTiles);
var c = determineTilemapFromTile(Std.int(point.x), Std.int(point.y));
if (activeMap[c])
{
//set that tilemap's tile specifically since it's onscreen / loaded already
if (tilemapArray[c] != null)
{
var p = globalToLocal(Std.int(point.x), Std.int(point.y));
tilemapArray[c].setTile(Std.int(p.x), Std.int(p.y), value, true);
}
}
}
/**
* Set the master tilemap from an array.
* @param array
*/
public function setFromArray(array:Array<Int>)
{
if (array.length == masterTileArray.length)
{
masterTileArray = array;
for (i in 0...activeMap.length)
{
if (activeMap[i])
{
deactivate(i);
activate(i);
}
}
}
}
/**
* Activate (and create) tilemaps by index.
* @param index
*/
public function activate(index:Int)
{
activeMap[index] = true;
var cur = new FlxTilemap();
var pos = indexToPoint(index, width);
cur.setPosition((pos.x) * (sizeOfTilemap * tileSize), (pos.y) * (sizeOfTilemap * tileSize));
cur.widthInTiles = sizeOfTilemap;
cur.heightInTiles = sizeOfTilemap;
var topleft = localToGlobal(0, 0, index);
var tiles = getTileSubset(masterTileArray, widthInTiles, Math.round(topleft.x), Math.round(topleft.y), sizeOfTilemap, sizeOfTilemap);
cur.loadMap(tiles, imageData, tileSize, tileSize, 0, 0, 1);
cur.updateFrameData();
tilemapArray[index] = cur;
FlxG.state.add(cur);
}
/**
* Deactivate (and destroy) tilemaps by index.
* @param index
*/
public function deactivate(index:Int)
{
if (tilemapArray[index] != null)
{
activeMap[index] = false;
tilemapArray[index].destroy();
tilemapArray[index] = null;
}
}
/**
* Clear tilemaps which have been deactivated (via activeMap accesses) but not destroyed yet.
*/
public function clearInactiveTilemaps()
{
for (i in 0...activeMap.length)
{
if (!activeMap[i])
{
if (tilemapArray[i] != null)
{
tilemapArray[i].destroy();
tilemapArray[i] = null;
}
}
}
}
private function getTileSubset(array:Array<Int>, total_width:Int, x:Int, y:Int, selection_width:Int, selection_height:Int):Array<Int>
{
var a:Array<Int> = [];
var cur = pointToIndex(new FlxPoint(x, y), total_width);
for (i in 0...selection_height)
{
for (i in cur...(cur + selection_width))
{
a.push(array[i]);
}
cur += total_width;
}
return a;
}
private function determineTilemapFromTile(tile_x:Int, tile_y:Int):Int
{
var tilemap_x = Math.floor(tile_x / sizeOfTilemap);
var tilemap_y = Math.floor(tile_y / sizeOfTilemap);
return pointToIndex(new FlxPoint(tilemap_x, tilemap_y), width);
}
private function globalToLocal(global_x:Int, global_y:Int):FlxPoint
{
var local_x = ((global_x / sizeOfTilemap) % 1) * sizeOfTilemap;
var local_y = ((global_y / sizeOfTilemap) % 1) * sizeOfTilemap;
return new FlxPoint(local_x, local_y);
}
private function localToGlobal(local_x:Int, local_y:Int, tilemapIndex:Int):FlxPoint
{
var ind:Int = 0;
var pos = indexToPoint(tilemapIndex, width);
ind += Std.int(pos.y * sizeOfTilemap * widthInTiles);
ind += Std.int(pos.x * sizeOfTilemap);
ind += pointToIndex(new FlxPoint(local_x, local_y), widthInTiles);
return indexToPoint(ind, widthInTiles);
}
private function indexToPoint(index:Int, width:Int):FlxPoint
{
var p = new FlxPoint(0, 0);
p.y = Math.floor(index / width);
p.x = Math.round(((index / width) % 1) * width);
return p;
}
private function pointToIndex(p:FlxPoint, width:Int):Int
{
var i = 0;
i = Std.int(p.y * width + p.x);
return i;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment