Sign in to follow this  
GenuineXP

Help with Beginning Isometric Game

Recommended Posts

GenuineXP    262
Hello. I'm working on a remake of the old DOS game called Jetpack, and I decided awhile ago that I wanted to make my game isometric. I'm using SDL and I've created very simple games before, but I'm still a beginner for the most part. Any guidance is greatly appreciated. My approach so far seems to be too simplistic. For positioning, I'm using some simple equations I came up with awhile ago. Here, x and y are 2D screen coordinates, while w, z, and u are 3D isometric coordinates. Also, a is the ratio of the height to width of each tile's base in the system. For my game, this is 1 / 2. c is a vertical compression factor. K is a 2D vector from the origin of the view port to the 2D position of the isometric origin of the projection.
x = w - z + Kx
y = aw + az + Ky - uc
w = ax + y + u - aKx + Ky
z = y + u + ax - x - Kx - aKy
u = [ a( w + z ) + Ky - y ] / c
This all worked beautifully when I first employeed these equations to create a landscape made of polygons. It made it very simple and quick to create randomly generated terrain. Now I'm using sprites for my tiles, all of which are "cubes". Positioning works just fine with these equations, but I can't draw my tiles correctly at all! I thought if I sorted the tiles by their y position on the screen plus their u position (height), I could draw them correctly. It seems to work... but not entirely. There are still stray tiles here and there that aren't drawn in the correct order, and if some tiles move, other tiles occasionall flicker as the sort churns out different results. I'm new to isometric games, although I created a few with the infamous Game Maker before using similar methods that worked just fine. I've been glancing at some documents on GameDev about drawing isometric maps, and it seems that using bitmasks is important. Really, I just need help with isometric games in general. How do I create a bitmask? Should my tiles be broken down into different sprites to be drawn correctly? I don't need to be able to create tiles of varying heights, but I would like to be able to have overhangs and underpasses that the player can easily walk through. (I think this will be easy because I'm using these equations, and I can just use mathematical collision checking.) I need somewhere to start before I get bogged down. :-) Any suggestions? I don't want to get too far into designing my engine until I think I actually know what I'm doing. If you'd like to see a screenshot of what I have so far, just ask. Thanks!

Share this post


Link to post
Share on other sites
haegarr    7372
following a tip of how to compute an index for sorting.

If an index x is running from the farthest tile to the right (near), and an index y is running from the farthest tile to the left (near), like illustrated here for pairs of x/y

0 0/0
1 0/1 1/0
2 0/2 1/1 2/0
3 0/3 1/2 2/1 3/0
4 0/4 1/3 2/2 3/1 4/0
...


(hopefully the indentation is displayed correctly ;-) than you can notice that the sum of the indices (shown at the left) is increasing from far to the near!

So sort your tiles by the sum of those kinds of indices and you can draw them from farthest to nearest. The fact that several tiles have the same sum plays no role since these tiles do not overlap.

Hopefully I have interpreted one of your problems right?! I could not determine exactly what you mean with "sorted the tiles by their y position on the screen plus their u position", so I hope I don't given you a tip you already knows ...

EDIT: The screen position could be computed from these indices, too (if you want). The vertical position of the _base_ of the tiles is propertional to the sum x+y of the indices (that is why sorting this way is possible), while the horizontal position is propertional to the difference x-y. You need then only to multiply that with the half of the projected width and height, resp., and add the absolute position of the room, similar to this:
h := h0 + half_width * ( x - y )
v := v0 - half_height * ( x + y )

Share this post


Link to post
Share on other sites
GenuineXP    262
Thanks for the reply, haegarr. :-)

I think I was just a bit too verbose when I posted this. :-P Basically, I can work with isometric positions just fine. The problem I'm having now is just with displaying my tiles correctly. I'll post a screenshot a little later; maybe that will help.

When I said I sorted the tiles by their y and u positions, I meant that I sorted by the sum of the actual y position on the screen and the 3D z coordinate (u) of each tile. If you're dealing with only one layer of tiles (all tiles are at the same height), then sorting those tiles by their y position on the screen works. To adjust for differing heights, I just added the u position of my tiles.

I'm going to see if I can rework my sorting algorithm. It's slow, and it may be faulty.

In your diagram, haegarr, it seems that I can just add the isometric x and y coordinates of my tiles and sort by that. I tried it, and it gave me the same results as when I sorted by the sum of the y position on the screen and the isometric z coordinate! This leads me to believe that my sort is faulty. I'll try a bubble sort and see what happens. It's very slow, but I know I can code it correctly.

Thanks for the help! Any other suggestions or comments are still greatly appreciated! :-)

Share this post


Link to post
Share on other sites
GenuineXP    262
Aha! The sorting algorithm I created was faulty! I just implemented a simple bubble sort and it works just fine!

