+1 vote

I know how to restrict the movement to a circle by setting its position directly:

  func clamp_vector(vector, clamp_origin, clamp_length):
    var offset = vector - clamp_origin
    return clamp_origin + offset.clamped(clamp_length)

And then:

position = clamp_vector(position, Vector2.ZERO, 150)

This would force the body to only be able to move within a circle with radius 150 around the origin.

But I can't figure out how to do that using move_and_slide.

Edit:
**Essentially, I want to mimic a distance joint, but since I have a kinematic body, they won't work. **

Any help is appreciated!
Thanks.

asked Aug 31 in Engine by solstice (52 points)

I don't understand why Joint2D cannot work with a KinematicBody2D.

It's because Joint2D only works with RigidBody2D or StaticBody2D but not with KinematicBody2D. I mean, it does "work" but the movement of the KinematicBody isn't restricted by the Joint.

1 Answer

0 votes

While not for the same purpose, I have a KinematicBody2D clamped to a radius around the player as a top-down crosshair, using the right-stick of a controller to move the crosshair.

The crosshair is a child node of the player, hence my using $Crosshair. It can move around within a circle around the player, like in Streets of Rogue.
get_action_strength() is used as I was using a controller, with the aim_right etc mapped to the right stick in the Input Map

get_player_aim() is called in _physics_process(delta)

func get_player_aim():
    var crosshair_speed = 1000

    player_aim = Vector2(
            float(Input.get_action_strength("aim_right")) -
            float(Input.get_action_strength("aim_left")),
            float(Input.get_action_strength("aim_down")) -
            float(Input.get_action_strength("aim_up"))
            ).normalized() * crosshair_speed

    $Crosshair.position = $Crosshair.position.clamped(160)      
    $Crosshair.move_and_slide(player_aim)

Alternatively, the code below instantly snaps the crosshair to the circle / radius specified, nothing in-between.
(Annoyingly, it also snaps a little to the up, down, left and right, which I'm not 100% sure how to correct yet. It might just be the cheap controller I'm using or the deadzones.)
This doesn't use move_and_slide(), though.

"crosshair_distance" is the distance the crosshair is from the player / it's parent node

func get_player_aim():
    var crosshair_distance : = 250  

    player_aim = Vector2(
            float(Input.get_action_strength("aim_right")) -
            float(Input.get_action_strength("aim_left")),
            float(Input.get_action_strength("aim_down")) - 
            float(Input.get_action_strength("aim_up"))
            ).normalized() * crosshair_distance

    $Crosshair.position = player_aim
answered Sep 2 by TraumaticHug (14 points)
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.