A Technical Look at Isometrics


In this section we'll take a different look at isometrics. We'll discuss everything you need to know in order to place objects in an isometric world and to map them back to the computer screen.

The Orientation of the Isometric World

Before moving forward, we need to look at the Flash coordinate system in a new way. Up to this point in the book we have been seeing the coordinate system as two-dimensional; that is, having an x-axis and a y-axis. Flash does not have a z-axis, but if it did, the positive end would extend out past the back of the computer screen.

graphics/08fig05.gif

The isometric world we will be dealing with can be conceptualized (and then treated mathematically) as a second 3D coordinate system sitting inside this Flash coordinate system. Let's call this second system "the isometric system" and the first "the Flash system." The Flash system is stationary; it cannot move since it is bound to your computer monitor. The isometric system is only isometric when it is oriented in a specific way within the Flash system. Please note that the isometric system does not change when its orientation changes. The only thing that makes it isometric is how it is seen from the Flash system.

Before it is rotated, the new coordinate system is aligned with Flash's coordinate system.

graphics/08fig06.gif

Now let's assume that the isometric system is completely aligned with the Flash system. In this case, there is no difference between the Flash system and the isometric system; in fact, it is not yet isometric. What has to happen to this second system to make it appear isometric, as seen from the Flash system?

  • It must be rotated 30° around its x-axis.

    The x-axis is treated like an axle, so it stays still while the coordinate system rotates. Before the rotation, all three axes lie along all three of Flash's axes. After the rotation, the isometric system's x-axis still lies along Flash's x-axis, but the other axes are no longer aligned.

    Rotated 30° around the x-axis

    graphics/08fig07.gif

  • It must then be rotated 45°around its own y-axis.

    During this rotation, the y-axis is treated like an axle, so it stays stationary while the rest of the isometric system is rotated around it. When this rotation has been completed, all three of the isometric axes are in different positions from their starting places, and it appears to be an isometric system as seen from the Flash system.

Rotated around isometric system's y-axis 45°

graphics/08fig08.gif

Final product:the isometric view as seen from the Flash coordinate system (your monitor).

graphics/08fig09.gif

graphics/cd_icon.gif

Take a look at the demo.swf file in the Chapter08 directory on the CD. This file was created to help you visualize how these two rotations take place. It shows a straight-on orientation in the Flash system (before it is isometric) and then rotates the cube in two steps. When it is finished animating, the cube is seen in an isometric view.

Cube in an isometric world

graphics/08fig10.gif

graphics/tip_icon.gif

Why is this view called isometric? If you look at the cube in the figure above, you will notice that only three faces are exposed. The area of each of these three faces is the same. The prefix iso means "the same," and metric signifies "measurement."

Placing an Object in the Isometric World

Throughout this book we have been advocating using code to describe visual elements their position, speed, and other properties and to store this information (as opposed to storing information in the movie clips themselves). If the position of something needs to be updated on the stage, then we do so at the end of the frame after all needed calculations are done. We take the position that we have calculated in memory and then assign that value to the _x and _y properties of the movie clip. This technique will be used in this chapter as well: We will discuss the position coordinates in the isometric system and in the Flash system, and how to move between them.

graphics/hand_icon.gif

Before continuing, I want to mention some restrictions we will be observing. First, look at the image below.

graphics/08fig11.jpg

We are going to restrict where we place objects to the quadrant of the isometric world formed by the x- and z-axes. Specifically, if we extend this quadrant upward in the y direction, we form an octant (a quadrant infinite in size, extended in an orthogonal, or perpendicular, direction). This octant is shown in the image below.

graphics/08fig12.jpg

The reason we restrict object placement to this octant has to do with z-sorting. (As a reminder, z-sorting refers to changing the depth of movie clips to make them appear to be at the correct distance from the screen.) For instance, as a character walks around a tree, you want the character to appear behind the tree at some points but in front of it at others. The issue of finding a good way to handle z-sorting has plagued Flash developers for a long time. With this octant restriction, we can use a technique I developed for z-sorting that makes it lightning-fast. We'll talk about this in the next section. To recap, the reason why we restrict object placement to this octant is so that we can use a specific and fast z-sorting technique. If someone comes up with something better, please let me know!

