0 votes

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 moveandslide() 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 moveandslide() 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

asked Sep 20, 2017 in Engine by CosmicKid (26 points)

1 Answer

+2 votes

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.

answered Sep 20, 2017 by eons (7,786 points)

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

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.