How can I create CollisionPolygon2D from one Sprite programatically?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ChuckSparrow

Hi mates!

I’m trying to create a map for a strategy game where the main screen is a map splitted in several regions and each region can be clicked to show information concerning this region. The shape of each region is irregular, so I need some way to detect when the user clicks over the “visible” area of the sprite.

I started creating a CollisionPolygon2D from the Sprite with the tool that the editor provides and it works great, but this is tedious when you have to create 200 or more regions.

I have been searching for a way to create these CollisionPolygon2D programatically, but I haven’t found anything.

Do you know how can this be done or an alternative way?

So you have a sprite with a drawn shape in it, and you want to extract that shape as a polygon to produce the collider?
If you don’t want to trace polygons of each region, how did you get those 200 regions in the first place?

Zylann | 2020-02-26 01:52

:bust_in_silhouette: Reply From: Zylann

What the editor uses to produce the polygon is a Bitmap: BitMap — Godot Engine (3.2) documentation in English

It allows you to pick the image you want, convert it to a mask (with pixels being only 0 or 1), and then use opaque_to_polygon, which will turn opaque regions into one or more polygon points.

I haven’t used that class before and it’s not documented much, but from a glance in the engine code I see opaque_to_polygon returns an array, where each item is itself an array containing 2D points of one polygon (because the shape could be composed of multiple polygons).
The editor does a bit more optional stuff to those points but it looks like none of it is available from scripts: https://github.com/godotengine/godot/blob/2d980f6f13cc761c1eb9329e7eaeba5e9d1a9b37/editor/plugins/sprite_editor_plugin.cpp#L207

Then you need to create a CollisionPolygon2D for each polygon, and send their outline by assigning the polygon property: CollisionPolygon2D — Godot Engine (3.2) documentation in English

As code:

var image = Image.new()
image.load("res://map.png")

var bitmap = BitMap.new()
bitmap.create_from_image_alpha(image)

var polygons = bitmap.opaque_to_polygons(Rect2(Vector2(0, 0), bitmap.get_size()))

for polygon in polygons:
	var collider = CollisionPolygon2D.new()
	collider.polygon = polygon
	add_child(collider)

BitMap was the missing piece. It doesn’t provide as many options as the editor, but it works great for me.

Thanks man!

ChuckSparrow | 2020-02-27 14:42

:bust_in_silhouette: Reply From: ChildLearning.Club

The Shaggy Dev’s Video, “Pixel-perfect collisions on sprites in Godot”
does good job of explaining how this can be achieved.

I’m doing a very similar program and am having some problems with opaque_to_polygon. It does not make really pixel perfect polygons in any situation and I want to know 1) how does that function work 2) if there is another good option

do you still have your project? I’m interested in seeing it because I’m just starting and want references of similar works