This is the first of two parts about isometrics in Flash. Here we will use the Photoshop file we made in the previous part to prepare wall tile graphics. We will then write code to create the world in Flash.
I have tried to follow the coding conventions of Actionscript 2.0 but since I am completely self-taught and not much of a programmer there may be some flaws. Big thanks to Codemonkey who took a look at the files before release.
Before we can do any coding we have to prepare our tiles graphics. The following is a pretty bad but fast way of doing things. As you can see in image 3.1 I do not only copy the tile but everything in front of it. This will add a few bytes to the size and you could of course erase everything except what is shown of the tile. But since I am lazy I will do it this way for now.
Open the Photoshop file from the previous part and hide everything except the walls. We will start with the tile at the very back and then follow that row to the down left. Draw a solid shape over the tile in a new layer (A). Then select the shape (B), hide the layer and copy everything below (C) with Ctrl+Shift+C. Open a new document with the dimensions of your tile +10 height and width with a transparent background. Paste your content and save as wall1.gif. Repeat this for all tiles, just notice that a lot of them are exactly the same. For instance, the first row has only three different tiles.
When you come to the short tiles you do exactly the same as before but with a shorter shape in step A.

3.1. Lazy but fast way to cut tiles
When the tedious job of making tiles is done we can move on to putting it all back together in Flash.
The code of the third part consists of two as-files, IsoWorld.as and Tile.as. In image 3.1 you will see the structure of the two files, a constructor function in each and four public methods in IsoWorld.

3.2. Listing of the members used in the project
There are also a few lines of code in the main timeline that starts with two lines prevent scaling and blurring of the graphics. After that we have a two-dimensional array to represent the world where each number is a tile, then three more of those for each wall that can be made in-/visible. Next we create an object of the IsoWorld class, call addTiles() with a new Tile class object for each tile. Last but not least we call the createWorld() method to build everything. This was fast, but as the title says, it is just an overview, details are coming below.
Create a new document, 800*600 pixels in size at 30 fps. There should be three layers on the main timeline (see 3.3); one for the code, one for the clip containing our world and one if you want to add a background later on.

3.3. Layers on the main timeline
Next we create two movie clips. The first is the holder of everything and should go directly in the root, on the myWorldClip layer. Give it the instance name “myWorldClip”. The second one is going to hold our tiles and should go in the library. In order to attach tiles to the stage we also have to give it “tiles” as a linkage identifier name (see 3.4).

3.4. Make sure to export the tiles movie clip
Double click on the tiles movie clip in the library to edit and add layers as in image 3.5. Add a stop action on the first frame on the label layer. This layer will be used to name each tile thru a label (for example “wall1”, “wall2”, “counter_corner_right”, “wall_window1”, it does not matter as long as you know what they mean).
The detail layer will be used later on to add, yes, details. Do not worry about this yet though.
The last layer, tile_graphics, will contain the tile images we made in Photoshop in the beginning of this part. If the tile has both a high and low tile image it should be put in a movie clip with the instance name “wall”. In that we have the low tile on the first frame with a stop action and the label “low”. On the second frame we have the high tile graphics and the label “high”. This will allow us to raise and lower walls by just telling them to go to the high/low label.

