Z-sorting


We've come across the concept of z-sorting a few times already in this chapter, and now we can finally discuss it in detail. Once again, z-sorting is the term used to describe the creation of the stacking order of movie clips. If two movie clips are overlapping, of course they can't both be on top. The one on top is said to have a higher depth. You are probably familiar with the concept of depth in Flash, but let's review a little bit and go over a few things you may not know about depths in Flash.

Each timeline in a Flash movie can have up to 16,384 depths, and each depth can hold only one movie clip. When you manually place movie clips in a timeline, they are assigned a depth starting at -16,383. Each additional movie clip manually placed in the timeline has a depth higher than the previous one, with numbers moving closer to 0. When you use ActionScript to create instances of movie clips, you assign them a depth. It is recommended by Macromedia (and is common practice) to assign positive depths to movie clips created with ActionScript. Depth 1 does not have to be filled before depth 2. This means that you can, for instance, use attachMovie() and assign the new movie clip a depth of 2,000,000.

Don't Go Too Deep!

Be careful how high a depth you use; if it is too high, then you can no longer easily remove the movie clip using removeMovieClip(). The highest depth to which you can assign a movie clip without losing the ability to use removeMovieClip() is 1,048,575. The depth 1,048,576 is too high. However, if your movie clip is above 1,048,575, you can use swapDepths() to bring that movie clip back down below this critical number and then use removeMovieClip().

graphics/08fig14.jpg

The goal of z-sorting in our isometric world is to assign each movie clip to a specific depth so that the objects in the world appear to be stacked correctly. With z-sorting we can make it so that a character can walk around an object like a tree. The tree's depth remains constant, while the character's depth changes as it moves.

Isometric worlds in Flash are usually also tile-based worlds. All of the files presented in this chapter from now on use tiles to create the world. In addition to all the advantages of tile-based worlds that were introduced in Chapter 7, "Tile-Based Worlds," we can add z-sorting. Z-sorting in a tile-based world is much easier to handle than it is in a non-tile-based world. What we do is assign a depth to each tile, with a gap of something like 5 between depths. So one tile might have a depth of 100, and the next tile might have a depth of 105. Then as the character moves onto the first tile, we give it a depth of 101, and when the character moves onto the next tile, we give it a depth of 106. Next, we'll discuss how to assign the depth to each tile.

As you know, in order to create a grid of tiles, you must use nested loops. One way to assign depth is to base it on where you are in the loop. But that's a limited technique that we won't use here. Instead, we use an equation that will give us a unique depth for each cell. This equation works for any y position. So if you decide to create a complicated isometric world in which there are multiple levels (such as the inside of a two-story house), then this equation will still work perfectly, giving you the correct depths to use.

First we establish a boundary of the largest x tile number we expect to use. If it is a 10-by-10 tile-based world, then this boundary is 10. In the following mathematical exercise we use the letters a and b to represent the maximum number of tiles that can be found in the x and z directions.

 a = 10  b = 10 

Then, assuming we are trying to find the depth of the tile specified by (x, y, z), we can write the following:

 floor = a*(b - 1) + x  depth = a*(z - 1) + x + floor*y 

In order for these equations to give a valid final result (depth), x, y, and z must all be positive values. So when we write this with ActionScript, we make use of the Math.abs() method of the Math object in Flash to ensure that the values are positive. Since we are assigning values based on the tiles themselves, we can use integers for x and z. For instance, the cell 3_5 would have an x of 3 and a z of 5. Since we are only dealing with one level (flat ground), the value of y remains 0.

Each tile contains its depth.

graphics/08fig15.gif

graphics/cd_icon.gif

To see this in action, open depth.fla from the Chapter08 folder on the CD. In this file is a 10-by-10 grid of tiles created in the isometric world. When each tile is created, we assign a depth to it using the calculateDepth() method. There are three layers in the main timeline: Object Definitions, Actions, and Assets. The Assets layer contains one movie clip called floor. This movie clip contains the tile movie clip and the ball movie clip. The Actions layer contains a lot of ActionScript needed to create the tiles, change some of the tiles to display objects, and move the ball movie clip. The Object Definitions layer contains the same ActionScript as it did in the position.fla example file in the previous section. We did not discuss the calculateDepth() method at that time. Let's look at it now:

 1   isometricAS.prototype.calculateDepth = function(x, y, z) { 2      var leeway = 5; 3      var x = Math.abs(x)*leeway; 4      var y = Math.abs(y); 5      var z = Math.abs(z)*leeway; 6      var a = this.maxx; 7      var b = this.maxz; 8      var floor = a*(b-1)+x; 9      var depth = a*(z-1)+x+floor*y; 10     return depth; 11  }; 

