Given a Vector2, how can I programmatically test whether it is inside

- A 2D Sprite with a texture, ignoring the alpha of the current frame's texture

- A CollisionObject2D such as an Area2D

I can't see any simple contains_point method for both

+2 votes

Best answer

The way I finally used was to use

Physics2DDirectSpaceState's intersect_point method and look at the results.

```
var space = get_world_2d().get_direct_space_state()
var results = space.intersect_point( thePoint, 32, [], 2147483647, Physics2DDirectSpaceState.TYPE_MASK_AREA )
# then see if the CollisionObject2D is inside the results
```

+1 vote

To what I know there is no direct way how to do it.

Sprite solution can be to add `Polygon2D`

as child node of a sprite and mark with it non-alpha part of your sprite. Then you can attach the following script to`Polygon2D`

node. Then you can test whether a `point`

(`Vector2D`

) lies inside the polygon with `has_point(point)`

function. It uses the Ray casting algorithm.

Solution for `CollisionObject2D`

is similar. Instead of adding `Polygon2D`

you can use coordinates of collision object polygon.

```
extends Polygon2D
var poly_corners = 0 # how many corners the polygon has (no repeats)
var poly_x = [] # horizontal coordinates of corners
var poly_y = [] # vertical coordinates of corners
var constant = [] # storage for precalculated constants (same size as poly_x)
var multiple = [] # storage for precalculated multipliers (same size as poly_x)
var vertices_pos = [] # storage for global coordinates of polygon's vertices
func _ready():
inic()
func inic():
var poly_pos = get_global_pos() # global position of polygon
var vertices = get_polygon() # local coordiantes of vertices
poly_corners = vertices.size()
poly_x.resize(poly_corners)
poly_y.resize(poly_corners)
constant.resize(poly_corners)
multiple.resize(poly_corners)
vertices_pos.resize(poly_corners)
for i in range(poly_corners):
vertices_pos[i] = poly_pos + vertices[i]
poly_x[i] = vertices_pos[i].x
poly_y[i] = vertices_pos[i].y
precalc_values_has_point(poly_x, poly_y)
func precalc_values_has_point(poly_x, poly_y): # precalculation of constant and multiple
var j = poly_corners - 1
for i in range(poly_corners):
if poly_y[j] == poly_x[i]:
constant[i] = poly_y[i]
multiple[i] = 0.0
else:
constant[i] = poly_x[i] - poly_y[i] * poly_x[j] / (poly_y[j] - poly_y[i]) + poly_y[i] * poly_x[i] / (poly_y[j] - poly_y[i])
multiple[i] = (poly_x[j] - poly_x[i]) / (poly_y[j] - poly_y[i])
j = i
func has_point(point):
var x = point.x
var y = point.y
var j = poly_corners - 1
var odd_nodes = 0
for i in range(poly_corners):
if (poly_y[i] < y and poly_y[j] >= y) or (poly_y[j] < y and poly_y[i] >= y):
if y * multiple[i] + constant[i] < x:
odd_nodes += 1
j = i
if odd_nodes % 2 == 0:
return false
else:
return true
```

- All categories
- Engine 30,408