3.5. Layers in the tiles movie clip
Now you have everything set up except the code!
In this part we have just two classes. The Tile class is the simpler of the two, holding just a constructor.
class Tile {
public function Tile (myTileSort:String, isOpen:Boolean, myChangeWall:Number, myDetail:String) {
tileSort = myTileSort;
openTile = isOpen;
changeWall = myChangeWall;
tileDetail = myDetail;
}
}
A tile object requires four variables when created: tileSort tells us what kind of tile it is (the label as a string from the tiles movie clip discussed in the previous paragraph), openTile is a Boolean that tells us if users are going to be able to walk on the tile or not, changeWall tells us what wall (if any) the tile belongs to through a number and finally tileDetail, a string that adds a detail if wanted.
The IsoWorld class has a little more content. The constructor requires the width of your tiles as a number, in this case 16 pixels. It also creates an array called tiles so we can store our tile objects later on.
class IsoWorld {
public function IsoWorld (myWidth:Number) {
tileWidth = myWidth;
tiles = new Array();
}
}
The createWorld method does all the work when it comes to adding tiles to the stage. It takes the arguments grid (two-dimensional array holding the world info) and target_mc (movie clip holding the world).
public function createWorld (grid:Array, target_mc:MovieClip):Void {}
First we assign the value of grid to a class variable.
worldGrid = grid;
Next we attach two movie clips to our holder, one in the other. This is to provide two “main levels” for making a distinction between open and closed tiles.
target_mc.createEmptyMovieClip("front", tileDepth);
target_mc.front.createEmptyMovieClip("back", tileDepth);
Then we get the lengths of the two-dimensional array by checking grid.length and grid[0].length.
gridHeight = grid.length; gridWidth = grid[0].length;
Now we have all the info we need to loop through our array. We do this by running two for loops, one with x < gridHeight as termination condition and the other with y < gridWidth.
for (var x = 0; x < gridHeight; ++x) {
for (var y = 0; y < gridWidth; ++y) {
Next we create a temporary name and a tile object for the current tile.
tileName = "tile_" + x + "_" + y; currentTileObject = Tile(tiles[grid[x][y]]);
Check the objects openTile value to determine whether it should go in the front or back.
if (currentTileObject.openTile) {
path = target_mc.front.back;
} else {
path = target_mc.front;
}
Next, calculate the position of the tile in an isometric environment. You get the isometric x value by subtracting the normal x value with the y value then multiplying the result with the tile width. The isometric y value is calculated by adding the normal x and y values, multiplied by the tile width divided by 2 (look at image 1.7 from the first part).
toIsoX = (y - x) * tileWidth; toIsoY = (y + x) * tileWidth / 2;
Then it is time to attach the current tile graphic to the stage. We do this by using the attachMovie() function. Use the path variable before to determine whether it goes in the front or the back. Use “tiles” as an id name to get the current tile object. The new name should be tileName (our temporary tile name) and the depth is calculated with the toIsoY value times 100 added with the toIsoX value.
path.attachMovie("tiles", tileName, toIsoY * 100 + toIsoX);
The tile is then moved to the correct location by setting the path[tileName] x and y values to the corresponding isometric x and y values.
path[tileName]._x = toIsoX; path[tileName]._y = toIsoY;
Next we check what kind of tileSort the tile is. These variables are strings corresponding to the labels we wrote on each frame in the tiles movie clip. You can also see that tileDetail does exactly the same thing. If there are no tileSort value it stops at the first frame.
if (currentTileObject.tileSort) {
path[tileName].gotoAndStop(currentTileObject.tileSort);
path[tileName].tileDetail.gotoAndStop(currentTileObject.tileDetail);
} else {
path[tileName].gotoAndStop(1);
}
Finally we call the changeWall function for all three walls telling them to go to the high state. This is because our user should start outside of the building when that time comes.
changeWall(_root.myGrid_wall1,"high") changeWall(_root.myGrid_wall2,"high") changeWall(_root.myGrid_wall3,"high")
Next we have an addTile and a getTile method. These are obviously for accessing the array holding our tiles.
public function addTile(tile:Tile):Void {
tiles.push(tile);
}
public function getTile(index:Number):Tile {
return tiles[index];
}
The changeWall method makes it possible to raise and lower the walls. It takes the arguments wallArray (array holding the tiles constituting the wall) and wallStat (a string with either high or low as value). It then checks the length of the array and runs a for loop, raising or lowering the tiles by telling the tiles wall movie clip to stop at label high or low.
public function changeWall(wallArray:Array, wallStat:String):Void{
for (var i = 0; i < wallArray.length; i++) {
var temp = eval(path + ".tile_" + wallArray[i][0] + "_" + wallArray[i][1]);
temp.wall.gotoAndStop(wallStat);
}
}
Timeline code
The following code should go in the root of the timeline, on the first and only frame of the script layer. The first two lines are to prevent scaling and blurring because those are pixel arts biggest enemies.
Stage.scaleMode = "noScale"; _quality = "low";
Next we have the two-dimensional array that make up the world. Each number represents a tile.
myGrid = [
[ 5, 9,11,11,11,11,11,11,12,14,15,15,15,15,16,17,18,18,18,18,19, 1, 1, 1, 1],
[ 6, 2, 2, 2, 2,13,47, 4, 4, 4, 4, 4, 4, 4, 4,20, 3, 3, 3, 3,20, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,21, 3, 3, 3, 3,21, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,21, 3, 3, 3, 3,21, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,33,46,41,42, 4, 4, 4, 4, 4, 4,25,26, 0, 0,24,22, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,34, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,23, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2, 0, 4, 4,43, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2, 0, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,33, 4, 4,43, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,27, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4,43,45, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4,40,44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 7, 2, 2, 2, 2,28, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,35, 1, 1, 1, 1],
[ 8,10, 0, 0,32,31,39,39,39,39,38,37,37,37,37,37,37,37,36,39,29, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
Then three more arrays to determine which tiles constitute which wall.
Grid_wall1 = [
[1,5], [4,5], [5,5], [8,5], [9,5], [10,5], [11,5], [12,5], [13,5], [14,5],
[15,5], [16,5], [17,5], [18,5], [19,5], [20,5], [20,4], [20,1]
];
myGrid_wall2 = [
[1,15], [2,15], [3,15], [4,15], [4,16], [4,19], [5,20], [4,20], [3,20],
[2,20], [1,20]
];
myGrid_wall3 = [
[20,6], [20,7], [20,8], [20,9], [20,10], [20,11], [20,12], [20,13], [20,14],
[20,15], [20,16], [20,17], [20,18], [20,19], [20,20], [19,20], [18,20],
[17,20], [16,20], [15,20], [14,20], [13,20], [12,20]
];
Next we create an isoWorld object called world with tile width 16.
var world:IsoWorld = new IsoWorld(16);
Below we add tile objects to the world through the worlds addTile() function. At the same time we create a new tile object for each tile sort with the tiles label name as a string, a boolean to determine if the tile is open or closed, a number representing what floor area the tile belongs to and finally a string stating what detail should be added.
world.addTile(new Tile("floor", true, 0, ""));
world.addTile(new Tile("pavement", true, 1, ""));
world.addTile(new Tile("floor1", true, 3, ""));
world.addTile(new Tile("floor2", true, 2, ""));
world.addTile(new Tile("floor3", true, 4, ""));
world.addTile(new Tile("wall1", false, 0, ""));
world.addTile(new Tile("wall2", false, 0, ""));
world.addTile(new Tile("wall3", false, 0, ""));
world.addTile(new Tile("wall4", false, 0, ""));
world.addTile(new Tile("wall5", false, 0, ""));
world.addTile(new Tile("wall6", false, 0, ""));
world.addTile(new Tile("wall7", false, 0, ""));
world.addTile(new Tile("wall8", false, 0, ""));
world.addTile(new Tile("wall9", false, 0, ""));
world.addTile(new Tile("wall10", false, 0, ""));
world.addTile(new Tile("wall11", false, 0, ""));
world.addTile(new Tile("wall12", false, 0, ""));
world.addTile(new Tile("wall13", false, 0, ""));
world.addTile(new Tile("wall14", false, 0, ""));
world.addTile(new Tile("wall15", false, 0, ""));
world.addTile(new Tile("wall16", false, 0, ""));
world.addTile(new Tile("wall17", false, 0, ""));
world.addTile(new Tile("wall18", false, 0, ""));
world.addTile(new Tile("wall19", false, 0, ""));
world.addTile(new Tile("wall20", false, 0, ""));
world.addTile(new Tile("wall21", false, 0, ""));
world.addTile(new Tile("wall22", false, 0, ""));
world.addTile(new Tile("wall23", false, 0, ""));
world.addTile(new Tile("wall24", false, 0, ""));
world.addTile(new Tile("wall25", false, 0, ""));
world.addTile(new Tile("wall26", false, 0, ""));
world.addTile(new Tile("wall27", false, 0, ""));
world.addTile(new Tile("wall28", false, 0, ""));
world.addTile(new Tile("wall29", false, 0, ""));
world.addTile(new Tile("wall30", false, 0, ""));
world.addTile(new Tile("wall31", false, 0, ""));
world.addTile(new Tile("wall32", false, 0, ""));
world.addTile(new Tile("wall33", false, 0, ""));
world.addTile(new Tile("wall34", false, 0, ""));
world.addTile(new Tile("wall35", false, 0, ""));
world.addTile(new Tile("counter1", false, 0, ""));
world.addTile(new Tile("counter2", false, 0, ""));
world.addTile(new Tile("counter3", false, 0, ""));
world.addTile(new Tile("counter4", false, 0, ""));
world.addTile(new Tile("counter5", false, 0, ""));
world.addTile(new Tile("chair", false, 0, ""));
world.addTile(new Tile("counter1", false, 0, "cash"));
world.addTile(new Tile("floor3", false, 0, "plant"));
When we have everything set up we call the world objects createWorld() function with the two-dimensional grid and the movie clip we put on the stage in the beginning.
world.createWorld(myGrid, myWorldClip);
Now you should have your world up and running. Not much is happening in it at the moment but I saved the best part for last. Next (Part IV) we will add a user and some code to let us control it in the world.
Comment:
(no reply)