This method contains the math equations we discussed earlier, translated into ActionScript. In line 2 we create a variable called leeway. We multiply this number by both x and z when they are passed in. This enables us to separate the depth of each tile by at least the value of leeway (5). So one tile may have a depth of 250 and the next one would have a depth of 255. If leeway had a value of 1, then each depth would be 1 more than the previous. Notice the use of Math.abs() in lines 3 5. This ensures that the values of x, y, and z are positive. In lines 8 and 9 we calculate the depth and then return it in line 10.

Now let's look at the function that creates the tiles, buildFloor():

 1   function buildFloor(path) { 2      path.tile._visible = false; 3      world.tiles = []; 4      var y = 0; 5      for (var j = 1; j<=10; ++j) { 6          for (var i = 1; i<=10; ++i) { 7             if (j == 1) { 8                world.tiles[i] = []; 9             } 10            var depth = iso.calculateDepth(i, y, j); 11            var name = "cell"+i+"_"+j; 12            path.attachMovie("tile", name, depth); 13            var clip = path[name]; 14            world.tiles[i][j] = {x:i, y:y, z:j, depth:depth,                clip:clip}; 15            var x = (i-1)*world.cellWidth; 16            var z = -(j-1)*world.cellWidth; 17            temp = iso.mapToScreen(x, y, z); 18            clip._x = temp[0]; 19            clip._y = temp[1]; 20         } 21     } 22  } 

There is an object in the timeline called world (which we'll see in the "Deconstruction of a Simple World" section later on) that was created to store information about this isometric world. In line 3 above we create an array on the world object called tiles. This is a two-dimensional array, and each element of the array is an object that represents a tile. In line 4 we set the variable y equal to 0. This is the level on which the tiles will be created. Look at line 10. This is where we find the depth of the current tile that is being added to the screen. We do this by passing in the x tile number, the z tile number, and the y level (0). In line 12 we add the tile using attachMovie(), and assign it a depth from the variable we created in line 10 called depth.

Next let's take a look at the function used to place the ball on the screen:

 1   function placeBall() { 2      ball.x = ball.x; 3      ball.y = ball.y; 4      ball.z = ball.z; 5      var temp = iso.mapToScreen(ball.x, ball.y, ball.z); 6      ball.clip._x = temp[0]; 7      ball.clip._y = temp[1]; 8      var cellx = Math.ceil(ball.x/world.cellWidth); 9      var cellz = Math.ceil(Math.abs(ball.z)/world.cellWidth); 10     var depth = iso.calculateDepth(cellx, 0, cellz); 11     var depth = depth+1; 12     ball.clip.swapDepths(depth); 13  } 

Take a look at lines 8 12. In lines 8 and 9 we find the tile that the ball is currently on top of by using the trick learned in the "Precision Detection" section of Chapter 7 (a method for determining where the character is located, so that we then had to perform collision detection only in that cell). We then determine the tile's depth in line 10 by invoking the calculateDepth() method of the isometricAS object. Next, in line 11, we increase the value of the depth by 1. This is so that the ball will appear on top of the current tile. (If we didn't do this, we'd be setting the depth of the ball to the same depth as the tile, which would destroy the instance of that tile.) Finally, in line 12 we set the ball's depth using swapDepths().

That isn't all of the ActionScript in this file. We don't explain all of the ActionScript because you have seen the techniques used in the rest of this file before. In the next section we will discuss some more of the Action Script, as well as add some more to this file.

graphics/08fig16.gif

Generate a SWF from this file to see z-sorting in action. Two plants will appear on the screen, along with a grassy tile-based ground and a sidewalk. The ball will appear at the edge of the floor. You can then use the arrow keys to move the ball around. Watch the ball move around the plants and the blocks sticking up through the floor; it appears in front of or behind the plant and the blocks as appropriate. You may notice that nothing is stopping you from moving the ball directly onto a cell that has an object, so the z-sorting can look a little bit odd if you move through an object. In the next section we add a character who can walk around in this world. We also add some collision detection to make sure the character doesn't move onto a tile that contains an object.



Macromedia Flash MX Game Design Demystified(c) The Official Guide to Creating Games with Flash
Macromedia Flash MX Game Design Demystified: The Official Guide to Creating Games with Flash -- First 1st Printing -- CD Included
ISBN: B003HP4RW2
EAN: N/A
Year: 2005
Pages: 163
Authors: Jobe Makar

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net