Sorting by the isometric x and y coordinates is much simpler and easier, haegarr. Thanks for the tip!

Any other advice is welcome. I'm sure I'll run into more problems soon. :-P

One thing I need to work on is joystick control. I can move a tile around with my gamepad's analog sticks, but (with the exception of the isometric z axis), moving the stick straight up moves the tile in a diagnol direction. Moving the stick diagonally moving the tile in a horizontal or vertical direction.

Any ideas on how to rememdy this? Once I implement the hero, it will lead to some complicated and cumbersome controls. :-
Thanks again!

Share this post


Link to post
Share on other sites
haegarr    7372
Quote:
Original post by GenuineXP
One thing I need to work on is joystick control. I can move a tile around with my gamepad's analog sticks, but (with the exception of the isometric z axis), moving the stick straight up moves the tile in a diagnol direction. Moving the stick diagonally moving the tile in a horizontal or vertical direction.

Ahem, what does this mean? It sounds that you map the horizontal / vertical stick positions to horizontal / vertical co-ordinates _before_ the isometric transformation is applied!? But you want the tile to move horizontally / vertically _on the screen_ instead?

If so, look again at the diagram I've posted earlier. Moving to the right on the screen means to increment the x index and to decrement the y index. Moving to the left means to decrement x and to increment y. Moving straight up means to decrement both x and y, and incrementing both results in moving straight down. With this knowledge and the formaulas given in the appendix of my previous post you can position tiles this way.

If incrementing / decrementing the index the tile will hop from one valid location to the next. If they should scroll smooth (i.e. not using a tile but an avatar), you can do the same but use less constants to multiply with (see half_width and half_height; they make the tile hop the amount a tile is wide / high).

If, on the other hand, you mean something different, then I need a hint that sound less vague to me, please.

Share this post


Link to post
Share on other sites
GenuineXP    262
I'm calculating the screen position very similarly to the way described in your appendix. :-)

I'm sorry that I'm being so vague and unclear. :-P I'll try to clear this up.

I'm allowing the joystick to move a particular tile only because I haven't fleshed out a character or avatar yet. Each game object in the engine has a velocity vector as well as position. I'm allowing the joystick to minipulate this vector which directly affects the isometric position of the tile I'm moving (before any tranformation to screen coordinates).

If we forget about moving along the isometric z axis (height), I can move the tile around with one analog stick. Moving the analog stick left and right moves the tile along the isometric x axis, so the tile appears to move diagonally across the screen. The same goes for moving the stick up and down, except that the tile is moving along the isometric y axis.

My question is, what's a good way to map joystick movement to a character or avatar? I'd like it if moving the analog stick left and right would actually move the tile along both the isometric x and y axes so that the character appears to move horizontally across the screen (and vertically when moving the analog stick up and down). See what I mean? Moving the analog stick diagonally would move the character along only one isometric axis.

Sorry. Is this clearer? :-.

Thanks again for your help!

Share this post


Link to post
Share on other sites
haegarr    7372
@GenuineXP: It is actually what I meant to understood from your previous description, and hence my previous post is ok in this sense.

The only thing is that I haven't known that you are using a velocity vector. Well, assuming that those vector defines a movement (dx,dy) in 2D for simplicity, you need only to map the index issue to the vector components:

// reset
speed = 5.0f; // units per frame
velocity.x = velocity.y = 0.0f;
// compute deltas from stick position
if(stick_is_pushed_right) {
velocity.x += 1.0f;
velocity.y -= 1.0f;
}
if(stick_is_pushed_left) {
velocity.x -= 1.0f;
velocity.y += 1.0f;
}
if(stick_is_pushed_up) {
velocity.x -= 1.0f;
velocity.y -= 1.0f;
}
if(stick_is_pushed_down) {
velocity.x += 1.0f;
velocity.y += 1.0f;
}
// normalize
float norm = sqrt(velocity.x*velocity.x + velocity.y*velocity.y);
velocity.x *= speed/norm;
velocity.y *= speed/norm;


Notice that stick pushing alters the velocity vector the same way as I've posted previously for changing the indices. Notice furthur that the 4 "if" clauses are independent, so that a concurrently pushing right _and_ up (as an example) will yield in (0,-2); however, due to the following normalization the vector is suitably reduced to (0,-1). The last step is to multiply the vector with the scalar speed (I assume you have already a speed value, but I needed to include one for clarity).

Maybe the signs are not working for you, so you possibly have to permute them. However, I think in principle it is what you are looking for.

EDIT: Well, I actually agree that the horizontal / vertical stick pushing should yield in the same motion on screen. My one and only isometric game some years ago was mouse controlled: Cliking on the avatar and dragging the mouse had pulled the avatar in that direction. In principal, that was in correspondence to your way of steering.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this