Level overlaid with XML data

Level overlaid with XML data

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.

The result

Get Adobe Flash player