It is currently Sun Jan 20, 2019 1:03 pm

 All times are UTC - 7 hours

 Page 1 of 1 [ 9 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 5:20 am

Joined: Sun Nov 25, 2018 9:13 am
Posts: 2
I am programming a metroid clone in C, and need some help with handling slopes.

A little info:
The player has a top-left origin, and a collision rectangle given as an x, y offset, width, and height. He's about
2 tiles tall and 1 tile wide. The TILE_SIZE is 16 pixels. Only whole pixel movement is possible.

The method I currently have for background collision is taken from what I have read on this forum.
It is the basic step x before y eject if solid algorithm, checking along the edges of the collision rectangle,
though I have included the psuedo-code of the version I use below,
just in case you have ideas for improvements.

BG collision algorithm (pseudo-code)
Code:
1. Add x velocity to x position.
2. Compute corners of collision rectangle.
3. Define a point p as the top-right (or top-left for neg. velocity) corner.
---4. Is the tile at point p solid? If so, eject the player along x-axis and go to 7.
---5. Otherwise add TILE_SIZE pixels to the y-coordinate of p.
---6. If p is below the collision rectangle snap it to the bottom side then set a flag that this is the last horizontal check. Go to 4.
7. Add y velocity to y position.
8. Re-compute corners of collision rectangle.
9. Define a point p as the bottom-left (or top-left for neg. velocity) corner.
---10. Is the tile at point p solid? If so, eject the player along y-axis and go to 13.
---11. Otherwise add TILE_SIZE pixels to the x-coordinate of p.
---12. If p is to the right of the collision rectangle snap it to the right side then set a flag that this is the last check. Go to 10.
13. Return.

This algorithm seems to work fine for ordinary solid, rectangular blocks and speeds less than TILE_SIZE.
But whenever I try to introduce 45 deg. slopes I always get buggy / game-breaking results...

Q:
Should I check along x-axis before y-axis if I am adding slopes?
Do I ignore slopes in the horizontal step and snap the y-position if colliding with slope in the vertical step?
What x position should I use as how far up/down the slope you are?
Do I need an entirely new algorithm? (like stepping x and y at the same time with smaller increments?)

So far the most stable result I have been able to get is to increment vertical-position during the horizontal step if colliding with a slope,
and skip the vertical step entirely if a slope was encountered in the horizontal step.
However if you stop moving left or right you are just ejected up from the slope this way (floating "in air" over it), and there is
no way to walk down a slope. I have no idea how to do sloped ceilings.

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 8:12 am

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 546
Location: Central Illinois, USA

_________________
My games: http://www.bitethechili.com

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 9:57 am

Joined: Wed Sep 07, 2005 9:55 am
Posts: 351
Location: Phoenix, AZ
I'm not sure how one would do it with just four collision points, I used eight. These will hold the values of the metatiles at the points top-left, top-middle, top-right, mid-left, mid-right, bottom-left, bottom-middle, bottom-right for the object being tested:

Code:
unsigned char mt_tl, mt_tm, mt_tr;
unsigned char mt_ml,        mt_mr;
unsigned char mt_bl, mt_bm, mt_br;

My system defines slope heights per x pixel for each sloped metatile to allow for things like curves.

LEFT, RIGHT, TOP, BOT are macros that test if that side of a metatile tile is solid from that direction. This allows for metatiles that can be jumped through, but not fallen through. SLOPE is a macro that tests if that metatile is sloped or not. Here's the basic pseudo-code of it:

Code:

get mt_bm

if (going_right)
{
get mt_tr, mt_mr, mt_br
if ( LEFT(mt_tr) || LEFT(mt_mr) || (!SLOPE(mt_bm) && LEFT(mt_br)) )                       // cancel out left ejection if bot-mid is in a slope, allowing right movement
eject_left
}
else if (going_left)
{
get  mt_tl, mt_ml, mt_bl

if ( RIGHT(mt_tl) || RIGHT(mt_ml) || (!SLOPE(mt_bm) && RIGHT(mt_bl)) )                   // cancel out right ejection if bot-mid is in a slope, allowing left movement
eject_right
}

if (falling_down)
{
get mt_bl, mt_bm, mt_br

if (SLOPE(mt_bm))
{
x_pix = object->mid_x() % 16;                     // translate object mid-x pos to the x pos within the metatile
dy = s_slopetbl[INDEX(mt_bm)][x_pix & 0x0F];      // get the height of the metatile at that position
y_bits = object->bot() % 16.0f;                   // translate object bot-y pos to the y pos within the metatile

if (y_bits > dy)                                  // if the player has sunk into the slope
{
object->add_to_y(dy - y_bits);                  //   set player at top of slope
m_vel.y = 0;
if (m_acc.y > 0) m_acc.y = 0;                   //   ***this allows negative y acc for jumps, but not positive for falls***
}
eject_up                                          // normal upward ejection
}
else if (TOP(mt_bl) || TOP(mt_bm) || TOP(mt_br))
eject_up

}
else if (rising_up)
{
get mt_tl, mt_tm, mt_tr

if (BOT(mt_tl) || BOT(mt_tm) || BOT(mt_tr))
eject_down
}

There is no support for sloped ceilings, but I guess I would just handle them the same as slopes but in reverse.

_________________
. That's just like, your opinion, man .

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 1:46 pm

Joined: Sun Nov 25, 2018 9:13 am
Posts: 2
never-obsolete wrote:
I'm not sure how one would do it with just four collision points, I used eight.

I don't use 4 collision points specifically, instead I sample points along one side of the collision rectangle with spacing at most equal to TILE_SIZE, and clamp the result so the sampled point is always on the line. Your idea about LEFT/RIGHT/BOTTOM/TOP solidity sounds very good, and storing the tile heights seems like a very good system too. I think I will at least need BOTTOM/TOP solidity for one-way platforms.

I got OK results by completely ignoring the slope tiles in the x-step and y-step of the collision routine, and instead doing another check afterwards specifically for slope tiles using only the corners, were I eject the sprite upwards on the y-axis if its below the slope line, or for ceiling slopes eject the sprite downwards. It does mean a slope without any solides near it you can walk right through however... How do you make the sprite stick to the slope? Do you use gravity?

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 6:37 pm

Joined: Fri May 08, 2015 7:17 pm
Posts: 2390
Location: DIGDUG
If I were going to check a point on a slope, I would have a Y array (8 bytes, or maybe 16) of collision points for every Y level.

Example \ = 0,1,2,3,4,5,6,7
(solid bottom left)

So you know which block the point is in, the low nibble of Y position should tell you the exact X point is collision. Let's say the Y pos. of point is \$45, we check the 5th byte, which is 5. If the X position is °< \$x5, collision. If it is > \$x5, no collision. You adjust up.

Similarly, you could think of the BG as vectors (points and lines), and have arbitrary angles. To check collision, you just need to decide which to points you are between, and generate the Y array on the fly with a trigonometry LUT.

Possibly the NES is too slow for this sort of thing.

_________________
nesdoug.com -- blog/tutorial on programming for the NES

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 7:32 pm

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 354
Location: Rio de Janeiro - Brazil
This totally reminds me of the famous article https://games.greggman.com/game/programming_m_c__kids/

The way I understand it, they made it so you have an "onground" flag. If the player is onground, just set the Y position based on the X position by looking in the correct table for the tile the player is walking on. That way you can have the ground on any shape, even pretty curves (curves may make it harder to detect a landing).

_________________

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 8:14 pm

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11094
Location: Rio de Janeiro - Brazil
This is another great source of ideas on how to implement slopes: http://info.sonicretro.org/SPG:Solid_Tiles

Sonic had quite advanced physics for the time, but its collision system is pretty straightforward, specially if you disregard rotation. Sonic sticks to the floor, and every slope has an array of heights, that's used to control the Y position of objects that are on the ground, and to detect when objects collide with the floor coming from above so that their state switches from "off the floor" to "on the floor". Each slope also has an angle value, which can be used to accelerate or slow down objects (most objects ignore this, only Sonic/Tails/Knuckles really react to the different angles).

Slopes in M.C. Kids are kinda poorly implemented IMO, you can code a more robust/versatile system without necessarily making things any more complex. Both Sonic and M.C. Kids have bugs in their slope collision systems though, and those are mentioned in the respective articles. I've come up with my own solution to solve Sonic's problem: when walking off pointy edges (i.e. the leading sensor point that was making contact with the floor has lost contact), remember the height of the last column of the slope and its X coordinate, and keep using that as the height of the floor until the trailing sensor point crosses the X coordinate of that column, when you can go back to checking the floor height normally.

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Thu Nov 29, 2018 8:57 pm

Joined: Wed Sep 07, 2005 9:55 am
Posts: 351
Location: Phoenix, AZ
Quote:
How do you make the sprite stick to the slope? Do you use gravity?

Yes. Gravity moves the object down, causing bottom-middle to register a slope has been hit. Then the slope handling code snaps the Y coordinate to the top of the slope if Y is considered to be in the solid part of the metatile at that particular X. Then the normal collision code causes the object to be ejected up and out of the solid tile.

_________________
. That's just like, your opinion, man .

Top

 Post subject: Re: Implementing 45 degree slopes in platformerPosted: Fri Nov 30, 2018 2:20 am

Joined: Thu Sep 15, 2016 6:29 am
Posts: 855
Location: Denmark (PAL)
nesrocks wrote:
The way I understand it, they made it so you have an "onground" flag. If the player is onground, just set the Y position based on the X position by looking in the correct table for the tile the player is walking on. That way you can have the ground on any shape, even pretty curves (curves may make it harder to detect a landing).

That's absolutely the way to do it if you are going for a classic video game design. Remember playing those games where walking down stairs or steep slopes let you occasionally drop down a pixel, making it impossible to jump if you mistimed your input while falling? Yeah, you don't want that.
Of course if you want to make really steep slopes that you want the player to be able to run off of, those should be an exception, or the movement would be weird (which it is in a lot of games).

I mean you could go for a realistic physics simulation, but why do that? It's a video game.
I'd imagine most platformers already have an "onground" flag anyway, for jumping purposes.

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 9 posts ]

 All times are UTC - 7 hours

#### Who is online

Users browsing this forum: No registered users and 3 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum

Search for:
 Jump to:  Select a forum ------------------ NES / Famicom    NESdev    NESemdev    NES Graphics    NES Music    Homebrew Projects       2018 NESdev Competition       2017 NESdev Competition       2016 NESdev Competition       2014 NESdev Competition       2011 NESdev Competition    Newbie Help Center    NES Hardware and Flash Equipment       Reproduction    NESdev International       FCdev       NESdev China       NESdev Middle East Other    General Stuff    Membler Industries    Other Retro Dev       SNESdev       GBDev    Test Forum Site Issues    phpBB Issues    Web Issues    nesdevWiki