KinematicBody2D to RigidBody2D collision detection and response

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CosmicKid
:warning: Old Version Published before Godot 3 was released.

I’m trying to remake my simple blobby-volley-like game in godot but I’m having a trouble with making player (KinematicBody2D with circle CollisionShape2D) hit the ball (RigidBody2D with circle CollisionShape2D). I decided the ball to be RigidBody2D because I want it to rotate on hit and all physics stuff like that.

My goal is to make the player simply push the ball at the particular speed and keep player’s movement unaffected after hitting the ball. I’ve tried to use move_and_slide() on player but of course it doesn’t let him move after hitting the obstacle. set_pos() is also a bad idea as it makes the player teleport and let him go through the ground (which is StaticBody2D).

I’ve also tried to use move_and_slide() and manually detect the collision using script attached to KinematicBody2D. However, it doesn’t seem to work properly, it detects collision with the ball from time to time as if player has to touch the ball in a specific way to trigger the collision detection.

Here’s my player script:

    extends KinematicBody2D

export var player_index = 1
export(Color, RGB) var color

const movement_speed = 350
const jump_speed = 700
const push_speed = 300
const custom_gravity = 1000
const floor_normal = Vector2(0, -1)

var velocity = Vector2(0, 0)
var can_jump = false

var collision_counter = 0

func _ready():
	# Called every time the node is added to the scene.
	# Initialization here
	get_node("body").set_modulate(color)
	set_process(true)

func _process(delta):
	check_input()
	check_collision_with_ball()
	move_dolfon(delta)

func move_dolfon(delta):
	# Apply gravity
	velocity.y += custom_gravity * delta
	
	# Move the dolfon
	velocity = move_and_slide(velocity, floor_normal)
	can_jump = is_move_and_slide_on_floor()

func check_input():
	if Input.is_action_pressed("p" + str(player_index) + "_move_left"):
		velocity.x = -movement_speed
		scale(Vector2( 1, 1))
	elif Input.is_action_pressed("p" + str(player_index) + "_move_right"):
		velocity.x =  movement_speed
		scale(Vector2(-1, 1))
	else:
		velocity.x = 0
	
	if Input.is_action_pressed("p" + str(player_index) + "_jump") && can_jump:
		velocity.y = -jump_speed

func check_collision_with_ball():
	if is_colliding() && player_index == 1:
		var collider = get_collider()
		if collider.get_name() == "ball":
			var dir = (get_collision_pos() - get_node("collision_shape").get_pos()).normalized()
			print("we hit a ball")
	

If needed, I can send the current project

:bust_in_silhouette: Reply From: eons

The move API won’t solve your problems here (because is a simple overlap prevention method), you need another body to act as a solid against the ball, like:

main_body (kinematic, using move, obstacle mask)
|-shape
|-sub_body(kinematic, moved by parent, ball layer)
    |-shape

The secondary body will be moved by the parent like if is using “set_pos”.
If you want the kinematic body to be notified of collisions, use the ball’s body_enter signal.

ps: to use physics, do things in _fixed_process.

Thanks! I didn’t know it is so simple and straightforward

CosmicKid | 2017-09-21 07:57