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); }
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); }