2D Platformer Ball game, ball (CharacterBody2D) does not bounce (move_and_slide)

Godot Version

v4.3.stable.official [77dcf97d8]

Question

Infos
My Player: CharacterBody2D
Collision Wall: TileMapLayer
Script currently works well except it doesn’t bounce

Description:
I have been googling, checking documentation etc. but couldn’t find the solution. I make a game where the ball falls down, it can move left and right. Now I want to add a bit of a bounce. I used move_and_slide() because move_and_collide I couldn’t get to work properly. (my issues: when moving down, I can press my arrow to the wall during falling and the falling would stop. Also, when moving around, it sometimes is going faster, sometimes slower, also falling is faster than moving left/right … that’s why I ditched move-and_collide again)

The ball I’m moving around in my 2d platformer game is a CharacterBody2D and my code is the following. My Map is using TileMapLayer:

func _physics_process(delta: float) -> void:
       # ....
	velocity += get_gravity() * delta

	var direction := Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
	
	move_and_slide()

The above code works well, except that the ball doesn’t have a natural bounce which will fade off slowly…

I tried stuff like:
https://godotforums.org/d/34971-move-and-slide-and-bounce-in-godot-4
and things like:

    for i in get_slide_count():
        var collision = get_slide_collision(i)
        if abs(collision.normal.x) > 0.5: 
            velocity.x = -prev_velocity.x * 0.5

I’m a complete beginner and would love some guidance.

Thank you very much for your help

EDIT: If you need more info, pls let me know.

Hi,
Have you tried this?

	var collision_info = move_and_collide(velocity * delta)
	
	if collision_info:
		velocity = velocity.bounce(collision_info.get_normal())

I hope it works.

Thank you @pbij, I tried this before. I changed my code now to the following:

func _physics_process(delta: float) -> void:
        # Add the gravity.
	velocity += get_gravity() * delta

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction := Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
	
	var collision_info = move_and_collide(velocity * delta)
	if collision_info:
		velocity = velocity.bounce(collision_info.get_normal())
	
	#move_and_slide()

My problems are now the following:

  1. The ball keeps bouncing (it’s not losing “momentum”)
  2. I can press “ui_left” and “ui_right” when the ball (player) is right next to a wall and then the player won’t fall anymore, which is wrong. The desired effect is that it only bounces on the bottom collision and any other bounces should be ignored.

Thank you a lot

UPDATE: I added the following code which makes it lose its bounciness but still, the ball can stick to the side walls, which shouldn’t happen. Here is my updated code:

	var collision_info = move_and_collide(velocity * delta)
	if collision_info:
		var direction2 = velocity.bounce(collision_info.get_normal())
		velocity = direction2 * 0.8
		print(velocity)

UPDATE: My workaround was creating an Arena2D for Left side of ball and Arena2D for right side of ball, then whenever it touches left or right I will update a global variable and call move_and_slide instead of move_and_collide. It works surprisingly well but it feels like a hack. If you have any better solution let me know please. THANK YOU