diff --git a/packages/flame_tiled/lib/src/renderable_tile_map.dart b/packages/flame_tiled/lib/src/renderable_tile_map.dart index 33559a4bb35..acd9cd28183 100644 --- a/packages/flame_tiled/lib/src/renderable_tile_map.dart +++ b/packages/flame_tiled/lib/src/renderable_tile_map.dart @@ -216,6 +216,8 @@ class RenderableTiledMap { bool Function(Tileset)? tsxPackingFilter, bool useAtlas = true, Paint Function(double opacity)? layerPaintFactory, + double atlasPackingSpacingX = 0, + double atlasPackingSpacingY = 0, }) async { final contents = await (bundle ?? Flame.bundle).loadString('$prefix$fileName'); @@ -232,6 +234,8 @@ class RenderableTiledMap { tsxPackingFilter: tsxPackingFilter, useAtlas: useAtlas, layerPaintFactory: layerPaintFactory ?? _defaultLayerPaintFactory, + atlasPackingSpacingX: atlasPackingSpacingX, + atlasPackingSpacingY: atlasPackingSpacingY, ); } @@ -253,6 +257,8 @@ class RenderableTiledMap { bool Function(Tileset)? tsxPackingFilter, bool useAtlas = true, Paint Function(double opacity)? layerPaintFactory, + double atlasPackingSpacingX = 0, + double atlasPackingSpacingY = 0, }) async { final map = await TiledMap.fromString( contents, @@ -270,6 +276,8 @@ class RenderableTiledMap { tsxPackingFilter: tsxPackingFilter, useAtlas: useAtlas, layerPaintFactory: layerPaintFactory ?? _defaultLayerPaintFactory, + atlasPackingSpacingX: atlasPackingSpacingX, + atlasPackingSpacingY: atlasPackingSpacingY, ); } @@ -288,6 +296,8 @@ class RenderableTiledMap { bool Function(Tileset)? tsxPackingFilter, bool useAtlas = true, Paint Function(double opacity)? layerPaintFactory, + double atlasPackingSpacingX = 0, + double atlasPackingSpacingY = 0, }) async { // We're not going to load animation frames that are never referenced; but // we do supply the common cache for all layers in this map, and maintain @@ -312,6 +322,8 @@ class RenderableTiledMap { images: images, tsxPackingFilter: tsxPackingFilter, useAtlas: useAtlas, + spacingX: atlasPackingSpacingX, + spacingY: atlasPackingSpacingY, ), ignoreFlip: ignoreFlip, images: images, diff --git a/packages/flame_tiled/lib/src/tile_atlas.dart b/packages/flame_tiled/lib/src/tile_atlas.dart index 46cd6896123..6f420035f5c 100644 --- a/packages/flame_tiled/lib/src/tile_atlas.dart +++ b/packages/flame_tiled/lib/src/tile_atlas.dart @@ -111,6 +111,8 @@ class TiledAtlas { Images? images, bool Function(Tileset)? tsxPackingFilter, bool useAtlas = true, + double spacingX = 0, + double spacingY = 0, }) async { final tilesetImageList = _onlyTileImages( map, @@ -209,12 +211,17 @@ class TiledAtlas { final tileImageSource = entry.$1; final image = await imagesInstance.load(tileImageSource); - final rect = bin.pack(image.width.toDouble(), image.height.toDouble()); + final rect = bin.pack( + image.width.toDouble() + spacingX, + image.height.toDouble() + spacingY, + ); pictureRect = pictureRect.expandToInclude(rect); - final offset = - offsetMap[tiledImage.source!] = Offset(rect.left, rect.top); + final offset = offsetMap[tiledImage.source!] = Offset( + rect.left - spacingX, + rect.top - spacingY, + ); canvas.drawImage(image, offset, emptyPaint); } diff --git a/packages/flame_tiled/lib/src/tiled_component.dart b/packages/flame_tiled/lib/src/tiled_component.dart index cc26ce3b524..4413935089c 100644 --- a/packages/flame_tiled/lib/src/tiled_component.dart +++ b/packages/flame_tiled/lib/src/tiled_component.dart @@ -117,6 +117,8 @@ class TiledComponent extends PositionComponent bool Function(Tileset)? tsxPackingFilter, bool useAtlas = true, Paint Function(double opacity)? layerPaintFactory, + double atlasPackingSpacingX = 0, + double atlasPackingSpacingY = 0, }) async { return TiledComponent( await RenderableTiledMap.fromFile( @@ -131,6 +133,8 @@ class TiledComponent extends PositionComponent tsxPackingFilter: tsxPackingFilter, useAtlas: useAtlas, layerPaintFactory: layerPaintFactory, + atlasPackingSpacingX: atlasPackingSpacingX, + atlasPackingSpacingY: atlasPackingSpacingY, ), priority: priority, ); diff --git a/packages/flame_tiled/test/goldens/larger_atlas_component_with_spacing.png b/packages/flame_tiled/test/goldens/larger_atlas_component_with_spacing.png new file mode 100644 index 00000000000..524f758b0ef Binary files /dev/null and b/packages/flame_tiled/test/goldens/larger_atlas_component_with_spacing.png differ diff --git a/packages/flame_tiled/test/goldens/larger_atlas_with_spacing.png b/packages/flame_tiled/test/goldens/larger_atlas_with_spacing.png new file mode 100644 index 00000000000..8fbee10ce90 Binary files /dev/null and b/packages/flame_tiled/test/goldens/larger_atlas_with_spacing.png differ diff --git a/packages/flame_tiled/test/tile_atlas_test.dart b/packages/flame_tiled/test/tile_atlas_test.dart index 1e3a42a1a2c..45058472096 100644 --- a/packages/flame_tiled/test/tile_atlas_test.dart +++ b/packages/flame_tiled/test/tile_atlas_test.dart @@ -134,6 +134,32 @@ void main() { ); }); + test( + 'packs complex maps with multiple images using a custom spacing', + () async { + final component = await TiledComponent.load( + 'isometric_plain.tmx', + Vector2(128, 74), + bundle: bundle, + images: Images(bundle: bundle), + atlasPackingSpacingX: 2, + atlasPackingSpacingY: 2, + ); + + final atlas = TiledAtlas.atlasMap.values.first; + expect( + await imageToPng(atlas.atlas!), + matchesGoldenFile('goldens/larger_atlas_with_spacing.png'), + ); + expect( + renderMapToPng(component), + matchesGoldenFile( + 'goldens/larger_atlas_component_with_spacing.png', + ), + ); + }, + ); + test('can ignore tilesets in the packing', () async { await TiledComponent.load( 'isometric_plain.tmx',