When working with 3D worlds, the coding architecture we've been using throughout this book (mentioned in the first paragraph of this section) is no longer just good practice, it's a necessity. We will now store three coordinates that represent each visual element x, y, and z in an object. These are the coordinates of anything in the isometric world. For instance, a character might have the coordinates (100, 10, -50) in the isometric world. In order to display this character on the screen, we have to figure out what the x and y positions of the movie clip on the screen need to be so that it looks as if the character is sitting at those isometric coordinates. So the next logical step is to find this linkage between the isometric system and the Flash system.

We know that the isometric system is related to the Flash system by the two rotations (30° and 45°) discussed in the previous section. Using our knowledge of trigonometry, we can map (project) any point from the isometric system into the Flash system. This is done in two steps, one for each rotation. To map from the isometric system to the Flash system we start with the points in the isometric system and then apply the two rotations to the coordinates. This actually maps the coordinates from the isometric system to an in-between system (after the first rotation) and then from the in-between system into the Flash system. During the first rotation, the y-coordinate is unchanged (because the y-axis is the fixed axis around which the system rotates); during the second rotation the x-coordinate remains unchanged. Here is the math to back it up. We start with the coordinates of a point (xpp, ypp, zpp). The pp is a mathematical convention; when an x-coordinate is changed to a new system, it is usually called xp (or x'). This is read as "x prime." When it is changed two times (as we do in this case), it is called xpp (or x''). This is read as "x double prime." So we start out with (xpp, ypp, zpp), and after the first rotation we'll have (xp, yp, zp). After the second rotation we'll have (x, y, z). So let's begin.

We start in the isometric system with points (xpp, ypp, zpp). To map this to the Flash system we must move through two angles. We treat them one at a time. First we will map the coordinates to the intermediate system by rotating them around the y-axis 45° to arrive at three new coordinates (xp, yp, zp):

 xp = xpp*cos(45) + zpp*sin(alpha)  yp = ypp zp = zpp*cos(45)   xpp*sin(alpha) 

Notice that yp is equivalent to ypp. This is because the system was rotated around the y-axis, so the y-coordinate was not changed. Next we rotate the coordinates (xp, yp, zp) around the x-axis 30° to arrive in the Flash coordinate system (x, y, z):

 x = xp  y = yp*cos(30)   zp*sin(30) z = zp*cos(30) + yp*sin(30) 

We now have the coordinates of where (xpp, ypp, zpp) should appear in the Flash system. You may have noticed that while we end up with (x, y, z), we still don't really have a z-axis in Flash. As mentioned earlier, we can think of a z-axis that moves into the computer screen. This conceptualization helps when trying to do things like mapping from 3D to Flash's system. Movie clips have _x and _y properties, but no _z property. So when the above math is changed into ActionScript, we can forget about the final z-coordinate. If we were not using an isometric view, we would most likely want to have real-time perspective changes. In that case, you would want this z-coordinate to hang around, because you would use it to calculate perspective. In our isometric case, though, we don't need it.

graphics/cd_icon.gifgraphics/hand_icon.gif

Let's see a working example of how to position an object, given its coordinates in the isometric system. Open position.fla in the Chapter08 directory. There are three layers in this file: Assets, Actions, and Object Definitions. The Assets layer contains all of the movie clips and buttons. At the top left of the stage you see three dynamic text fields. They are there to show you the current coordinates of the ball in the isometric system. On the right side of the stage there are two text fields that show you the x- and y-coordinates of the ball in Flash's system. In the middle there is a movie clip with an instance name of floor. Floor contains a graphic of a square floor in an isometric world. Also contained in that movie clip are a movie clip with an instance name of ball and a movie clip with an instance name of shadow. The shadow clip will move around with the ball to help give you a better idea of where the ball is. As the ball changes y positions, the shadow does not; this helps the player visualize the object's location.(A visual cue or clue in a 3D world would be that the ball changed size according to its location; a correlative cue in the isometric world is the location of the object's shadow to help you understand the behavior of the object itself.) On the bottom-right side of the stage are two buttons with which you can control the ball's y position in the isometric world.

graphics/08fig13.gif

Use your four arrow keys to move the ball around. You can change the ball's y position by using the buttons on the bottom-right side of the screen. Notice that your ball will not move through the floor we imposed the octant restriction.

Now let's look at the ActionScript involved in all of this. I have written an object called isometricAS, which is contained on the layer called Object Definitions. This object contains three very helpful methods for working with isometrics. We will talk about two of these methods (mapToScreen() and mapToIsoWorld()) very soon, and will save the third (calculateDepth()) for the next section.

The ActionScript in the Actions layer makes use of what was defined in the Object Definitions layer and handles things like capturing key events and placing the ball and shadow on the screen.

Let's look at the actions in the Object Definitions layer. First we see this:

 1   isometricAS = function (maxx, maxz) { 2      this.maxx = maxx; 3      this.maxz = maxz; 4      this.theta = 30; 5      this.alpha = 45; 6      this.theta *= Math.PI/180; 7      this.alpha *= Math.PI/180; 8      this.sinTheta = Math.sin(this.theta); 9      this.cosTheta = Math.cos(this.theta); 10     this.sinAlpha = Math.sin(this.alpha); 11     this.cosAlpha = Math.cos(this.alpha); 12  }; 

First we create the object itself, called isometricAS. By creating it as a function object, we are setting it up so that we can later create instances of this object by invoking the constructor new isometricAS(). There are two parameters, maxx and maxz. We will discuss these in the next section since they apply only to the calculateDepth() method. In lines 4 and 5 we set the angles that are needed for the world to be isometric 30° and 45°. Then in the next several lines we calculate the sine and cosine of these angles and store the values. (This way we will not have to calculate them every time we need them.)

