Player character hovering one pixel above the ground occasionally?
Asked Answered
K

5

0

Hi everyone,

I've been following the following tutorial to teach myself a bit of Godot (3.5), https://www.codingkaiju.com/tutorials/beginner-godot-2d-platformer/#Create_the_Player But I've been having a problem where my player sprite sometimes hovers a single pixel above the ground. The player is a KinematicBody2D, the terrain is a TileMap.

Screenshots as example:

My movement code is the following:

extends KinematicBody2D

export var move_speed := 100
export var gravity := 2000
export var jump_speed := 550

var velocity := Vector2.ZERO

func _process(_delta):
    change_animation()

func change_animation():
    if velocity.x > 0:
        $AnimatedSprite.flip_h = false
    elif velocity.x < 0:
        $AnimatedSprite.flip_h = true
    if velocity.y < 0:
        $AnimatedSprite.play("jump")
    else:
        if velocity.x != 0:
            $AnimatedSprite.play("walk")
    else:
        $AnimatedSprite.play("idle")

func _physics_process(delta):
    velocity.x = 0
    if Input.is_action_pressed("move_right"):
        velocity.x += move_speed
    if Input.is_action_pressed("move_left"):
        velocity.x -= move_speed

    velocity.y += gravity * delta

    if Input.is_action_pressed("jump"):
        if is_on_floor():
            velocity.y = -jump_speed

    velocity = move_and_slide(velocity, Vector2.UP)

I've tried decreasing the pixel margin the physics simulation uses, turning off pixel perfect rendering, etc... but none of them seem to work. It doesn't seem to be related to the animation either since removing all of them has the issue subsist. The collision shape is a simple rectangle as well.

If I turn on collision shapes it seems to always happen when standing on or near the boundary between two tiles.

Kelwunn answered 17/4, 2023 at 18:49 Comment(0)
K
0

I've managed to isolate it to the camera behaviour. I have a Camera2D attached to my Player, if I have drag margin v enabled the behaviour described above will happen.

I imagine scripting my camera movement to always be at whole integer positions could solve this instead of using drag margin? Does anyone have experience with this?

Kelwunn answered 18/4, 2023 at 20:16 Comment(0)
S
0

Kelwunn If I turn on collision shapes it seems to always happen when standing on or near the boundary between two tiles.

And in those cases are the collisions shapes touching or is there a gap between them too? Seems like this could be caused by a collision shape having an edge in between pixels that makes it look flush or not depending on how it gets rounded. Is the player's collision box's y extent an odd number?

It also may be worth trying move_and_slide_with_snap, although jumping would require a bit more handling:

As long as the snap vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting snap to (0, 0) or by using move_and_slide instead.

I kind of suspect the camera tweaks are just masking the issue, although if you can get it to do that consistently I guess that's a good a fix as any.

Sharasharai answered 19/4, 2023 at 0:40 Comment(0)
K
0

Sharasharai

The collision shapes themselves have a 1 pixel separation. The collision box y extend is an odd number, I'll have a test to see if making it a round number prevents the issue.

Kelwunn answered 19/4, 2023 at 21:29 Comment(0)
S
0

Kelwunn Actually never mind the odd number, I think what I was thinking of was in a project where the shape was scaled to 50%. I took a look at that tutorial project though and think the asset itself might be a bit screwy, the player sprite image is supposed to have 3 vertical frames but it's 50 pixels tall, which does not divide evenly into 3. And if you look at the screenshot at the top of the page it also looks like the player is hovering above the ground, so I think you might need to edit the asset to get a pixel perfect collision.

Sharasharai answered 20/4, 2023 at 1:42 Comment(0)
K
0

Sharasharai

Thank you for all the help so far, sadly replacing the asset by a regular 20x16 rectangle I can still replicate it, though it seems less common. Interestingly enough while moving left or right the sprite raises itself up a single sprite, I don't know if this is expected behaviour with how move_and_slide works...

I imagine in the end it's because of floating point physics which doesn't really matter in most cases. I suppose one would be best to code their own physics if you wanted pixel perfect movement; I did find a video series about it:

Kelwunn answered 20/4, 2023 at 22:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.