Drawing Tiles - HeapsIO/heaps GitHub Wiki

Drawing tiles

Tiles can be drawn with multiple approaches, some of which going to be covered by following example.

h2d.Bitmap

Bitmap is a simple container to draw one Tile. It's the most basic type, but should be used with caution, as each Bitmap causes a draw call.

h2d.TileGroup

TileGroup allows to batch-draw Tiles beloning to same Texture with ability to apply individual tint, transform and alpha to each tile. This class can be used to draw static tiles, but not very well suited for dynamic movement, since it should be cleared and refilled with data each time something should be altered.

TileGroup hacking

With @:privateAccess tileGroup.content it's possible to access underlying TileLayerContent instance and do more fine-tuned geometry operations other than simple rectangles.

h2d.SpriteBatch

SpriteBatch allows to batch-render Tiles belonging to same Texture, but contrary to TileGroup, it updates batch data each frame and allows to control each SpriteElement individually. Note that by default SpriteBatch does not utilize scale and rotation of SpriteElements and it should be enabled with hasRotationScale flag. Same applies to update method of SpriteElement - it will be called only when hasUpdate flag is set.

BasicElement and updates

h2d.SpriteBatch.BasicElement is a good example of how update method can be utilized. This class provides simple simulation of gravity, friction and velocity.

Sample

This example draws tile layers from a Tiled export file (json) using TileGroup batching, Bitmap for backdrop image and SpriteBatch for batch-rendering of moving sprites.

The example uses a backdrop.png, bunnies.png, tiles.json and tiles.png files, that should be put in the resources (/res) folder. Those files are not included in samples directory.

class Main extends hxd.App {
	static function main() {
		// embed the resources
		hxd.Res.initEmbed();
		new Main();
	}
	
	override private function init() {
		super.init();
		
		// Add backdrop Bitmap
		var bitmap = new h2d.Bitmap(hxd.Res.backdrop.toTile(), s2d);
		
		// parse Tiled json file
		var mapData:TiledMapData = haxe.Json.parse(hxd.Res.tiles_json.entry.getText());
		
		// get tile image (tiles.png) from resources
		var tileImage  = hxd.Res.tiles_png.toTile();
		
		// create a TileGroup for fast tile rendering, attach to 2d scene
		var group = new h2d.TileGroup(tileImage, s2d);
		
		var tw = mapData.tilewidth;
		var th = mapData.tileheight;
		var mw = mapData.width;
		var mh = mapData.height;
		
		// make sub tiles from tile
		var tiles = [
			 for(y in 0 ... Std.int(tileImage.height / th))
			 for(x in 0 ... Std.int(tileImage.width / tw))
			 tileImage.sub(x * tw, y * th, tw, th)
		];
		
		// iterate on all layers
		for(layer in mapData.layers) {
			// iterate on x and y
			for(y in 0 ... mh) for (x in 0 ... mw) {
				// get the tile id at the current position 
				var tid = layer.data[x + y * mw];
				if (tid != 0) { // skip transparent tiles
					// add a tile to the TileGroup
					group.add(x * tw, y * mapData.tilewidth, tiles[tid - 1]);
				}
			}
		}
		
		// Create raining bunnies with SpriteBatch
		var bunnies = hxd.Res.bunnies.toTile();
		var batch = new h2d.SpriteBatch(s2d);
		batch.hasRotationScale = true;
		batch.hasUpdate = true;
		// Note: Does not count as a bunnymark.
		for (i in 0...100) {
			var bunny = new Bunny(bunnies);
			batch.add(bunny);
			bunny.reset();
		}
	}
}

class Bunny extends h2d.SpriteBatch.SimpleElement {
	
	public function new(t:h2d.Tile) {
		super(t);
		gravity = 100;
	}
	
	public function reset() {
		y = -t.height;
		x = Math.random() * (batch.getScene().width - t.width);
		scale = 1 + (Math.random() - 0.5) * .1;
		vx = Math.random() * 60;
	}
	
	override function update(dt:Float) {
		super.update(dt);
		if (y > batch.getScene().height) reset();
		return true;
	}
	
}

// simple type definition for Tile map 
typedef TiledMapData = { layers:Array<{ data:Array<Int>}>, tilewidth:Int, tileheight:Int, width:Int, height:Int };
⚠️ **GitHub.com Fallback** ⚠️