drawTiles
Instead of using the build in nme.display.Sprite class you can roll your own game entities and render with drawTiles().
In drawTiles() you will optimally have only one layer for game content, so that you only need to call drawTiles() once per frame. In order to do this you need to build up a class that has everything you need in it (ex: GameEntity). nme.display.Sprite has x/y, width/height, rotation, scale, graphics, etc and you will need to replicate all of that in your GameEntity class. Handling the graphics yourself is the major hurdle since you will need to plan out how you layout your graphics before you load a level in your game (using a Tilesheet).
Note: The libraries Tilelayer or gm2d (look in the blit folder) handle the drawTiles() abstraction nicely. TileLayer uses TileSprite to replace nme.display.Sprite, while gm2d uses Tile for the nme.display.Sprite functionality
Your main game loop would something like this:
class GameMain
{
public var renderArray:Array<Float>;
public var gameEntities:Array<GameEntity>;
public function new():Void
{
renderArray = new Array<Float>();
gameEntities = new Array<GameEntity>();
//Here we update all game entities and then render
Lib.current.stage.addEventListener(Event.ENTER_FRAME,onUpdate);
}
private function onUpdate(inEvent:Event):Void
{
//Reset render array...see TileLayer for most efficient way to handle
renderArray = [];
for (entity in _gameEntities)
{
entity.update(); //update x,y position
}
//we now have all the graphics at the correct positions...one batch render!
Lib.current.stage.graphics.drawTiles(renderArray);
}
}
You game entity would look something like this (only x/y and graphics shown for simplicity):
class GameEntity
{
//drawTiles tile ID
private var _tileID:Int;
private var _x:Float;
private var _y:Float;
private var _gameMain:GameMain;
public function new (inTileId:Int,inGameMain:GameMain):Void
{
//get ref to main game so we can update render array
_gameMain = inGameMain;
//This is the graphic we show every frame
_tileID = inTileId;
_x = _y = 0.0;
}
//Call me on each ENTER_FRAME event!
public function update():Void
{
//Assign arbitrary values to x and y
_x = Std.random(100);
_y = Std.random(100);
//Update render array with this entities information
//order for drawTiles() is id,x,y,...etc
_gameMain.renderArray.push(_tileID);
_gameMain.renderArray.push(_x);
_gameMain.renderArray.push(_y);
}
}
At this point the code still won't work, and that's because the tileID is meaningless at this point...i.e. what does the tileID refer to? It needs to represent something inside of a nme.display.Tilesheet. A tilesheet is just a large image made up of smaller images...that's it. Each small image occupies some space in the large image and that "occupied space" is what the tileID represents.
Example:
- tileID=0 represents the image at x=0,y=0,width=100,height=100
- tileID=1 represents the image at x=101,y=0,width=300,height=100
So now you need to setup your tilesheet...and with that you could use a tool like texturepacker that will generate a large image (from many small .pngs,.jpgs,etc) and will ALSO generate rectangle data...and that rectangle data correlates 1:1 with the tile IDs. The TileLayer library is already setup to read in texturepacker sparrow output so all you have to do is open the tool drop in some images and export the .png and .xml file and then TileLayer will autocreate your tilesheet data.
If you want to roll your own solution you can just create a blank bitmap (i.e. new BitmapData(2048,2048)) and then start adding smaller BitmapData to the larger image and track the rectangles yourself...but then you need an algorithim on how you are going to stack the rectangles..i.e. a binning or packing algorithim like repack or the algorithim I added for gm2d use here.
So as you can see your todo list grows very quickly...I highly recommend TileLayer and Texturepacker if you want to use drawTiles() Tilelayer is efficient, well written, well commented, and should have you up and running 100x quicker then rolling your own solution.