Object follow mouse in radius

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

How do I make the object follow the mouse position but is limited by the radius?
I got the way in unity, but after i try in godot it doesn’t work

:bust_in_silhouette: Reply From: DaddyMonster

Assuming 2d, verboseness for clarity:

export var radius = 5

func _process(_delta):
    var mouse_pos = get_tree().get_mouse_position()
    var player_pos = player.transform.origin 
    var mouse_dir = (mouse_pos-player_pos).normalized()

    obj.transform.origin = player_pos + (mouse_dir * radius)

I’ve not tested this code so apologies in advance if there’s a mistake. If you want the obj to also face the mouse then obj.look_at(mouse_pos)

enter image description here
Thank You, Your Comment helped Me a lot.
It works fine, i modified it a bit

export var radius = 5
func _process(delta: float) -> void:
	var mouse_pos = get_global_mouse_position()
	var player_pos = player.global_transform.origin 
	var distance = player_pos.distance_to(mouse_pos) 
	var mouse_dir = (mouse_pos-player_pos).normalized()
	if distance > radius:
		mouse_pos = player_pos + (mouse_dir * radius)
	object.global_transform.origin = mouse_pos

David Wong | 2021-09-25 13:47

Glad it helped! Some sensible modifications you’ve made there. Can’t believe the amount of faffing about Unity requires to do something so simple. Stick with Godot! :wink:

DaddyMonster | 2021-09-25 14:09

Thank you so much to both of you. I have been searching for HOURS and there wasn’t anyone with the right question, not to speak of even an answer. Seeing that video of the Sprite spinning with the cursor was like seeing water in a desert. Thank you for the beatiful code!!!

FireBlo33om | 2022-07-10 18:33

Hi there! This looking great for me. I am trying to do essentially what your code does except I want to clamp it at certain angles. Basically I only want around the object to move a certain number of degrees around the circle. Is there any way to clamp this? I can clamp by x position or y position, but I need to clamp by both at the same time if that makes sense? Like using this image as an example:

https://answers.unity.com/storage/temp/68760-제목-없음.png

I only want it to go as far as the object is pictured and in between. It shouldn’t be able to go all the way to the left of the object.

theworldisaplace | 2022-07-20 20:30

So just obj.rotation to get the angle. And then use the clamp() function to constrain it.

rotation explained:
Node2D — Godot Engine (stable) documentation in English

clamp() explained:
@GDScript — Godot Engine (stable) documentation in English

This will be in radians (the amount the radius subtends the arc length of the circle) and will start from pointing right and go anti-clockwise. 1*2*PI is a full circle. So 1*PI/4 is 45 degrees.

Abandon degrees. It’s extra computation for no gain.

Hope that helps. Good luck!

DaddyMonster | 2022-07-20 23:50

That answered the question concisely but I don’t know what your level is so if that was too complicated let me know and I’ll explain it in layman’s terms. Do try to figure it out first though by reading the links and googling the terms.

DaddyMonster | 2022-07-21 00:10

:bust_in_silhouette: Reply From: Lola

Hello,

What do you want to do? Is it in 2D or in 3D? Should the object smoothly move towards the mouse or teleport to it?

I am going to assume the most simple case: a 2D constraint where the object teleports.
What you have to do is simple:

  1. Get the constrained object position relative to the area center,
  2. constraint this position to the radius if it is too big,
  3. place the constrained object at the calculated position.

Here is a script that does that:

# This is the "constrainer" script
# You can move the constrainer node to move the area center.

tool
extends Node2D


## The radius of the constrained area.
export var radius := 30 setget set_radius

export var constrained_object_path: NodePath
onready var constrained_object: Node2D = get_node(constrained_object_path)


func _process(_delta: float) -> void:
    # 1. Get the constrained object position relative to the area center
    var global_dir := get_global_mouse_position() - global_position
    # 2. constraint this position to the radius if it is too big
    if global_dir.length() > radius:
        global_dir = radius * global_dir.normalized()
    # 3. place the constrained object at the calculated position
    constrained_object.global_position = global_position + global_dir


func _draw() -> void:
    draw_circle(Vector2.ZERO, radius, Color(1.0, 0.0, 0.0, 0.25))


func set_radius(r):
    radius = r
    update() # this triggers a _draw() call.