Exemple #1
0
    public static TileSet makeTileset(Texture texture, bool collisions)
    {
        var ts = new TileSet();

        int i = 0;

        for (int y = 0; y < TILESET_HEIGHT; y++)
        {
            for (int x = 0; x < TILESET_WIDTH; x++)
            {
                ts.CreateTile(i);
                ts.TileSetTexture(i, texture);
                var region = new Rect2(x * TILE_WIDTH, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
                ts.TileSetRegion(i, region);

                if (collisions)
                {
                    var image  = texture.GetData();
                    var bitmap = new BitMap();
                    bitmap.CreateFromImageAlpha(image, .01f);

                    var            polygons = bitmap.OpaqueToPolygons(region, 2);
                    List <Vector2> plist    = new List <Vector2>();
                    for (int j = 0; j < polygons.Count; j++)
                    {
                        Vector2[] v = (Vector2[])polygons[j];
                        for (int k = 0; k < v.Length; k++)
                        {
                            // I have no idea why it's adding y*48 to y coordinates...
                            Vector2 mv = new Vector2(v[k].x, v[k].y - (y * TILE_HEIGHT * 2));
                            plist.Add(mv);
                        }
                    }

                    // Point cloud must be at least 3
                    if (plist.Count >= 3)
                    {
                        var collision = new ConvexPolygonShape2D();
                        collision.SetPointCloud(plist.ToArray());
                        ts.TileSetShape(i, 0, collision);
                    }
                }
                i++;
            }
        }
        return(ts);
    }
Exemple #2
0
    void MakeTileCollisionShapes(TileMap map)
    {
        TileSet tileSet = map.TileSet;

        foreach (int tileId in tileSet.GetTilesIds())
        {
            // Load image and calculate collison polygon
            // https://github.com/godotengine/godot/blob/2abe996414b8b551e69e29461de3ff1bcaf5a28f/editor/plugins/sprite_2d_editor_plugin.cpp#L160
            // https://github.com/godotengine/godot/blob/2abe996414b8b551e69e29461de3ff1bcaf5a28f/editor/plugins/sprite_2d_editor_plugin.cpp#L255

            Image tileImage = tileSet.TileGetTexture(tileId).GetData();

            Rect2 rect = new Rect2();
            rect.Size = new Vector2(tileImage.GetWidth(), tileImage.GetHeight());

            BitMap imageBitMap = new BitMap();
            imageBitMap.CreateFromImageAlpha(tileImage);

            Array lines = imageBitMap.OpaqueToPolygons(rect);

            Array <Array <Vector2> > OutlineLines = new Array <Array <Vector2> >();
            OutlineLines.Resize(lines.Count);

            Array <Array <Vector2> > computedOutlineLines = new Array <Array <Vector2> >();
            computedOutlineLines.Resize(lines.Count);

            for (int pi = 0; pi < lines.Count; pi++)
            {
                Array <Vector2> ol  = new Array <Vector2>();
                Array <Vector2> col = new Array <Vector2>();

                IList <Vector2> linesLines = (IList <Vector2>)lines[pi];

                ol.Resize(linesLines.Count);
                col.Resize(linesLines.Count);

                for (int i = 0; i < linesLines.Count; i++)
                {
                    Vector2 vtx = linesLines[i];

                    ol[i] = vtx;
                    vtx  -= rect.Position;

                    // Flipping logic is not implemented since idk how that would
                    // translate from a Sprite to an Image
                    // Don't flip any sprites horizontally or vertically

                    // this assumes the texture is centered in the image (which it is)
                    vtx -= rect.Size / 2;

                    col[i] = vtx;
                }

                OutlineLines[pi]         = ol;
                computedOutlineLines[pi] = col;
            }


            // Now that we've calculated the collision polygon, we need to set it
            // https://github.com/godotengine/godot/blob/2abe996414b8b551e69e29461de3ff1bcaf5a28f/editor/plugins/sprite_2d_editor_plugin.cpp#L400

            if (computedOutlineLines.Count == 0)
            {
                GD.PrintErr("Error, couldn't make some geometry - tileId is " + tileId.ToString());
                continue;
            }

            ConvexPolygonShape2D newShape = new ConvexPolygonShape2D();
            for (int i = 0; i < computedOutlineLines.Count; i++)
            {
                var outline = computedOutlineLines[i];
                newShape.Points = outline.ToArray <Vector2>();
                tileSet.TileSetShape(tileId, 0, newShape);
                tileSet.TileSetShapeOffset(tileId, 0, new Vector2(256, 256));                 // needs to be offset by this amount for some reason
            }
        }
    }
    public static TileSet makeTileset(Texture texture, bool collisions)
    {
        BitMap original_bitmap = null;
        BitMap bitmap          = null;

        if (collisions)
        {
            var image = texture.GetData();
            original_bitmap = new BitMap();
            original_bitmap.CreateFromImageAlpha(image, .001f);

            // bitmap with borders is needed to shrink mask later
            bitmap = new BitMap();
            bitmap.Create(new Vector2((TILE_WIDTH + 2) * TILESET_WIDTH, (TILE_HEIGHT + 2) * TILESET_HEIGHT));
            bitmap.SetBitRect(new Rect2(new Vector2(0, 0), bitmap.GetSize()), true);
        }

        var ts = new TileSet();

        int i = 0;

        for (int y = 0; y < TILESET_HEIGHT; y++)
        {
            for (int x = 0; x < TILESET_WIDTH; x++)
            {
                ts.CreateTile(i);
                ts.TileSetTexture(i, texture);
                var region = new Rect2(x * TILE_WIDTH, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
                ts.TileSetRegion(i, region);

                if (collisions)
                {
                    for (int m = 0; m < TILE_WIDTH; m++)
                    {
                        for (int n = 0; n < TILE_HEIGHT; n++)
                        {
                            bitmap.SetBit(new Vector2(x * (TILE_WIDTH + 2) + m + 1, y * (TILE_HEIGHT + 2) + n + 1),
                                          original_bitmap.GetBit(new Vector2(x * TILE_WIDTH + m, y * TILE_HEIGHT + n)));
                        }
                    }

                    var bitmap_region = new Rect2(x * (TILE_WIDTH + 2) + 1, y * (TILE_HEIGHT + 2) + 1, TILE_WIDTH, TILE_HEIGHT);
                    var polygons      = tilePolygons(bitmap, bitmap_region);
                    int c             = 0;

                    foreach (Vector2[] polygon in polygons)
                    {
                        if (isConvex(polygon))
                        {
                            var collision = new ConvexPolygonShape2D();
                            collision.SetPointCloud(polygon);
                            ts.TileSetShape(i, c++, collision);
                        }
                        else
                        {
                            int[] triangles = Geometry.TriangulatePolygon(polygon);
                            for (int t = 0; t < triangles.Length; t += 3)
                            {
                                Vector2[] triangle  = { polygon[triangles[t]], polygon[triangles[t + 1]], polygon[triangles[t + 2]] };
                                var       collision = new ConvexPolygonShape2D();
                                collision.SetPointCloud(triangle);
                                ts.TileSetShape(i, c++, collision);
                            }
                        }
                    }
                }
                i++;
            }
        }
        return(ts);
    }