Jump to content
A 2021 backup has been restored. Forums are closed and work in progress. Join our Discord server for more updates! ×
SoaH City Message Board

How to determine slope angle in a tile based engine?


Arghle

Recommended Posts

Hey! I'm finding myself a bit stuck here.. Would appreciate any advice!

So from what I understand, in Sonic games each 16x16 block of tile is assigned a single angle, right?

For someone who isn't very knowledgeable of mathematics beyond basic algebra; What's the easiest way to determine the angle that a tile should give off?

If it's impossible to do without learning more advanced math, what would I need to learn?

Link to comment
Share on other sites

You need trigonometry.

It's not that much hard for common platformer games.

In Genesis, they are given by collision masks. Basically bytes showing the height of the first point and the height of the last point. And then, for full 360°, there are four modes which the player can assume - which I'm not gonna get into, but it's basically a rotation of all sensors, depending on Sonic's position, limits and etc. So imagine a platformer like Mario or Megaman for now, which are less complicated about that.

What you can imagine is that you have two lines: one a few in front of the player, other a few pixels behind the player.

The code checks for the height of the mask on the corresponding X coordinate of each line (notice that I'm not telling you here how it recognizes which tile is on the player's feet position, but I'm already assuming the engine knows!).

The player's Y position will assume the biggest height both masks. If there's only one, set it to this only one. If there's none, set angle to 0.

In Sonic games, Sonic has three speeds, which are X Speed, Y Speed and Ground Speed. Ground Speed changes directly X Speed and Y Speed (This doesn't happen in Sonic Worlds Engine), but this is a feature of the 360°ness.

You can take a sneak peek on Sonic Retro Physics Guide to understand it a bit more.

Now, about ANGLES: for a common platformer, the angle is given by the arctan of the DIVISION between the DIFERENCES of the two Y values and the two X values. You'll also need to convert it to radians, if necessary.

In pseudocode:

deltaX = pointBack.X - pointFront.X;
deltaY = pointBack.Y - pointFront.Y;

angle = arctan(deltaY / deltaX);

angleInRadians = angle * (180 / PI);

If you're using a programming language like C, C++ or Java, there might be an atan2(deltaY, deltaX) function that does the job of arctan(deltaY / deltaX) for you.

If I'm not mistaken, MMF2 has arctan.

EDIT: Stay sharp with null quotients -- meaning: deltaX. It will most likely not happen, but if you overlap the back sensor with the front sensor, you might get and undefined result on your calculation.

Link to comment
Share on other sites

Thanks so much for the explanation!! Mind verifying that I'm calculating the angle correctly? Still unsure!

isthisright_zps210a7996.png

(I enlarged the image, the markings on the sides of the tile were originally one pixel each, the tilesize is 16x16)

Also, what's the significance of converting the angle to radians? Does the ATan2 equation eliminate the need for that?

Link to comment
Share on other sites

If you have DeltaX = -15 and DeltaY = -9, then the angle is:

angle = atan(-9 / -15) = atan(0.6) = 0.54 radians

or 31 degrees (= 0.54 * 180 / pi)

I think luksamuk made a mistake; what he calls angleInRadians should be the angle in degrees. An arctan function normally returns the angle in radians, so if you need it in degrees you'll have to convert it.

Apparently the ATan2 function did give you the right angle in degrees directly, though it subtracted 180° because you gave a negative DeltaX. Normally you should calculate like this: DeltaX = X2 - X1, rather than X1 - X2. Same with DeltaY.

If you give positive numbers to the ATan2 function it should give you the right angle.

If you need the angle in radians:

angleInRadians = angleInDegrees * pi / 180

I don't know if you will need it; it depends on what you need the angle for.

By the way, here you end up with a positive angle for a downward slope. I don't know how Sonic games are made, but I'm used to the opposite: positive angles for upwards slopes and negative angles for a downward slopes, because I use a upward Y axis (basically I would have DeltaX = 15 and DeltaY = -9). Maybe that's normal for Sonic games, but you should check to be sure.

Link to comment
Share on other sites

Thanks, Core D: I really messed up on that angleInRadians thing.

There's no real significancy on converting angles to radians and vice-versa, it actually depends on which Framework/API you're using to render your game.

Taking C/C++ as an example,

void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);

requires your angle value to be in degrees, meaning you can use the direct value of double atan2(double, double).

XNA Game Studio, though, uses radians in the method

SpriteBatch.Draw (Texture2D texture, Rectangle dest, Nullable<Rectangle> src, Color color, Single angle, Vector2 origin, SpriteEffects effect, Single depth)

for example. (note: float is an alias for Single in C#)

One last thing I'd like to add: Apparently, the angles of the masks are also stored on the tiles' data, on classic Sonic games. But that's only for angle-mode changing and rendering purposes. The actual influence of ramps on speed is calculated in real-time, because Sonic can be over two pieces (16x16) at the same time. This way, you get a gradual influence of the slopes on speed.

Link to comment
Share on other sites

  • 2 weeks later...

Thanks for the replies.. currently attempting to write a program that should calculate the heights and angles of the tiles for me..

Apparently the ATan2 function did give you the right angle in degrees directly, though it subtracted 180° because you gave a negative DeltaX. Normally you should calculate like this: DeltaX = X2 - X1, rather than X1 - X2. Same with DeltaY.

If you give positive numbers to the ATan2 function it should give you the right angle.

So if I do the calculations as you suggest and still obtain a negative angle, would it be okay just to add that negative angle value to 180? Trying to find the best way to make this process as automated as possible!

By the way, here you end up with a positive angle for a downward slope. I don't know how Sonic games are made, but I'm used to the opposite: positive angles for upwards slopes and negative angles for a downward slopes, because I use a upward Y axis (basically I would have DeltaX = 15 and DeltaY = -9). Maybe that's normal for Sonic games, but you should check to be sure.

eh.. All the programming language I'm familiar with use the downward Y axis as the positive value.. This part still goes a bit over my head!

One last thing I'd like to add: Apparently, the angles of the masks are also stored on the tiles' data, on classic Sonic games. But that's only for angle-mode changing and rendering purposes. The actual influence of ramps on speed is calculated in real-time, because Sonic can be over two pieces (16x16) at the same time. This way, you get a gradual influence of the slopes on speed.

Is there still just a single angle value per tile when calculating the speed?

Link to comment
Share on other sites

So if I do the calculations as you suggest and still obtain a negative angle, would it be okay just to add that negative angle value to 180? Trying to find the best way to make this process as automated as possible!

This is how I would do it:

slopes.png

You may want to switch the positive and negative values if you're using a downward Y axis. In any case, I think it's important to keep the distinction between positive and negative angles, and between acute and obtuse angles.

eh.. All the programming language I'm familiar with use the downward Y axis as the positive value.. This part still goes a bit over my head!

I would think that depends on the engine, not on the programming language. C for example doesn't impose anything; I just prefer to use an upward Y axis because it's similar to the trigonometric circle. But either way it's fine; you just need to make sure all the calculations are consistent.

Link to comment
Share on other sites

Thanks that I will be helpful for switching movement modes! Still need to figure out if I'm calculating angle correctly as a speed modifier though..

To go into more detail, I pretty much have a one pixel sensor that I'm using to scan a set of 16x16 tiles.. it records the height value for each pixel of a tile and calculates the angle using Atan2..

Sometimes Atan2 return a negative angle value, I'm not sure if it's okay that I leave it at that value?

I feel awkward asking, but I think my physics are a bit broken, might take a while for me to figure it out on my own..

( Nice to know C works that way! I've never ventured far from Blitzmax or Monkey.. )

Link to comment
Share on other sites

You'd have to run a visual test to ensure if it works the way you want.

If you can't right now, just grab some pen and paper and convert it to an angle 0 < x < (360 or 2*pi). If the angle's different, then you might want to write a function to make the adjustments for you.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...