Next, we create this method on the isometricAS object:

 1   isometricAS.prototype.mapToScreen = function(xpp, ypp, zpp) { 2      var yp = ypp; 3      var xp = xpp*this.cosAlpha+zpp*this.sinAlpha; 4      var zp = zpp*this.cosAlpha-xpp*this.sinAlpha; 5      var x = xp; 6      var y = yp*this.cosTheta-zp*this.sinTheta; 7      //var z = zp*this.cosTheta+yp*this.sinTheta; 8      return [x, y]; 9  }; 

This method takes the coordinates of a point in the isometric system and maps its x- and y-coordinates in the Flash system. It does so by the same math steps that we went over earlier in this section.

graphics/tip_icon.gif

Notice that line 7 is commented out. Earlier in this section when we talked about the math, I mentioned that we wouldn't need the z-coordinate when we were in the Flash system. I kept that line of ActionScript in there just in case you want it. If you ever decide to display a non-isometric view in which you'll need to apply perspective changes, then you will need this coordinate.

In line 8 we return the values x and y (which are the positions as they appear in the Flash system) as an array.

The final method of the isometricAS object that we will discuss in this section does something we have not yet discussed:

 1   isometricAS.prototype.mapToIsoWorld = function(screenX,       screenY) { 2    var z = (screenX/this.cosAlpha-screenY/       (this.sinAlpha*this.sinTheta))*       (1/(this.cosAlpha/this.sinAlpha+       this.sinAlpha/this.cosAlpha)); 3      var x = (1/this.cosAlpha)*(screenX-z*this.sinAlpha); 4      return [x, z]; 5   }; 

This function maps the coordinates (x, y) from the Flash system into the isometric system. Since we have only the x- and y-coordinates from the Flash system, we cannot map that to an (x, y, z) position in the isometric system; we can only map it to two coordinates. This method is useful when we want to capture the user's mouse position and then find out where that would be in the isometric world.

If you have ever played Electrotank's Mini Golf game, then you have seen this used; as you move the mouse around the character, the character rotates to follow. Then, when you click, the character hits the ball. In order to calculate what angle the mouse made with the character, we map the mouse coordinates to the isometric world. The angle as it appears on the screen is not the angle that is truly in the isometric world.

We're not going to use this method in this section, but we will show a direct application of it in the final section in this chapter. I am not going to show the math involved in deriving the above equations, as it got pretty hairy, but I will tell you that I used the equations in the mapToScreen() method and worked backward.

Select the frame in the Actions layer, and open the Actions panel. Let's look at the first three lines of the ActionScript:

 1   iso = new isometricAS();  2   ball = {x:0, y:0, z:0, clip:floor.ball,      shadowClip:floor.shadow}; 3   speed = 5; 

In line 1 we create an instance of the isometricAS object. In the next line we create an object called ball, which will be used to store all of the information about the ball movie clip that we will be moving around in the isometric world. We initialize this object at position (0, 0, 0) and give it references to the ball movie clip and the shadow movie clip. In line 3 we set the speed. This simply specifies how much to move the ball every time an arrow key is pressed.

Next, we create a function called captureKeys():

 1   function captureKeys() { 2      if (Key.isDown(Key.RIGHT)) { 3         ball.x += speed; 4      } else if (Key.isDown(Key.LEFT)) { 5         ball.x -= speed; 6      } 7      if (Key.isDown(Key.UP)) { 8         ball.z += speed; 9      } else if (Key.isDown(Key.DOWN)) { 10        ball.z -= speed; 11     } 12  } 

When this function is called, it checks to see which arrow keys are currently pressed down. If any are, then it changes the ball's position in either the x or z direction in the isometric system by the amount of speed.

Here is the function that is called to place the ball and the shadow on the screen:

 1   function placeBall() { 2      var temp = iso.mapToScreen(ball.x, ball.y, ball.z); 3      ball.clip._x = temp[0]; 4      ball.clip._y = temp[1]; 5      var temp = iso.mapToScreen(ball.x, 0, ball.z); 6      ball.shadowClip._x = temp[0]; 7      ball.shadowClip._y = temp[1]; 8   } 

In line 2 we call the mapToScreen() method of the isometricAS object, passing in the ball's coordinates. The result is stored as an array called temp. We then use the values of this array to position the ball on the screen (lines 3 and 4). In line 5 we do almost the same thing as we did in line 2 except that we pass in 0 as the value of the y position. We then use this array to place the shadow movie clip on the screen. We passed in the value of 0 for the y position because the shadow should always be on the ground, which has a y position of 0. But the x and z positions of the shadow should always be the same as the ball's. This adds a very simple and helpful effect to an object that's moving around in a 3D environment. To mention Electrotank's Mini Golf again, you can see how useful something like this is in that game. It is especially evident when the ball flies off a ramp. You can see the shadow move down the ramp as the ball goes through the air.

Now we come to a function called changeY(). As you can guess, this function changes the ball's y position. It is called when either of the two buttons at the bottom-right side of the screen is clicked.

 1   function changeY(num) { 2      ball.y += num; 3      if (ball.y>0) { 4         ball.y = 0; 5      } 6   } 

When this function is called, the ball's y position is increased by the amount of the parameter passed in. If the y position is ever below the floor, then we set it equal to the floor. This is so the ball cannot go through the floor.

Finally, we arrive at the onEnterFrame event:

 1   _root.onEnterFrame = function() { 2      captureKeys(); 3      placeBall(); 4      ignoreMe(); 5   }; 

graphics/cd_icon.gif

Check out the bonus file position_with_ gravity.fla in the Chapter08 folder on the CD. It's similar to position.fla; the main difference is that this one has gravity so that the ball can bounce around in the isometric world.


This event calls captureKeys() and placeBall() in every frame. Ignore the ignoreMe() function it is just there to help display the coordinates on the screen for you to see when testing the file.

That's everything! You are now on your way to building an isometric world. It's best to make your isometric world a tile-based world. You will see an example of this in the final section of this chapter.



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