Godot Version
4.2
Question
I’m trying to get a random a point around my payer character between an area 2d and a range but so far I havent been able to find an answer to this question. So far I found some guidance but so far all I have been able to do is get a random point within the area 2d. But I want the points to be outside the area 2d.
@onready var collision_shape_2d = $"../Player/Area2D/CollisionShape2D".shape.get_rect()
@onready var targetPos : Vector2
func PickRandomPoint():
var x = randi_range(collision_shape_2d.position.x, (collision_shape_2d.position.x + collision_shape_2d.size.x) + 50)
var y = randi_range(collision_shape_2d.position.y, (collision_shape_2d.position.y + collision_shape_2d.size.y) + 50)
targetPos = Vector2(x,y)
#Spawns a Tag to see where the random point is
var pos = POINT.instantiate()
pos.position = targetPos
get_tree().root.add_child(pos)
Shouldn’t you be adding the size to the rand_range from parameter? Something like this
Also size may not be enough. For simplicity, you will have to get the radius of an imaginary circle around your rectangle. I am assuming your position is centered in the rectangle.
var pos=$StaticBody3D/collision_shape_2d.position
var sz=$StaticBody3D/collision_shape_2d.size.length() / 2
var from=pos + sz
var to=(pos + sz) + 50
var x = randi_range(from.x, to.x)
var y = randi_range(from.y, to.y)
I am using a circle for the collision shape 2d so the radius and size I am using are those of the circle and the player is centered in it.
I can’t test this right now, but the basic idea is as follows and I’m pretty sure my math is right.
If your area is a square and you want a square area outside that, run your first range from -1 to 1 for both x and y. This gives you a quadrant your point lies in. then you just scale that value to be within your hollow shape. So if you roll (-0.2, -0.6) and (assume a square) your shape has an outer limit of 6 and an inner limit of 4 you multiple the vector by the difference 2, which gives (-0.4, -1.2) then add (or subtract if negative) 4 to give you a final value for your point of (-4.4, -5.2).
To confirm with limits:
(-1, -1) → (-2, -2) → (-6, -6)
(1, 0) → (2, 0) → (6, 4)
This will work with rectangles, but you’ll need to use vector multipliers instead of scalars. I’m doing it as a square because I don’t want to do that math in my head.
The same procedure works for a circle in polar coordinates. Instead of x and y you have r and θ (theta). You then do some trig math to convert that back to Cartesian space.
This time, your r bound is the radius of your inner circle to radius of outer circle and your θ bound is -π to π (Godot has a PI constant defined). Then, you just convert back:
x = r cos θ
y = r sin θ
That will give you a point between your two circles. It works for an ellipse too, but I’m not getting into that math…
Thanks for sharing, very helpful
It sounds like you’re looking for a range in a donut shape around the character? If so, perhaps something like:
func random_donut_point(center: Vector2, inner: float, outer: float) -> Vector2:
var angle: float = randf_range(0.0, TAU) # Random angle 0..360 degrees.
var vec: Vector2 = Vector2.RIGHT # (0.0, 1.0)
var dist: float = randf_range(inner, outer) # Random length.
# Put 'em all together...
return (vec * dist).rotated(angle)
If you hand that your player’s position, the radius of the collision shape for the inner radius (maybe plus a small fudge value so they don’t overlap) and the furthest away you want something to be, it should give you a random point within a circle of the larger radius that doesn’t fall inside the smaller radius.
oooh thanks for sharing this! I’ll probably have a hard time translating this into code but this is a start
oh this is exactly what i needed thank you for sharing