Let us try to implement a sample Starling-based top-down level with provision to detect the tile on which we touch. We will use the source and the tile sheet given in the Chapter 1
folder from the shared source. The code for the TopDownScene
class is shared in the following code snippet. You will need to initialize this class from the Starling document class using new Starling(TopDownLevel, stage)
.
package com.csharks.juwalbose { import starling.display.DisplayObjectContainer; import starling.display.Image; import starling.events.Event; import starling.events.Touch; import starling.events.TouchEvent; import starling.textures.Texture; import starling.textures.TextureAtlas; public class TopDownLevel extends DisplayObjectContainer { //Texture Atlas image [Embed(source="../../../../assets/assets.png")] public static const AssetTex:Class; //Texture Atlas XML [Embed(source = "../../../../assets/assets.xml", mimeType = "application/octet-stream")] private static const AssetXml:Class; private var texAtlas:TextureAtlas; private var tileWidth:uint=50; private var borderX:uint=25; private var borderY:uint=50; private var touch:Touch; //LevelData as 2 dimensional array private var levelData:Array=[["14","21","21","21","21","21","21","13","21","21","21","21","21","21","17"], ["18","12","7","2","2","8","2","3","2","5","2","2","7","13","20"], ["18","3","3","2","2","2","2","2","2","2","2","2","3","2","20"], ["18","3","3","2","2","2","9","2","2","2","3","2","3","3","20"], ["18","5","2","2","5","2","2","2","4","2","2","2","2","5","20"], ["10","2","2","2","2","3","2","2","2","2","2","2","7","2","12"], ["18","2","8","2","2","2","2","3","2","5","2","2","2","5","20"], ["18","2","2","2","4","2","2","2","2","2","4","2","2","2","20"], ["18","11","2","3","2","2","2","3","2","2","2","2","2","10","20"], ["15","19","19","19","19","19","19","13","19","19","19","19","19","19","16"]]; public function TopDownLevel() { super(); this.addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event):void { this.removeEventListener(Event.ADDED_TO_STAGE, init); //Let us create a texture atlas var tex:Texture =Texture.fromBitmap(new AssetTex(),false); var img:Image; texAtlas=new TextureAtlas(tex,XML(new AssetXml())); //Loop through 2D array & add images to stage for(var i:int=0;i<levelData.length;i++){//i is for rows for(var j:int=0;j<levelData[0].length;j++){//j is for columns img=new Image(texAtlas.getTexture(paddedName(levelData[i][j]))); addChild(img); //calculate position depending on i & j img.x=j*tileWidth+borderX; img.y=i*tileWidth+borderY; } } //Listener for touch this.addEventListener(TouchEvent.TOUCH, onTouch); } private function paddedName(id:String):String{ //function to return '0' padded name var offset:uint=10000; offset+=int(id); var str:String="tiles"; str+=offset.toString().substr(1,4); return str; } private function detectTile(valueX:int, valueY:int):void{ //function to detect tile at given position var tileX:int=int(valueX-borderX)/tileWidth; var tileY:int=int(valueY-borderY)/tileWidth; trace(levelData[tileY][tileX]); } protected function onTouch(event:TouchEvent):void { for (var i:int = 0; i < event.getTouches(this).length; ++i) { touch = event.getTouches(this)[i]; detectTile(touch.globalX,touch.globalY); } } } }
Here we are using the Starling TextureAtlas
class created from embedded assets. The embedded XML and PNG files are created using the TexturePacker
application using the Sparrow/Starling export feature. The PaddedName
function adds the zero padding to the tile names and the onTouch
listener function traces out the tile value in the levelData
array based on the touch position. The registration point of an image is at its top-left corner by default. This benefits us for placing them properly in the scene. Try working with this on your own by playing around with the level data. You can change the values in the level data and see the level scene updates accordingly. We have a total of 22 tiles to play with.
In the preceding code, we have placed each tile as individual images on the scene. This will look fine but it is not necessarily the best approach. This creates a lot of independent entities on the scene, which may become a performance hog for a complicated game where we may need to manipulate each and every tile on every frame. An alternate approach is to use a RenderTexture
class.
A RenderTexture
class can be considered as a dynamically changeable Starling texture, which can be altered anytime via code. We can use methods to clear it, draw items onto it, or to fill it up completely. For our previous level scene, we can simplify everything by creating a single image based on a RenderTexture
class, and then drawing all tiles onto it. This results in the scene having only one entity, thereby minimizing the effort on the Flash Player. Let us take a look at the changes in the code:
rTex=new RenderTexture(stage.stageWidth,stage.stageHeight); var rTexImage:Image= new Image(rTex); addChild(rTexImage); for(var i:int=0;i<levelData.length;i++){ for(var j:int=0;j<levelData[0].length;j++){ img=new Image(texAtlas.getTexture(paddedName(levelData[i][j]))); img.x=j*tileWidth+borderX; img.y=i*tileWidth+borderY; //draw to texture instead of adding new image rTex.draw(img); } }
The detectTile
function is also slightly altered to ignore invalid touch points which fall out at the side level area:
private function detectTile(valueX:int, valueY:int):void{ var tileX:int=int(valueX-borderX)/tileWidth; var tileY:int=int(valueY-borderY)/tileWidth; if(tileX<0 ||tileY<0 ||tileX>levelData[0].length-1 ||tileY>levelData.length-1) { //outside of tile area return; } trace(levelData[tileY][tileX]); }
Use RenderTexture
wherever possible for efficient resource management as well as performance boost. There is an additional method called RenderTexture.drawBundled
, which can further speed things up considerably. We will be using this function a lot for our screen update.
18.227.190.211