I am trying to implement slopes into my 2D platformer using Godot 3.0.

I currently use `move_and_slide()` to update my position since I didn't have any luck designing custom collision response for slopes with `move_and_collide()`.

Using `move_and_slide()`, I've noticed that my player moves slower proportional to the steepness of the slope. I don't like this.

So, my question: Assuming `move_and_slide()`, is there a way to adjust my Player's velocity while on the slope so that his velocity up the slope diagonal is an upwards projection of his would-be horizontal movement, or, alternatively, scaled to this would-be horizontal movement?

I had planned to do this using `move_and_collide()`, projecting the velocity remainder onto the collision surface's plane using a normal and `Vector2.slide()`, but, like I said, I didn't have much luck. (Ascending slopes worked fine, but I got jittery behavior when descending them, as well as slid down them during idle.) Ideally, I'd like a way using `move_and_slide()`.

I know that I can get the collision data (collision normal, remainder, etc.) used in the `move_and_slide()` by calling `get_slide_collision()` after it. Maybe there is some way to use this data to achieve my desired result?

in Engine
edited

I managed to get my desired movement on slopes using `move_and_collide()` rather than `move_and_slide()`.

Here is the code, roughly:

``````var collision = move_and_slide(vel * delta)
if collision:

# get collision info
var normal = collision.normal
var remainder = collision.remainder
var horizontal_movement = abs(remainder.x)

# reset y vel so it doesn't keep accumulating
vel.y = Vector2(0, vel.y).slide(normal).y

# get movement vector along slope
var remaining_movement = remainder.slide(normal) # get projection of remainder on slope
remaining_movement = remaining_movement.normalized()  # normalize projection
remaining_movement *= horizontal_movement # scale projection to horizontal distance
move_and_collide(remaining_movement) # move the sprite along the slope
``````

To prevent my sprite's animation from changing to its descend animation in the event of losing contact during the descent of a slope, I use a 16-pixel long downward raycast vector to set a `grounded` boolean, rather than rely on Godot's in-built `is_on_floor()`

by (1,602 points)
edited

Hi.

For now to achieve control of velocity in slopes a use a combination of nodes. First I use horizontal and vertical ray cast to get collision normal (and not only the normal obtained with KinematicBody2D). Base on the horizontal normal and the vertical normal, I set tiles type (you can use enum o variables to do that). Then I control the way (and linear velocity) of the actor (character) when up slope and down slope.To control the linear velocity I use lineal equation of `y = mxb` and `tan(normal.angle())`. For example, if the slope is 45° it means that the actor have to up slope in y axis the same velocity as it advance on x axis. That is because `tan(45°) = 1` so for every unit (pixel) advanced on x it have to advanced on y. Something like this:

``````if is_on_slope and is_up_slope:
var x = speed
var y = tan(normal.angle()) * speed
linear_velocity = Vector2(x, y)

# y = mx OR y = tan(angle)x
# if the speed = 100 and normal.angle() = 45°, then tan(angle) = 1, so y = 1x (https://ggbm.at/QHavT7Ay)
# if the speed = 100 and normal.angle() = 25°, then tan(angle) = 0.47, so y = 0.47x. Means that x = 100 and y = 0.47 * 100 (https://ggbm.at/fEU94NHz)
# if the speed = 100 and normal.angle() = 65°, then tan(angle) = 2.14, so y = 2.14x. Means that x = 100 and y = 2.14 * 100 (https://ggbm.at/b5SsMZC5)
``````

For down slope a resolve for x and y = speed.

Then you want to take some control for consecutive slopes (one beside the other) and when the character is running on slope and the next tile is a slope with different tangent.

Then if you want to go more fast or more slow, you can play with `y = mx` adding or subtracting speed.

If you want, you can use trigonometry to, where `x = cos(normal angle) * velocity.x` and `y = sin(normal angle) * velocity.y` and so on...

Forgive my english because I am not a native english writer. Have nice time coding on your game!

by (152 points)
edited by