How do I get is_on_floor() to work properly?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jtbx

Hi all,

I’m trying to make the player rotate when they jump, then rotate back to normal when they land. I’ve finished the basic movement mechanics so far, however when the player is moving along an edge of a platform, the player rotates back and forth very fast, as if is_on_floor() is returning both True and False. This is my code:

extends KinematicBody2D

var velocity = Vector2.ZERO

const SPEED = 250
const GRAVITY = 30
const JUMPFORCE = -850

func _physics_process(_delta):
    # Check for input. If there's no input, change the animation to idle
	var is_idle = true
    if Input.is_action_pressed("move_left"):
	    is_idle = false
	    velocity.x = -SPEED
    if Input.is_action_pressed("move_right"):
	    is_idle = false
	    velocity.x = SPEED

    if is_idle:
	    $AnimatedSprite.animation = "idle"
	    if is_on_floor():
		    velocity.y = 1
    else:
	    $AnimatedSprite.animation = "walk"

	if Input.is_action_pressed("move_jump") and is_on_floor():
    	velocity.y = JUMPFORCE

	if is_on_floor() or is_on_wall():
    	$AnimatedSprite.rotation = TAU
    else:
	    $AnimatedSprite.animation = "idle"
	    $AnimatedSprite.rotation_degrees += 15
		velocity.y += GRAVITY

    velocity = move_and_slide(velocity, Vector2.UP)
    velocity.x = lerp(velocity.x, 0, 0.02)

	if velocity.length() > 0:
		$AnimatedSprite.play()
    else:
		$AnimatedSprite.stop()

	if velocity.x != 0:
		$AnimatedSprite.animation = "walk"
		$AnimatedSprite.flip_v = false
		$AnimatedSprite.flip_h = velocity.x < 0

Could someone tell me how to stop the character rotating back and forth?
Thanks in advance :slight_smile:

:bust_in_silhouette: Reply From: RandallCurtis

Apply “gravity” at a constant rate. The velocity.y = 1 during idle is probably causing an inconsistent/jittery return ofis_on_floor() since velocity.y will bounce between 0-1 every frame. Constant gravity will keep the KinematicBody in “collision” with the floor and ensure that is_on_floor() calls are consistent.

Here’s my edited code that seemed to fix the issue:

extends KinematicBody2D

var velocity = Vector2.ZERO
var grounded
var on_wall

const SPEED = 250
const FRICTION = 10
const GRAVITY = 30
const JUMPFORCE = -850

func _physics_process(delta):
	# Check for input. If there's no input, change the animation to idle
	var is_idle = true
	if Input.is_action_pressed("move_left"):
		is_idle = false
		velocity.x = -SPEED
	if Input.is_action_pressed("move_right"):
		is_idle = false
		velocity.x = SPEED

	if is_idle:
		$AnimatedSprite.animation = "idle"
	else:
		$AnimatedSprite.animation = "walk"

	if Input.is_action_just_pressed("move_jump") and is_on_floor():
		velocity.y = JUMPFORCE

	if is_on_floor() or is_on_wall():
		$AnimatedSprite.rotation = TAU
	else:
		$AnimatedSprite.animation = "idle"
		$AnimatedSprite.rotation_degrees += 15
	
	velocity.y += GRAVITY
	if is_idle:
		velocity.x = lerp(velocity.x, 0, FRICTION * delta)
	velocity = move_and_slide(velocity, Vector2.UP, false)

	if velocity.length() > 0:
		$AnimatedSprite.play()
	else:
		$AnimatedSprite.stop()

	if velocity.x != 0:
		$AnimatedSprite.animation = "walk"
		$AnimatedSprite.flip_v = false
		$AnimatedSprite.flip_h = velocity.x < 0

This worked well. Thanks!

jtbx | 2022-11-07 20:47