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?

in Engine by (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()
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)
by (27,822 points)
selected by

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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.