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

in Engine

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
``````
by (254 points)

trying to find way to do that in godot 3

+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

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
``````
by (675 points)