示例#1
0
        /// <summary>
        /// Given an input of perimeters that describe a single tile group, returns a list of ConvexPolygonShape2Ds that
        /// represent the tile group but decomposed into rectangles.
        /// </summary>
        /// <param name="allPerims">Array of lists describing single tile group. Every list in the array represents a
        /// different perimeter.</param>
        /// <returns>A list of ConvexPolygonShape2Ds, with each one being a rectangle that the original irregular polygon
        /// was decomposed into.</returns>
        private static List <ConvexPolygonShape2D> _PartitionPolygonToRectangles(
            IReadOnlyList <List <Vector2> > allPerims)
        {
            var partitionedRectangles = new List <ConvexPolygonShape2D>();

            var allIsoPerims = new List <Vector2> [allPerims.Count];

            for (int i = 0; i < allPerims.Count; i++)
            {
                //convert to iso axis so all the shapes 'look' rectangular
                allIsoPerims[i] = AxisFuncs.CoordArrayToIsoAxis(allPerims[i]);
            }

            (List <Chord> chords, List <ChordlessPolygon> chordlessPolygons) = allIsoPerims.DecomposeComplexPolygonToRectangles();
            List <List <Vector2> > allRectangles = chordlessPolygons.DecomposeChordlessPolygonToRectangles(chords);

            foreach (List <Vector2> rectangle in allRectangles)
            {
                List <Vector2> carteRectangle = AxisFuncs.CoordArrayToCarteAxis(rectangle);
                var            cps2d          = new ConvexPolygonShape2D()
                {
                    Points = carteRectangle.ToArray()
                };
                partitionedRectangles.Add(cps2d);
            }

            return(partitionedRectangles);
        }
 /// <summary>
 /// Create a default polygon.
 /// </summary>
 public SimplePolygon()
 {
     polygonShape2D   = new ConvexPolygonShape2D();
     collisionShape2D = new CollisionShape2D()
     {
         Shape = polygonShape2D
     };
 }
示例#3
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);
    }
示例#4
0
 public override void _Ready()
 {
     surface_1 = GetNode <Line2D>("Water_Surface_1");
     surface_2 = GetNode <Line2D>("Water_Surface_2");
     collider  = (ConvexPolygonShape2D)GetNode <CollisionShape2D>("Collider/CollisionShape2D").Shape;
     Vector2[] polygon_body = new Vector2[length + 2];
     segment_spread = Math.Abs(bounds[1].x - bounds[0].x) / (length - 1);
     for (int i = 0; i < length; i++)
     {
         water_surface[i] = new Water_Segment_Poly(new Vector2((i * segment_spread) + bounds[0].x, bounds[0].y));
         polygon_body[i]  = water_surface[i].position;
         surface_1.AddPoint(water_surface[i].position);
         surface_2.AddPoint(new Vector2(water_surface[i].position.x, water_surface[i].position.y + 1));
         left_deltas[i]  = 0;
         right_deltas[i] = 0;
     }
     polygon_body[length]     = bounds[1];
     polygon_body[length + 1] = new Vector2(bounds[0].x, bounds[1].y);
     Polygon         = polygon_body;
     collider.Points = polygon_body;
 }
示例#5
0
    public void MakeDraggable()
    {
        dragArea = new Area2D();
        AddChild(dragArea);

        dragArea.Connect("mouse_entered", this, nameof(OnMouseEntered));
        dragArea.Connect("mouse_exited", this, nameof(OnMouseExited));

        var shape = new ConvexPolygonShape2D();

        shape.SetPoints(new Vector2[]
        {
            new Vector2(0, -1f),
            new Vector2(1f, -0.5f),
            new Vector2(1f, 0.5f),
            new Vector2(0, 1f),
            new Vector2(-1f, 0.5f),
            new Vector2(-1f, -5f),
        });

        var ownerId = dragArea.CreateShapeOwner(dragArea);

        dragArea.ShapeOwnerAddShape(ownerId, shape);
    }
示例#6
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);
    }
