Basically you want to have a "camera" concept to show exactly what you want in your game. In this case the camera may follow your hero, so that it tries to keep the hero centered on the screen as much as possible (similar to how the original super mario bros. game worked).
In order to do so you would add all of your sprites to a parent sprite so your display hierarchy looks like this:
So now your "camera" is in the Game Container layer and you simply use scrollRect() to show exactly what you want. The scrolling parts come into play by having your scrollRect() follow the hero. You could do this with a listener or just a function call, something like:
var oldHeroXPos = hero.x;
var oldHeroYPos = hero.y;
//move your hero in game
//make the camera follow the hero..i.e. move same amount as the hero
The camera.moveOffset() function would look something like this:
public function moveOffset(inXDiff:Float,inYDiff:Float):Void
gameContainer.scrollRect.x += inXDiff;
gameContainer.scrollRect.y += inYDiff;
After you get this working you will have an issue where scrolling isn't smooth, so you will have to do additional work to change the camera position over time...maybe give it some elasticity to make it look nicer.
Note if you use a game engine such as flixel, or awe6 that this type of thing is already taken care of for you, and unless you are interested in learning exactly what it takes to implement a smooth camera I always suggest using a tried and true game library to help get your game out quicker, but the end goals are up to you.
Keep in mind that whatever game logic you use to move your enemies would apply regardless of the camera, and you would probably want a slightly larger box (bigger than the camera) that would be used to indicate if the game entity was "alive" i.e. needs its AI run. If you did something like this then you could have enemies walk into your screen even if the hero stands still (camera not moving).
Instead of using the build in
nme.display.Sprite class you can roll your own game entities and render with
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:
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
Your main game loop would something like this:
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
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!
You game entity would look something like this (only x/y and graphics shown for simplicity):
//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
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.
- 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.