+2 votes

Lets say I want to create nodes of arbitrary shape inside a scene. Naturally when I add a Sprite as a child of RigidBody2D, I also want the CollisionShape2D to be exactly (or at least approximately) the shape of Sprite. How do I go about it? Is it difficult to implement? Am I limited to using built-in collision shapes? The question is related to pixel-perfect collision too. In other words, I want to automate the process of creating collision shapes from a Sprite.

The example usage is creating randomly generated terrain maps as a StaticBody2D imported from .png transparent image.

Using Godot 2.1.2 stable.

in Engine by (1,371 points)
edited by

3 Answers

+2 votes
Best answer

Sprites now have a tool that creates CollisionPolygon2D's automatically. Click on "Sprite" on the top tool bar, and then select "Create CollisionPolygon2D sibling option".
See 2D meshes tutorial for details.

Using Godot 3.1.1 stable.

by (281 points)
edited by
+1 vote

Use a CollisionPolygon2D instead of predefined shapes, and you can add the coordinates manually!

by (674 points)

Using CollisionPolygon2D solves the problem of limited number of built-in shapes, yes. But what I'm trying to achieve is actually how to automate the process of creating such shapes so I don't have to manually create a CollisionPolygon2D for each sprite I import.

So you want to create shapes programmatically.
IMO you have to use collisionobject2d api, because Collision*** nodes are editor-helpers only :(.

Yeah, seems like I need to dig into it more. Thanks for pointing out to the API, I suspected it wouldn't be easy... Maybe Godot 3.0 will bring such functionality.

May I suggest writing a tool for this in another language? It could generate the vertexes and write them to a file, then have Godot build a polygon from that. I'm considering doing that with Python+Pillow for my game, and perhaps later making a plugin of it through DLScript (unlikely).

Go for it! I'm rather interested in some general algorithm for it, implementation doesn't really matter. It would be even better to make this stuff work at run-time.

You can read the Image data from the ImageTexture resource and look for transparent points to create your Convex/Concave PolygonShape2D.

+1 vote

I've figured a somewhat hacky solution that could turn sprites into a bunch of convex shapes using mesh instances in 2D space:

Create collision shapes from sprites in Godot 3.0

  1. Create a sprite and assign its texture.
  2. Select the node sprite, at the top panel of the viewport click Sprite.
  3. In the popup menu, press Convert to 2D Mesh.
  4. In the window dialog, press Create 2D Mesh button.

Now you can get faces from the mesh, convert those faces into a bunch of ConvexPolygonShape2D (which are triangles), and add those directly to a physics body.

func _ready():
    # Get triangles points from mesh
    var points = $MeshInstance.mesh.get_faces()

    var idx = 0
    var shapes = []

while idx < points.size():

    # Each three vertices represent one triangle
    # Converts automatically from Vector3 to Vector2!
    var tri_points = PoolVector2Array([points[idx], points[idx + 1], points[idx + 2]])

    # Create an actual triangle shape
    var tri_shape = ConvexPolygonShape2D.new()
    tri_shape.points = tri_points

    idx += 3

for sh in shapes:
    # Add created shapes to this collision body
    # `0` indicates the first shape owner which is `CollisionShape2D`
    shape_owner_add_shape(0, sh)
by (1,371 points)

I should note that this solution is not complete because it doesn't take into account possible holes in the sprite's texture, but it's still quite useful.

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 Frequently asked questions and 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.