示例#8
0
    public void LoadTMX(string filename)
    {
        layers = new Dictionary <string, TileMap>();
        File   f           = new File();
        string mapPath     = "res://map/";
        string mapFilename = mapPath + filename;

        if (f.Open(mapFilename, File.ModeFlags.Read) == Error.Ok)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(f.GetAsText());
            XmlElement root = xmlDoc.DocumentElement;
            tileWidth  = int.Parse(root.Attributes["tilewidth"].Value);
            tileHeight = int.Parse(root.Attributes["tileheight"].Value);
            tileSize   = new Vector2(tileWidth, tileHeight);
            width      = int.Parse(root.Attributes["width"].Value);
            height     = int.Parse(root.Attributes["height"].Value);
            XmlNode tilesetNode    = root.SelectSingleNode("tileset");
            string  tilesetPath    = tilesetNode["image"].Attributes["source"].Value;
            int     firstgid       = int.Parse(tilesetNode.Attributes["firstgid"].Value);
            int     tilesetColumns = int.Parse(tilesetNode.Attributes["columns"].Value);
            int     tilesetCount   = int.Parse(tilesetNode.Attributes["tilecount"].Value);
            int     tilesetWidth   = int.Parse(tilesetNode["image"].Attributes["width"].Value);
            int     tilesetHeight  = int.Parse(tilesetNode["image"].Attributes["height"].Value);

            tilesetPath = System.IO.Path.Combine(mapPath, tilesetPath);
            GD.Print(tilesetPath);
            tilesetPath = ResolvePath(tilesetPath);
            GD.Print(tilesetPath);
            Texture tilesetTexture = GD.Load <Texture>(tilesetPath);
            GD.Print($"Loaded Tileset texture {tilesetPath} {tilesetTexture.GetWidth()}x{tilesetTexture.GetHeight()}");
            TileSet tileset = new TileSet();
            for (int i = 0; i < tilesetCount; i++)
            {
                tileset.CreateTile(i);
                tileset.TileSetTexture(i, tilesetTexture);
                tileset.TileSetTileMode(i, TileSet.TileMode.SingleTile);
                tileset.TileSetRegion(i, new Rect2((i % tilesetColumns) * tileWidth, (i / tilesetColumns) * tileHeight, tileWidth, tileHeight));
                //tileset.TileSetTextureOffset(i, new Vector2((i % tilesetColumns) * tileWidth, (i / tilesetColumns) * tileHeight));
                //tileset.AutotileSetSize(0, new Vector2(tileWidth, tileHeight));
                ConvexPolygonShape2D shape = new ConvexPolygonShape2D();
                shape.Points = new Vector2[] {
                    new Vector2(0, 0), new Vector2(16, 0),
                    new Vector2(16, 16), new Vector2(0, 16)
                };
                tileset.TileSetShape(i, 0, shape);
            }

            foreach (XmlNode layer in root.SelectNodes("layer"))
            {
                int    layerWidth    = int.Parse(layer.Attributes["width"].Value);
                int    layerHeight   = int.Parse(layer.Attributes["height"].Value);
                string layerName     = layer.Attributes["name"].Value;
                string layerEncoding = layer["data"].Attributes["encoding"].Value;
                if (layerEncoding != "csv")
                {
                    GD.Print($"{mapFilename} layer {layerName} invalid encoding {layerEncoding}!");
                    continue;
                }
                TileMap map = new TileMap();//GetNode<TileMap>(layerName);
                map.CollisionLayer = 1 << 1;
                map.CollisionMask  = 0;
                map.CellSize       = new Vector2(tileWidth, tileHeight);
                //if (map == null) continue;
                GD.Print($"Loading layer {layerName}.");
                string dataStr = layer["data"].InnerText;
                dataStr.Replace("\n", "");
                string[] dataStrCells = dataStr.Split(",");
                map.Name    = layerName;
                map.TileSet = tileset;

                int tileCount = 0;
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        string dataStrCell = dataStrCells[y * width + x];
                        long   tileId      = long.Parse(dataStrCell);
                        tileId &= 0xffff;
                        tileId -= firstgid;
                        if (tileId >= 0)
                        {
                            map.SetCell(x, y, (int)tileId, false, false, false);
                            tileCount++;
                        }
                    }
                }
                GD.Print($"Added {tileCount} tiles to layer {layerName}.");
                layers.Add(layerName, map);
                AddChild(map);
            }
        }
        else
        {
            GD.Print("Error loading map.tmx!");
        }
    }