3
\$\begingroup\$

I'm trying to write a GDScript (using Godot 4) function that creates a new component at a specific Vector2 position. This works quite well with the following code:

func _create_thing(at_position):
    var component = load("res://thing.tscn").instantiate() as Node2D
    component.position = at_position
    %PlayfieldNode2D.add_child(component)

Now I'm trying to restrict where players can create something. I want to define a polygon shape in the editor to determine the area where this is allowed. My thought was to create an Area2D node with a CollisionPolygon2D shape and then do something like this:

    if %AllowedArea2D.contains_point(at_position):
         # creation logic here

This is pseudo-code, because I found no contains_point(...) or similar method in the Area2D docs. I looked through the docs of other related Node types such as the CollisionPolygon2D, Polygon2D and several others, but found no solution yet.

Bottom line: how can I define a polygon shape in Godot 4 and later check if a specific Vector2 is inside that polygon?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Minutes after posting I find the answer myself, was tempted to delete my question because it was so simple, but it might help someone else too...

Although I found no method on one of the object's classes themselves, it is on a Geometry2D helper class, specifically the is_point_in_polygon(point, polygon) method does what you need here. For example:

    if Geometry2D.is_point_in_polygon(at_position, %CollisionPolygon2D.polygon):
         # creation logic here
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks. I thought I was gonna have to go instantiate a whole Geometry2D, not realizing this was a static method. \$\endgroup\$ Commented May 14, 2023 at 6:31
2
\$\begingroup\$

I know you found an alternative approach. However, originally you wanted something that worked with Area2D. Well, here is that:

var query := PhysicsPointQueryParameters2D.new()
query.collide_with_areas = true
query.collide_with_bodies = false
query.position = at_position
var result := get_world_2d().direct_space_state.intersect_point(query)
var in_the_area := false
for entry in result:
    if entry.collider == area_2d:
        in_the_area = true
        break

prints(in_the_area)
\$\endgroup\$
1
  • \$\begingroup\$ Best example about using PhysicsPointQueryParameters2D I've found so far \$\endgroup\$
    – Krumelur
    Commented Mar 16 at 18:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .