0 votes

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?

asked Feb 26 in Engine by ChuckSparrow (15 points)

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?

1 Answer

+2 votes
Best answer

What the editor uses to produce the polygon is a Bitmap: https://docs.godotengine.org/en/3.2/classes/class_bitmap.html

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: https://docs.godotengine.org/en/3.2/classes/class_collisionpolygon2d.html#class-collisionpolygon2d-property-polygon

As code:

var image = Image.new()

var bitmap = BitMap.new()

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

for polygon in polygons:
    var collider = CollisionPolygon2D.new()
    collider.polygon = polygon
answered Feb 26 by Zylann (27,004 points)
selected Feb 27 by ChuckSparrow

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

Thanks man!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.