So let’s say you’ve started work on your latest awesome game, and you’ve come up with this level design:
*Graphics taken from Danc’s Miraculously Flexible Game Prototyping Tiles, which are awesome and free!*
How are you going to store this map layout in code?
###The One-Dimensional Case
If we just had a single line of tiles, it’d be easy:
We could just store it in a simple Array, like this:
var level:Array = new Array( 5 ); //there are five tiles
level[0] = STONE;
level[1] = WATER;
level[2] = WATER;
level[3] = WATER;
level[4] = DIRT;
…or like this:
var level:Array = new Array(); //no tiles yet
level.push( STONE, WATER, WATER, WATER, DIRT );
…or this:
var level:Array = new Array( STONE, WATER, WATER, WATER, DIRT );
…or even just like this:
var level:Array = [STONE, WATER, WATER, WATER, DIRT];
All those code snippets do the same thing.
Then, when we want to find out what tile to place at each position, we can just look up the value of the element of the level
array at that index. So, level[0]
will be equal to STONE
, level[3]
will be WATER
, and so on.
It’s difficult to imagine how it could be simpler. So how can we do this for a 2D map?
###There is No Native 2D Array Class
In other programming languages (like C#, for example) , we could just create a 2D array which works in the same way as the regular array. So, if I label the rows and columns of the level design I posted above:
…then I can write how this would work in code:
var level:Array = new Array( 4, 5 ); //there are 4 rows and 5 columns
level[0,0] = STONE;
level[0,1] = WATER;
level[0,2] = WATER;
level[0,3] = WATER;
level[0,4] = DIRT;
level[1,0] = STONE;
level[1,1] = WOOD;
level[1,2] = WOOD;
level[1,3] = WOOD;
level[1,4] = DIRT;
level[2,0] = STONE;
level[2,1] = STONE;
level[2,2] = WATER;
level[2,3] = WATER;
level[2,4] = DIRT;
level[3,0] = STONE;
level[3,1] = WATER;
level[3,2] = WATER;
level[3,3] = DIRT;
level[3,4] = DIRT;
Like before, we can look at individual elements in the array; for example, level[1,3]
is equal to WOOD
and level[2,0]
is STONE
.
But we cannot do this in AS3! There is no built-in 2D array class. If you write:
var level:Array = new Array( 4, 5 );
…then Flash will just make a new regular, one-dimensional array with level[0]
equal to 4 and level[1]
equal to 5.
###The Solution: Nested Arrays
We know we can store an entire single row in an array, so why not just make four arrays, and store one row in each?
var firstRow:Array = [STONE, WATER, WATER, WATER, DIRT];
var secondRow:Array = [STONE, WOOD, WOOD, WOOD, DIRT];
var thirdRow:Array = [STONE, STONE, WATER, WATER, DIRT];
var fourthRow:Array = [STONE, WATER, WATER, DIRT, DIRT];
And there’s nothing to stop us putting arrays inside another array, so…
var level:Array = [firstRow, secondRow, thirdRow, fourthRow];
Now, level
is an *array of arrays*. We call this “nesting arrays”, and we call each of firstRow
, secondRow
etc. “nested arrays”.
This means that level[0]
is actually an array itself; level[0]
is equal to [STONE, WATER, WATER, WATER, DIRT]
. And we can access elements within this sub-array — so, level[0][0]
is equal to STONE
, level[0][3]
is WATER
, and so on.
In other words, we can access any element of this array of arrays using level[row][column]
. Not bad!
Also, we don’t have to create the individual row arrays separately from the level array. It’s fine to do this:
var level:Array = new Array( 4 ); //there are four rows
level[0] = [STONE, WATER, WATER, WATER, DIRT];
level[1] = [STONE, WOOD, WOOD, WOOD, DIRT];
level[2] = [STONE, STONE, WATER, WATER, DIRT];
level[3] = [STONE, WATER, WATER, DIRT, DIRT];
…or even:
var level:Array = [ [STONE, WATER, WATER, WATER, DIRT], [STONE, WOOD, WOOD, WOOD, DIRT], [STONE, STONE, WATER, WATER, DIRT], [STONE, WATER, WATER, DIRT, DIRT] ];
###Looping Through Nested Arrays
To loop through nested arrays, we can use (not surprisingly) a nested loop. It looks like this:
for ( var row:int = 0; row <= 3; row++ )
{
for ( var column:int = 0; column <= 4; column++ )
{
trace( row, column, level[row][column] );
}
}
This would output:
0 0 STONE 0 1 WATER 0 2 WATER 0 3 WATER 0 4 DIRT 1 0 STONE 1 1 WATER 1 2 WATER
...and so on, down to:
3 4 DIRT
###Ragged Arrays
Using an array of arrays like this allows us to create *ragged* arrays -- that is, arrays where the rows can be of different lengths.
Suppose we have a level like this:
Those aren't "invisible" tiles and the end of the rows; there are just no tiles there. We can easily store this level like so:
var level:Array = new Array( 4 ); //there are four rows
level[0] = [STONE, WATER, WATER, WATER];
level[1] = [STONE, WOOD, WOOD, WOOD, DIRT];
level[2] = [STONE, STONE, WATER, WATER];
level[3] = [STONE, WATER, WATER];
Of course, you'll get an error if you try to access level[3][4]
, so watch out for that. It's a particular problem when looping; the above nested loop code needs to be modified like so:
for ( var row:int = 0; row < level.length; row++ )
{
for ( var column:int = 0; column < level[row].length; column++ )
{
trace( row, column, level[row][column] );
}
}
Note that instead of checking row <= 4
, the outer loop checks row < level.length
. level.length
is the number of elements in the level array -- i.e., the number of rows.
Similarly, the inner loop now checks column < level[row].length
, i.e. it makes sure column
is less than the number of tiles in the current row.
###3D Arrays
We aren't restricted to two dimensions. We could use as many dimensions as you like, but anything above 3D becomes hard to draw.
Here's a map with rows, columns, and a third dimension: layers. Can you figure out how we could store it using nested arrays?
{ 49 comments… read them below or add one }
Next Comments →
Beginner’s guide to using multidimensional arrays in AS3: http://bit.ly/8aTWOS
This comment was originally posted on Twitter
@keyeske This might be helpful to you: http://gamedev.michaeljameswilliams.com/2010/01/13/multidimensional-arrays-in-as3/
This comment was originally posted on Twitter
Please help im trying to figure out how I can attach movie clips to what i put in the array im trying to figure out how to make a inventory. Please help
Hey Keyeske,
I’m a little confused — do you mean you want to add movie clips to the screen (or to the inventory) based on what’s in the array?
Sory about that. add movie clips to the screen based on the array. I understand how the array works but I dont know how to use it
Ah, OK. Well, suppose you’re using Strings in your array, like:
…then to make it add movieclips corresponding to each item, you could start with a function like this:
That's a basic start point using a 1D array. How's that? Does it make sense?
Thanks im going to go and try it. oh sorry if i keep buggin you but how do i use splice and push? sorry if i seem noobish im more of an artist but im trying to learn programming to do my rpg
No problem. I actually get a lot of questions about arrays; maybe I should expand this into a series?
You use
push()
to add one or more new items to the end of an existing array. So, if you have this:…and you
trace( inventory )
, you’ll get this:But if you put this after the existing code:
…and then
trace( inventory )
again, you’ll get:Splicing an array has the opposite effect; it’s used to remove items. You tell it where to start and how many to remove, and it does that. So, if we continue with the above “inventory” array, and do:
…it’ll remove two items, starting with
inventory[1]
. That means that if you nowtrace( inventory )
, you’ll get:Make sense?
Dru Kepple wrote a great guide to arrays over at activetuts+, and there’s loads of info about arrays on the livedocs page, by the way π
Multidimensional Arrays in AS3 http://bit.ly/7HzpW7
This comment was originally posted on Twitter
Multidimensional Arrays in AS3 http://bit.ly/7HzpW7 (via @bioRex21)
This comment was originally posted on Twitter
Thanks Michael for another great tutorial.
“Can you figure out how we could store it using nested arrays?”
We should add an new dimension to the array for the layers.
Maybe like this:
For the readout we need to add an another for-loop.
I think this should work.
A little question: What is the best way to store this data, if you have for example 10 gamelevels? Should I store it into in xml-files like for each gamelevel?
Hey Martin, cheers for your kind words π
Nice solution! Yes, it’ll work. But, I’m curious as to how you’ll choose to store the second and third layers, where there are some blank spaces?
You could use XMLs, if you wanted to, or you could even just create the arrays directly in code, like:
…but that’s a bit messy. Still, it works, but XML’s probably going to be neater, yeah.
Yes pleas do turn this in to a series.
-Wes
Multidimensional Arrays in #AS3. Good primer for dealing with arrays in #flex http://bit.ly/8aTWOS
This comment was originally posted on Twitter
And how about encrypting the level code to an much shorter string, it saves up alot of space especially on large maps.
Tom — smart idea! You mean, like, we’d store the level as
"12223/14443/11223/12233"
in a String and then use code to convert it in to tiles in an Array later?So yeah, I prefer this method
I used this in my Bloons clone to create waves like this here
I actually don’t like the way it’s shown here, I prefer my way, but I guess that’s anyone’s decision which style he/she prefers =D
EDIT: To you two guys with your string idea, thats quite neat, e.g. having such a format like “(1/1,grass)(1/2,sea)” so f.e. tile at position 1/1 will be created as a grass tile. Reading out with substrings would be one way, but I myself dislike working with substring or other string functions though they are very useful, I don’t like them (as I’m having troubles using ’em lol)
ANOTHER EDIT: To your small challenge (3D Arrays), to me, that’s mere child’s play lol (yep, I’m a poser lulz)
ANOTHEROTHER EDIT: How about not coding this at all and using Flash IDE to simply create Areas that you render to the screen and then giving actions to the single tiles? That would be far better for you to create
Best regards
So, does that code mean you’d have 25 green enemies followed by 10 yellow enemies in the first wave?
I can see that laying out the code like that makes it much clearer, in that case. Though, I would personally prefer interspersing them like so:
…but as you say, it’s up to the coder which style they like π
Fast answer, lol, yeah I thought about that one, too, but came along to not change it (because of laziness (I got PLENTY)) after I’ve set it up for the first time =D
Euhm… pherhaps, but I found this:
http://www.newgrounds.com/bbs/topic/1107353
It’s by a guy named glaiel gamer … he’s kind-off good π
Wow, OK, that’s… a little more complex than I was thinking, haha!
Awesome post, thanks for linking to it.
Edit: Ooh, he made Closure, I thought his name was familiar.
Multidimensional Arrays in AS3 by @MichaelJW http://bit.ly/7HzpW7 great stuff as always π
This comment was originally posted on Twitter
Multidimensional Arrays in AS3 by @MichaelJW http://bit.ly/7HzpW7 great stuff as always π
This comment was originally posted on Twitter
Interesting… now I want to see a flash game in 4D… And the string idea would be especially good for user level creation.
4D game? Miegakure. OK, not Flash, but still π
Yeah, that’d make it easy to share levels, just copy and paste the string into a comment or email or whatever.
Not only that, you could probably embed it into a link via GET to change the flashvars, so someone could just go online and automatically load that level (if that makes any sense).
Also, I don’t think that is 4D (technically). See this: http://en.wikipedia.org/wiki/Four_dimensionalism
Even better! So you’d have http://mysite.com/mygame.html?levelCode=4jh7fgdfjh874n and it’d load it up immediately. Awesome.
Hmm, but if 4D games involve treating time like the three spatial dimensions, then how do you play?
how about creating a multidimensional array by a loaded xml file of unknown depth.
its easy to make a recursive function and parse the xml file, its also easy to know in each step of the way the depth inside the xml file you are into, but how about creating a multidimensional array representing the structure of the xml file, and inside each sub array storing the data and attributes from the xml file. let me give you an example :
Great turorial. Game I’m working on right now is pretty similar to this one. However, I used another method of doing this. However it doesn’t do same thing also, but in my game it works same
@theo: whoa, impressive code… but wouldn’t it require all your attributes and so on to be named after numbers? I say that because of lines like this:
@Kustrle: Cheers. Ah, is that the game you posted screenshots of in the Frozen Haddock forums?
hi, yes they can be named after numbers in order to represent the depth , so when you read the multidimensioanl array to sort it out according to the numbers, or text and attributes can be saved as objects inside the array as well. its a matter of choice
Yes, do you think I am able to developing two games at same time :D? Just one is too hard for me…
@theo: Nice! Are you using that anywhere?
@Kustrle: hehe; well, how’s that one game going then? π
Thank you for explaining this so well
haha if you can develop one game you can develop 2 or as many as you want.
Cheers π
As 3D arrays are very large – then a Voxel or nested arrays of might be less advantageous than a scene graph.
I think this is nested lists of objects and their children.
every object knows where it is and which way it facing.
the advantage is you don’t need to iterate over empty space 8-*.
objects are usually lists of vertices, with corresponding facet groups, then colours and decals stuck on them and maybe skeletal sytems for character animation.
as regards the 4th dimension of time usually some algorythmic shorthand is required such as only storing keyframes and tweening, morphing and interpolating and deforming objects based on their skeletons.
A type of XML is usually used for this, for instance.
a scene graph in XML with the indentation indicating “is a child of” so everything is a child of Level1.
The Location Details can be nested so the Sword is a child of the hero and moves relative to him.
Back when the Web was born it was in 3d and 2d and they called it VRML and HTML. :=)
Hope this helps and thanks for all the hard work, your tutorials are excellent and bug free – rare and fine qualities.
VRML! Wow, I remember that π
So basically, you’re talking about basing the data structure on the objects in the space, rather than on the points in space themselves?
Good point! And yeah, XML is a good fit for this. But also, AS3’s own object/class model works well, too —
hero.addChild( sword )
πThanks for the kind words π
<
p>First of all, great stuff here/p>
Hello everyone,
i have the following problem:
I have to describe a colored grid where at x,y position the colour can be red, green etc. etc.
This was really easy for me in basic, but i can’t do in the right way in actionscript.
basic
dim grid%(1 To 10, 1 To 10)
grid%(4,5)=3: rem grid cell at 4,5 will have color 3 (red)
now, what will be this code in actionscript?
Moreover, i want to add a description for the colored cell of the grid
thank you
Best regards
Consider using the built-in Dictionary class to simplify these nested array lookups, and also to gain an incredible lookup speed advantage vs iterating over regular Array instances.
Thanks for the tip, Andy!
Would you like to give us some example code for that?
@michael Williams
or anyone else who can help me
ok im trying to use a 2d array using the exact same graphics your using and recemmending and ive got this
and that seems to work for an array and then ive got
}
which is what i thought you were using but it just seems to generate a bunch of water
no matter what i put in the array
maybe ive got the code completely mixed up i don’t know
i just started as3 a couple days ago using your avoider game tutorial
ok thanks for reading
also i think all your tuts are amazing but im very stupid
and have a hard time understanding anything except working code
so when you assume (and must people will be able to) that we’ll be able to figure out
how to use these arrays once we have them
i still have a hard time trying to figure things out
thanks alot
daniel from his computer
Hey Daniel,
You’ve actually nearly got it. I’m afraid I think you will kick yourself π
Instead of:
…you just need:
(…or is it row then column? I’m never sure.)
And same goes for the other if, of course π
Hi Michael, This is bhupi and interested in 3d array i read your tips on 2 d array, Plz can u explain the 3 d array for AS 2.0. actually I am try to learn gaming programming. I am waiting for your help. take care.
i kicked myself
Hi I am not sure if you are still answering questions, but i am having problem with 2d arrays.
My Xml(‘test.xml’) looks like this:
ju675
kyu49
so just trying the way you did but i am facing some problems, here is my code
Sorry, I messed up the code and everything when i posted it so posting it again.
Hi I am not sure if you are still answering questions, but i am having problem with 2d arrays.
My Xml(βtest.xmlβ) looks like this:
mg749
ks749
ks678
we649
sd449
df459
hj569
so just trying the way you did but i am facing some problems, here is my code
function completeXMLHandler(event:Event):void
{
var loader:URLLoader=URLLoader(event.target);
var result:XML=new XML(loader.data);
var myXML:XMLDocument=new XMLDocument();
myXML.ignoreWhite=true;
myXML.parseXML(result.toXMLString());
for each (var usr in result.item)
{
level.push({name:usr.@name,state:usr.@state,complex:usr.item,state:usr.@image});
}
for ( var row:int = 0; row < level.length; row++ )
{
trace(level[row].name);
for ( var column:int = 0; column < level[row].length; column++ ){
trace(level[row][column].complex);
}
}
}
I am not able to trace: “trace(level[row][column].complex);”
This is a really helpful guide and the best I’ve found so far. Exactly what I was looking for. π
Nice, clear, helpful article Michael. I was helping a guy troubleshoot his connect4 clone and he was having issues with his arrays. Naturally, having a background in C#, I knew a multidimensional array would solve his problem but wasn’t sure how to go about it in AS3.
Thanks!
{ 1 trackback }