Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

convert Cartesian width and height to Isometric

I'm trying to create an Isometric game in the SDL graphics library.

When you render in SDL you require a source rectangle and a destination rectangle. The source rectangle is the portion of the texture you have loaded that you wish to render and the destination rectangle is the area on the screen you are rendering to. Rectangles simply consist of 4 properties, X position, Y position, Width, and Height.

Now say I have a Cartesian destination rectangle with these coordinates:

X=20, Y=10, Width=16, Height=16

Now say I wanted to convert this to Isometric. To convert the X and Y coordinates I would use:

isometricX = cartX - cartY;
isometricY = (cartX + cartY) / 2;

Now what I don't understand is what I would do to convert the Cartesian Width and Height to Isometric Width and Height to create the illusion that the view port is being moved 45 degrees to one side and 30 degrees down, creating the Isometric look.

EDIT: I'd like to clarify my question a little, so when I convert the Cartesian Coordinates to Isometric I change this:https://i.sstatic.net/I79yK.png to this:https://i.sstatic.net/ZCJg1.png. So now I am trying to figure out how to rotate the tiles so they all fit together and how I need to adjust the Height and Width to get this to happen.

like image 228
deery50 Avatar asked Mar 23 '26 06:03

deery50


1 Answers

To start with you'll need these operations to convert to and from isometric coordinates:

isoX = carX + carY;
isoY = carY - carX / 2.0;

carX = (isoX - isoY) / 1.5;
carY = isoX / 3.0 + isoY / 1.5;

right-angled corners in the top-left and bottom-right become 120 degrees, the other two corners become 60 degrees. the bottom-right corner becomes the bottom corner, the top-left corner becomes the top. this also assumes that y increases going up, and x increases going right (if your system is different, flip the signs accordingly). you can verify via substitution that these operations are eachothers inverse.

for a rectangle you need 4 points transformed - the corners - as they will not be 'rectangular' for the purposes of SDL (it will be a parallelogram). this is easier to see numerically.

first, assign the corners names of some sort. i prefer clockwise starting with the bottom-left - this coordinate shall be known as C1, and has an associated X1 and Y1, the others will be C2-4.

C2 - C3
|    |
C1 - C4

then compute their cartesian coordinates...

X1 = RECT.X;
Y1 = RECT.Y;

X2 = X1; // moving vertically
Y2 = RECT.Y + RECT.HEIGHT;

X3 = RECT.X + RECT.WIDTH;
Y3 = Y2; // moving horizontally

X4 = X3; // moving vertically
Y4 = RECT.Y;

and lastly apply the transform individually to each coordinate, to get I1, I2, I3, I4 coordinates...

iX1 = X1 + Y1;
iY1 = Y1 - X1 / 2.0;
// etc

and what you end up with is on-screen coordinates I1-4, that take this shape:

    I2
  /    \
I1      I3
  \    /
    I4

But unlike this shoddy depiction, the angles for I4 and I2 will be ~127 deg, and for I1 and I3 it should be ~53 deg. (this could be fine-tuned to be exactly 60/120, and depends on the 2.0 factor for carX when computing isoY - it should be sqrt(3) rather than 2.0 but meh, close enough)

if you use the inverse transform, you can turn back the I1-4 coordinates into C1-4, or locate a world coordinate from a screen coordinate etc.

implementing a camera / viewport gets a little tricky if only at first but it's beyond what was asked so i won't go there (without further prodding)...

(Edit) Regarding SDL...

SDL does not appear to "play nice" with generalized transforms. I haven't used it but its interface is remarkably similar to GDI (windows) which I've played around with for a game engine before and ran into this exact issue (rotating + scaling textures).

There is one (looks to be non-standard) SDL function that does both scaling and rotating of textures, but it does it in the wrong order so it always maintains the perspective of the image, and that's not what is needed here.

Basic geometry will be fine, as you've seen, because it's fills and lines which don't need to be scaled, only positioned. But for textures... You're going to have to either write code to render the texture one pixel at a time, or use a combination of transforms (scale after rotate), or layering (drawing an alpha-masked isometric square and rendering a pre-computed texture) and so on...

Or of course, if it's an option for you, use something suited for raw geometry and texture data like OpenGL / Direct3D. Personally I'd go with OpenGL / SFML for something like this.

like image 97
Xeren Narcy Avatar answered Mar 24 '26 18:03

Xeren Narcy