What seems to be the problem
In my last post on storing level data in XML, I outlined a method for creating levels for a tile based game that would be as easy to use as opening a text editor. Unfortunately, the method required that you enter the number of rows in the level manually. I figured if I found this annoying (which I did, squinting my eyes to count each row) then I should probably fix it.
A more efficient way
When AS3 parses through XML data, it will read XML data that falls between <tags> until there are no more. This means that if each row of a level is between XML <tags>, a two dimensional array can be created with a new array being created for each row of values. Lets have a look at the XML first.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <!-- BLOCK TYPES 1 = Static Block 2 = Ramp left to right 3 = Ramp right to left 4 = Loose block 5 = Player --> <levels> <level> <title> Tutorial 3 </title> <data> <r>111111111111111111111</r> <r>100000000000000000501</r> <r>100400000000000211111</r> <r>100400000000021111111</r> <r>111111300000000000001</r> <r>111111113000040000001</r> <r>100000000000040000001</r> <r>104000000000040000021</r> <r>111113000000040000211</r> <r>111111300000213002111</r> <r>111111111111111111111</r> </data> </level> </levels> |
Inside <levels> can be any number of <level> objects. Each <level> has a <title> and <data>. The <data> is then made up of any number of <r> or row objects. This method of storing the data allows easy viewing and editing of the level, whilst eliminating the need to have a separate value for the number of rows.
Parsing the XML data
The following code is take from line 55 of the Levels.as file from the game project. This is the part that deals with parsing the level data and putting it into a usable array. See code comments for details.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | if(levelPart.name() == "data") { var dataRows:XMLList = levelPart.children(); var n:int = 0; var dataArray:Array = new Array(); // A temporary array to hold each level for each (var eachRow:XML in dataRows) //For each XML object inside the data object { //This reg expression selects every character and number separately var myPattern:RegExp = /[A-Z]|[a-z]|[0-9]/g; var str:String = eachRow.text(); //Get the text from each row var sArray:Array = str.match(myPattern); //Match the reg expression against the text dataArray[n] = sArray; //For each row, create a new array in the parent array. n++; } obj.data = new Array(); obj.data = dataArray; //Add the array to the object containing other level info } levels.push(obj); //Push the object into the global array defined on line 12 |
While at the moment, the level tiles are represented by the numbers 0-5, the regular expression on line 63 allows for any character a-z both lowercase and capitals, and all numbers 0-9. This should be enough for any game we want to create.
Building the level
Back in the TileGame.as, we now have a new and improved createLvl() function. Now that the level data is in 2 dimensional array, we can traverse the data with a simple nested loop.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | private function createLvl(e:Event):void { //Store the current level data in an array for easy access var lvlArray:Array = L.levels[lvlCurrent-1].data; for(var i:int = 0;i<lvlArray.length;i++) { for(var j:int = 0;j<lvlArray[i].length;j++) { switch (lvlArray[i][j]) //This is how we find each tile value { //I only show one object's build code for clarity. case "1": //Create Solid Block var wallFd:b2FixtureDef = new b2FixtureDef(); var wallSd:b2PolygonShape= new b2PolygonShape(); var wallBd:b2BodyDef = new b2BodyDef(); //Notice I can use the i and j integers to position elements wallBd.position.Set(j/ m_physScale*30, i/ m_physScale*30); wallBd.type = b2Body.b2_staticBody; wallFd.friction = .9; wallFd.restitution = .05; wallFd.shape = wallSd; wallSd.SetAsBox(15 / m_physScale, 15 / m_physScale); levelB = m_world.CreateBody(wallBd); levelB.CreateFixture(wallFd); break; case "2": //Create Ramp left to right break; case "3": //Create Ramp right to left break; case "4": //Create Loose block break; case "5": //Create Player break; } } } //Once the level is built, begin running the physics engine. addEventListener(Event.ENTER_FRAME, run); } |
Well that’s about it. In upcoming posts I would like to start getting some custom graphics into the game and fine tuning the camera to be a little smarter. In the mean time, feel free to play around with the full source code or just the basics with the SWF and XML.


Wow, that’s cool
Thanks for the sourse, it helped me to solve one box2d problem that I’d encountered the other day
Hey no problem. Come back in a few days for more. Next post will have multiple level support, game goals, and a smarter camera setup.