One Way Platforms and Bouncy Platforms - #2
Conversation
I cut up some of the art and made some one-way platform lookin things out of the existing art (not complete)
I did this by detecting when the one way platform should be in the player's collision mask, and put the one way platforms on layer 2 (also i named the layers and added a const for the oneway platform layer number to avoid magic numbers in player.gd)
cuz it was causing side-falling issues. you shouldnt bump into them like that
drew a special_tiles png for bouncy platforms and other things in the future that have special properties. added bouncy collision math in the player for collisions against collision layer 3.
There was a problem hiding this comment.
Hey Lonk!
I really appreciate you taking the time to improve the gameplay of this by adding in one-way and bouncy platforms. But, this is meant to be a tutorial focused project. Improving the gameplay helps improve the fun of the game, but is also kind of out of the scope for what I intended. Again, thank you, this change is awesome.
I apologize for taking so long to review this PR, it was a tough one. I really didn't like the double move_and_slide() which we discussed over Discord and I took some time to implement a cleaner soltution.
My fix is to implement a boolean flag has_pending_bounce that it flipped when colliding with a bounce platform.
Then on the next physics frame we do not apply gravity if this boolean is true which lets the player bounce as expected.
# Apply pending bounce from last frame FIRST
if has_pending_bounce:
velocity = pending_bounce_velocity
has_pending_bounce = false
elif not is_on_floor():
# Apply normal gravity
velocity.y = min(velocity.y + get_gravity().y * gravity_scale * delta, max_fall_speed)This change also removes the need for the _bouncy_position_correction function.
There's some small formatting and nitpicks in the review I'd like you to address before a merge.
I'd like you to try to implement the has_pending_bounce flag yourself, but if you're running into trouble here's my solution: https://gist.github.com/bearlikelion/ad6f7f1e69253dc36687832c16fe8c0c
Thanks,
Mark
| if !col: return | ||
|
|
||
| # If it detects a bouncy thing, bounce. | ||
| if !(PhysicsServer2D.body_get_collision_layer(col.get_collider_rid()) & BOUNCY_LAYER): |
There was a problem hiding this comment.
Nitpick: I prefer using not to !, they do the same thing but being verbose makes it easier for me to understand and read at a glance.
I frequently still use ! though so not a major change
There was a problem hiding this comment.
This is also a double negative? I'm not sure we need this here because then it's checking collision layer on every collision, not just bouncy collisions.
| move_and_slide() | ||
| _bouncy_position_correction(pos1, pos2, col.get_normal()) | ||
|
|
||
| _on_landed() |
There was a problem hiding this comment.
Potential Bug: I think this should be wrapped in an is_on_floor() to prevent the function accidentally firing before the player collides with the platform.
| if !(PhysicsServer2D.body_get_collision_layer(col.get_collider_rid()) & BOUNCY_LAYER): | ||
| var new_vel: Vector2 = _bouncy_col_math(vel, col.get_normal()) | ||
| velocity = new_vel | ||
| move_and_slide() |
There was a problem hiding this comment.
I don't like this double move_and_slide() solution and will provide my solution in the PR review comment.
| extends CharacterBody2D | ||
|
|
||
| enum { | ||
| NULL, |
There was a problem hiding this comment.
I don't like NULL being in an ENUM. NULL = Nothing, an ENUM defines something.
There was a problem hiding this comment.
Bouncy layer is set to 4 in your bitwise math.
My solution was to implement
enum {
NULL = 0,
DEFAULT_LAYER = 1,
ONE_WAY_LAYER = 2,
BOUNCY_LAYER = 4
}
| _on_landed() | ||
| was_on_floor = is_on_floor() | ||
|
|
||
| #Handle one-way platforms |
There was a problem hiding this comment.
Space after # for readability
|
|
||
| # Handles the one-way platform functionality. | ||
| func _handle_one_way() -> void: | ||
| # The only time that a one way platform should have collision is when: its detected by the check, the player is moving downwards or resting, and the down direction is not pressed. |

So, i first messed with the sprite sheet and tileset. I added a bunch new platforms that we can use on other maps, and then put all the skinny platforms onto a unique physics layer.
The player detects the one way platform below itself, and then adds the one way platform layer to the player's collision mask if its not pressing down and the player is at rest or moving down.
I know this works because this is how i make it work for Bonk-a-Donk.
Caveats to this approach:
But, as long as all one-way platforms maintain identical thickness and the one-way check area on the player is not modified, this mechanic should function exactly as intended.
I also added Bouncy Platforms which function on a separate collision layer.
I did this by replacing move_and_slide() in _physics_process() (player.gs) with an _apply_physics() function that handles collision math and applying the physics to the player. it calls move_and_slide(), checks the resulting collision, checks if its a bouncy layer (layer 3), does collision math,calls move_and_slide() again, and then corrects final positions that got modified by the move_and_slide() so you cannot gain height with successive bounces