Help with straight movement into circular movement? (Godot 4.x, Godot 4.2.1)
-
Here's what I'm trying to make happen:
- The object appears. (I currently have it set to appear somewhere random on-screen for testing purposes using
position = Vector2(randf_range(0,get_viewport_rect().size.x),randf_range(0,get_viewport_rect().size.y))
. In the game, the object will be dropped by enemies when they are defeated.) - The object moves away from the center and toward the closest point on a circle. This circle is centered. The circle's size can be changed at
_ready()
. - Upon reaching that point, the object moves along the circumference from that point clockwise or counterclockwise.
I have tried 4 different approaches, some using parent node rotation, trigonometry, and Path2Ds, but none of them have worked and I'm out of ideas. Does anyone have any tips?
- The object appears. (I currently have it set to appear somewhere random on-screen for testing purposes using
-
Sorry for not seeing your question until this late.
Could you please elaborate on where you are having trouble, and what you have working so far?
-Are you having trouble spawning the object in a random place?
-Or are you unable to find the closest point on the circle?
-Perhaps you have the first 2 steps complete, but you just can't make it move along the circumference?And a few minor questions:
-Will the object spawn inside the circle, outside the circle, or both?
-Does the circle always stay in the center, and will it change size later in-game?
-How much math can you understand?I will try coming up with something, but I might struggle as well
-
I made a code to make the item move towards the closest point on the circle.
Basically, I noticed that if you drew an imaginary line from the center of the circle to the item, the line eventually touches the closest point on the circle.
Since want to find the slope of that line, use arctan(y/x) to find the angle. With the slope, you can then find the x and y coordinates of the point on the circle. This is done by cos(angle)radius and sin(angle)radius.
Now that you have the desired x and y coordinates, simply move the item towards that direction.Note that since Godot measures x and y from the top left corner, you have to go through weird conversions to make it work with trig:
extends Node2D var radius = 250 var phase = 0 var speed = 100 var angular_speed = .2 var clockwise = -1 #-1 for clockwise, 1 for counter-clockwise var x var y var angle var xgoal var ygoal var movement func _ready(): position = Vector2(randf_range(0,get_viewport_rect().size.x),randf_range(0,get_viewport_rect().size.y)) set_xy() angle = atan2(y, x) #find the angle from the center of the circle to the position xgoal = radius*cos(angle) #using that angle, find the coordinates of where that would be on the circle ygoal = radius*sin(angle) movement = Vector2(xgoal - x, -(ygoal - y)).normalized() #direction the item should travel func set_xy(): #sets the x and y coordinates, then offsets the values so that (0, 0) is at the center of the screen (instead of the top left ocrner) x = position.x - get_viewport_rect().size.x/2 y = -(position.y - get_viewport_rect().size.y/2)
Alright, I hope it makes sense and works for you. I also completed the second half of the code.
This part checks if the item is close enough to the edge, then activates the next phase.
In the second phase, the code simply increases the angle slowly, then converts the angle to the coordinates on the circle.
The code should work if you just add it on to the end of the first half:func _process(delta): if phase == 0: phase0(delta) if phase == 1: phase1(delta) func phase0(delta): #moving the item towards the edge of the circle. End this phase once close enough to the edge position += movement * speed * delta set_xy() #(next several lines) measuring how far it is from the edge, then go to next phase if it's close enough var distance = Vector2(xgoal-x, -(ygoal-y)).length() if distance<5: phase = 1 func phase1(delta): #circling around after reaching the edge angle += angular_speed * clockwise * delta #increase the angle slowly xgoal = radius * cos(angle) #(next several lines) finding and converting the angle to coordinates. ygoal = -radius * sin(angle) xgoal += get_viewport_rect().size.x/2 ygoal += get_viewport_rect().size.y/2 position = Vector2(xgoal, ygoal)