Example in Flash
Ok, time to really get our fingers
dirty and build a complex fully featured isometric environment. Ok, not really.
It probably won't be any more complex than what's been mentioned previously, at
least not at first, though it will be set up in a way to be more flexible and
easier to throw in more methods once discussed. Before, I said, "...the rest
will go faster and with less step by step instruction..." though I don't think I
really cohered to that. This time, that statement will be true.
So first off, since we are dealing with a gridded system based on 2 value
coordinate locations, we should set up a Point class to allow us to work with
those coordinates as a single, solid object. In this Point class will be methods
making use of those important isometric equations. The code:
toIso takes a screen-based point,
such as _x, _y coordinates or a mouse position, and returns the point as it
relates to the iso grid. toScreen takes an isometric point and returns that
point as it exists on the screen. The trans argument decides whether or not the
point being used is itself transformed into the new point or if its just being
used to return a new separate point with the transformations applied. round
obviously rounds the point and too includes the trans argument. This would be
used to get an absolute grid location from something like a mouse point
location, like that which was done in the previous Flash example of placing the
ball where the mouse was pressed. Of course, also included is the toString
method so that if we ever try to trace a point directly, we'll get a formatted
string displaying the contents of our point object and not "[object Object]".
As this class is set up, it accesses spacing directly as a free, single variable
from that scope. By doing so, there lacks the immediate ability to change that
easily based on different grid systems. If you needed to do that, then you might
consider developing an isometric grid class to let you create distinctive grid
systems and incorporate these functions in that. Again, it all depends on the
level of complexity that you plan for yourself and what you intend to achieve.
Here, I'm assuming a single consistent spacing-based grid which wont change or
need to be so complex to have a separate class to define it with.
Since we'll need to move movie clips around on the screen based on these points,
we should set up our movie clips to be able to handle them a little more easily.
Notably, we should be able to tell a movieclip to set its location to a point
and have it just happen. With that, we can include a property to allow us to get
the mouse location as a point from the scope of that movieclip:
Now, to set the position of the
movieclip on the screen with a point object, we just use myMc.loc = myPoint;
using myMc.loc alone to retrieve the point. myMC.mouseLoc will give the mouse
location within the scope of that movieclip as a point. As a quick example of
setting a movie clip to grid position (2,3), you can use:
myMc.loc = new
This makes up the basic foundation
for movieclip to grid relations through their point locations. Now we can start
to encompass more functionality, namely, at this point, collision grids. This
really doesn't take much since all we have to do is check within a certain point
in an array and see if its a valid value or not:
Next lets implement the key
controls, but also include a method to turn the character to face in the
direction of movement. This will be based on the key pressed, but instead of
stringing everything out in if statements, we can consolidate a little using
some math. At this point we also have the option of allowing a character to be
moved diagonally on the screen, in both an x and y movement at the same time.
That would mean drawing more character positions though, and I'm not up for
Included is not only key detection,
but also methods of moving absolutely or relatively. Absolutely we already have,
absolutely has yet to be included:
KeyMovement isn't prototyped because that will just be assigned directly to an
onKeyDown. Other than that you have a function attached to the key object to
return a point indicating the direction of the arrow keys using 1 and -1 to
distinguish between positive and negative movement, and two new Point
prototypes, one which adds two points and one which converts the point to a
frame number. This is the math I was talking about. What the point.toFrame does
is takes that point from the Key function (direction) and converts it to one of
4 frames which the movieclip is then told to gotoAndStop at. Because we have
only 4 possible directions, only 4 possible frames can come out of the 4
possible points - and those frames are 1 (left), 2 (down), 4 (up) and 5 (right).
3 is an empty frame though will never get hit unless toFrame is called and both
x and y values are 0.
This won't happen because of the if
(dir) check in Key.movement, however the possibility still exists to use that
method to cause a movieclip to go to frame 3 if you need. Though its not the
most efficient way to handle the frames (straight if/elses would be faster
though like thousandths of a second) its crafty and takes up little space. On
top of this we can include another Movieclip prototype to let us know what
direction it's in by its frame number.
I'll just use a case statement here
I also included some point functions
to return direction points associated with those directions, much like Key.LEFT
and Key.RIGHT but since they are objects and not basic values, a function is
needed to return a new object of that type and not a reference to the actual
Point.LEFT or Point.RIGHT etc.
One last thing before going to bed. There's still more to cover, most notably
fluid movement (not jumping directly from grid space to grid space) and possibly
some path finding, but first lets finish up this Point driven example. The last
thing is an action grid - setting a space for an action and then initiating that
action when the user tries (whatever it is that allows them to do so).
So here we go:
Yeah, that's pretty much it.
Basically all you do from this is great a new grid and assign a certain position
to be the action for that spot. Then you simply run the action in that grid
associated with the players loc when its tried.
If no action is set in that grid
space in the actionsGrid, nothing happens. What the new Point.equals prototype
allows you to do is within your defined function check for the direction of the
character to be correct for calling that action. This can be used easily
checking to see if the character's direction equals a preset Point.LEFT or