mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 08:56:01 +08:00 
			
		
		
		
	TileStack (#1910)
Support searching for, and collecting stacks of tiles.
This commit is contained in:
		| @ -965,14 +965,46 @@ void main() { | |||||||
|  |  | ||||||
| ## TiledComponent | ## TiledComponent | ||||||
|  |  | ||||||
| Currently we have a very basic implementation of a Tiled component. This API uses the lib | Tiled is a free and open source, full-featured level and map editor for your platformer or | ||||||
| [tiled.dart](https://github.com/flame-engine/tiled.dart) to parse map files and render visible | RPG game. Currently we have an "in progress" implementation of a Tiled component. This API | ||||||
| layers. | uses the lib [tiled.dart](https://github.com/flame-engine/tiled.dart) to parse map files and | ||||||
|  | render visible layers using the performant `SpriteBatch` for each layer. | ||||||
|  |  | ||||||
|  | Supported map types include: Orthogonal, Isometric, Hexagonal, and Staggered. | ||||||
|  |  | ||||||
|  | Orthogonal | Hexagonal             |  Isomorphic | ||||||
|  | :--:|:-------------------------:|:-------------------------: | ||||||
|  | | |   | ||||||
|  |  | ||||||
| An example of how to use the API can be found | An example of how to use the API can be found | ||||||
| [here](https://github.com/flame-engine/flame_tiled/tree/main/example). | [here](https://github.com/flame-engine/flame_tiled/tree/main/example). | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### TileStack | ||||||
|  |  | ||||||
|  | Once a `TiledComponent` is loaded, you can select any column of (x,y) tiles in a `tileStack` to | ||||||
|  | then add animation. Removing the stack will not remove the tiles from the map. | ||||||
|  |  | ||||||
|  | > **Note**: This currently only supports position based effects. | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  |     final stack = map.tileMap.tileStack(4, 0, named: {'floor_under'}); | ||||||
|  |     stack.add( | ||||||
|  |       SequenceEffect( | ||||||
|  |         [ | ||||||
|  |           MoveEffect.by( | ||||||
|  |             Vector2(5, 0), | ||||||
|  |             NoiseEffectController(duration: 1, frequency: 20), | ||||||
|  |           ), | ||||||
|  |           MoveEffect.by(Vector2.zero(), LinearEffectController(2)), | ||||||
|  |         ], | ||||||
|  |         repeatCount: 3, | ||||||
|  |       )..onComplete = () => stack.removeFromParent(), | ||||||
|  |     ); | ||||||
|  |     map.add(stack); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
| ## IsometricTileMapComponent | ## IsometricTileMapComponent | ||||||
|  |  | ||||||
| This component allows you to render an isometric map based on a cartesian matrix of blocks and an | This component allows you to render an isometric map based on a cartesian matrix of blocks and an | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								doc/images/orthogonal.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/images/orthogonal.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								doc/images/pointy_hex_even.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/images/pointy_hex_even.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 45 KiB | 
							
								
								
									
										
											BIN
										
									
								
								doc/images/tile_stack_single_move.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/images/tile_stack_single_move.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 104 KiB | 
							
								
								
									
										67
									
								
								packages/flame_tiled/lib/src/mutable_transform.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								packages/flame_tiled/lib/src/mutable_transform.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | import 'dart:typed_data'; | ||||||
|  | import 'dart:ui'; | ||||||
|  |  | ||||||
|  | import 'package:flame/components.dart'; | ||||||
|  | import 'package:flame/effects.dart'; | ||||||
|  |  | ||||||
|  | /// A mutable version of [RSTransform] for custom batch manipulation. | ||||||
|  | class MutableRSTransform implements RSTransform, PositionProvider { | ||||||
|  |   final _values = Float32List(4); | ||||||
|  |  | ||||||
|  |   /// This is a cache of `-scos * anchorX + ssin * anchorY` | ||||||
|  |   final double _anchorX; | ||||||
|  |  | ||||||
|  |   /// This is a cache of `-ssin * anchorX - scos * anchorY` | ||||||
|  |   final double _anchorY; | ||||||
|  |  | ||||||
|  |   final Vector2 _position; | ||||||
|  |  | ||||||
|  |   MutableRSTransform( | ||||||
|  |     double scos, | ||||||
|  |     double ssin, | ||||||
|  |     double tx, | ||||||
|  |     double ty, | ||||||
|  |     this._anchorX, | ||||||
|  |     this._anchorY, | ||||||
|  |   ) : _position = Vector2(tx, ty) { | ||||||
|  |     _values[0] = scos; | ||||||
|  |     _values[1] = ssin; | ||||||
|  |     _values[2] = tx + _anchorX; | ||||||
|  |     _values[3] = ty + _anchorY; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// The cosine of the rotation multiplied by the scale factor. | ||||||
|  |   @override | ||||||
|  |   double get scos => _values[0]; | ||||||
|  |   set scos(double scos) => _values[0] = scos; | ||||||
|  |  | ||||||
|  |   /// The sine of the rotation multiplied by that same scale factor. | ||||||
|  |   @override | ||||||
|  |   double get ssin => _values[1]; | ||||||
|  |   set ssin(double ssin) => _values[1] = ssin; | ||||||
|  |  | ||||||
|  |   /// The x coordinate of the translation, minus [scos] multiplied by the | ||||||
|  |   /// x-coordinate of the rotation point, plus [ssin] multiplied by the | ||||||
|  |   /// y-coordinate of the rotation point. | ||||||
|  |   @override | ||||||
|  |   double get tx => _values[2]; | ||||||
|  |   set tx(double tx) => _values[2] = tx; | ||||||
|  |  | ||||||
|  |   /// The y coordinate of the translation, minus [ssin] multiplied by the | ||||||
|  |   /// x-coordinate of the rotation point, minus [scos] multiplied by the | ||||||
|  |   /// y-coordinate of the rotation point. | ||||||
|  |   @override | ||||||
|  |   double get ty => _values[3]; | ||||||
|  |   set ty(double ty) => _values[3] = ty; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   set position(Vector2 value) { | ||||||
|  |     _values[2] = value.x + _anchorX; | ||||||
|  |     _values[3] = value.y + _anchorY; | ||||||
|  |     _position.x = value.x; | ||||||
|  |     _position.y = value.y; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Vector2 get position => _position; | ||||||
|  | } | ||||||
| @ -2,6 +2,7 @@ import 'package:flame/extensions.dart'; | |||||||
| import 'package:flame/game.dart'; | import 'package:flame/game.dart'; | ||||||
| import 'package:flame/sprite.dart'; | import 'package:flame/sprite.dart'; | ||||||
| import 'package:flame_tiled/flame_tiled.dart'; | import 'package:flame_tiled/flame_tiled.dart'; | ||||||
|  | import 'package:flame_tiled/src/mutable_transform.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/group_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/group_layer.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/renderable_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/renderable_layer.dart'; | ||||||
| import 'package:flame_tiled/src/tile_transform.dart'; | import 'package:flame_tiled/src/tile_transform.dart'; | ||||||
| @ -13,6 +14,7 @@ import 'package:tiled/tiled.dart' as tiled; | |||||||
| class TileLayer extends RenderableLayer<tiled.TileLayer> { | class TileLayer extends RenderableLayer<tiled.TileLayer> { | ||||||
|   late final _layerPaint = Paint(); |   late final _layerPaint = Paint(); | ||||||
|   late final Map<String, SpriteBatch> _cachedSpriteBatches; |   late final Map<String, SpriteBatch> _cachedSpriteBatches; | ||||||
|  |   late List<List<MutableRSTransform?>> indexes; | ||||||
|  |  | ||||||
|   TileLayer( |   TileLayer( | ||||||
|     super.layer, |     super.layer, | ||||||
| @ -26,6 +28,11 @@ class TileLayer extends RenderableLayer<tiled.TileLayer> { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void refreshCache() { |   void refreshCache() { | ||||||
|  |     indexes = List.generate( | ||||||
|  |       layer.width, | ||||||
|  |       (index) => List.filled(layer.height, null), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     _cacheLayerTiles(); |     _cacheLayerTiles(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @ -95,14 +102,18 @@ class TileLayer extends RenderableLayer<tiled.TileLayer> { | |||||||
|         final scos = flips.cos * scale; |         final scos = flips.cos * scale; | ||||||
|         final ssin = flips.sin * scale; |         final ssin = flips.sin * scale; | ||||||
|  |  | ||||||
|         batch.addTransform( |         indexes[tx][ty] = MutableRSTransform( | ||||||
|           source: src, |  | ||||||
|           transform: RSTransform( |  | ||||||
|           scos, |           scos, | ||||||
|           ssin, |           ssin, | ||||||
|             offsetX + -scos * anchorX + ssin * anchorY, |           offsetX, | ||||||
|             offsetY + -ssin * anchorX - scos * anchorY, |           offsetY, | ||||||
|           ), |           -scos * anchorX + ssin * anchorY, | ||||||
|  |           -ssin * anchorX - scos * anchorY, | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         batch.addTransform( | ||||||
|  |           source: src, | ||||||
|  |           transform: indexes[tx][ty], | ||||||
|           flip: flips.flip, |           flip: flips.flip, | ||||||
|         ); |         ); | ||||||
|       } |       } | ||||||
| @ -152,14 +163,18 @@ class TileLayer extends RenderableLayer<tiled.TileLayer> { | |||||||
|         final scos = flips.cos * scale; |         final scos = flips.cos * scale; | ||||||
|         final ssin = flips.sin * scale; |         final ssin = flips.sin * scale; | ||||||
|  |  | ||||||
|         batch.addTransform( |         indexes[tx][ty] = MutableRSTransform( | ||||||
|           source: src, |  | ||||||
|           transform: RSTransform( |  | ||||||
|           scos, |           scos, | ||||||
|           ssin, |           ssin, | ||||||
|             offsetX + -scos * anchorX + ssin * anchorY, |           offsetX, | ||||||
|             offsetY + -ssin * anchorX - scos * anchorY, |           offsetY, | ||||||
|           ), |           -scos * anchorX + ssin * anchorY, | ||||||
|  |           -ssin * anchorX - scos * anchorY, | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         batch.addTransform( | ||||||
|  |           source: src, | ||||||
|  |           transform: indexes[tx][ty], | ||||||
|           flip: flips.flip, |           flip: flips.flip, | ||||||
|         ); |         ); | ||||||
|       } |       } | ||||||
| @ -257,11 +272,13 @@ class TileLayer extends RenderableLayer<tiled.TileLayer> { | |||||||
|         final scos = flips.cos * scale; |         final scos = flips.cos * scale; | ||||||
|         final ssin = flips.sin * scale; |         final ssin = flips.sin * scale; | ||||||
|  |  | ||||||
|         final transform = RSTransform( |         final transform = indexes[tx][ty] = MutableRSTransform( | ||||||
|           scos, |           scos, | ||||||
|           ssin, |           ssin, | ||||||
|           offsetX + -scos * anchorX + ssin * anchorY, |           offsetX, | ||||||
|           offsetY + -ssin * anchorX - scos * anchorY, |           offsetY, | ||||||
|  |           -scos * anchorX + ssin * anchorY, | ||||||
|  |           -ssin * anchorX - scos * anchorY, | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         // A second pass is only needed in the case of staggery. |         // A second pass is only needed in the case of staggery. | ||||||
| @ -377,13 +394,14 @@ class TileLayer extends RenderableLayer<tiled.TileLayer> { | |||||||
|         final scos = flips.cos * scale; |         final scos = flips.cos * scale; | ||||||
|         final ssin = flips.sin * scale; |         final ssin = flips.sin * scale; | ||||||
|  |  | ||||||
|         final transform = RSTransform( |         final transform = indexes[tx][ty] = MutableRSTransform( | ||||||
|           scos, |           scos, | ||||||
|           ssin, |           ssin, | ||||||
|           offsetX + -scos * anchorX + ssin * anchorY, |           offsetX, | ||||||
|           offsetY + -ssin * anchorX - scos * anchorY, |           offsetY, | ||||||
|  |           -scos * anchorX + ssin * anchorY, | ||||||
|  |           -ssin * anchorX - scos * anchorY, | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         // A second pass is only needed in the case of staggery. |         // A second pass is only needed in the case of staggery. | ||||||
|         if (map.staggerAxis == tiled.StaggerAxis.x && staggerY > 0) { |         if (map.staggerAxis == tiled.StaggerAxis.x && staggerY > 0) { | ||||||
|           xSecondPass.add(TileTransform(src, transform, flips.flip, batch)); |           xSecondPass.add(TileTransform(src, transform, flips.flip, batch)); | ||||||
|  | |||||||
| @ -5,11 +5,13 @@ import 'package:flame/extensions.dart'; | |||||||
| import 'package:flame/flame.dart'; | import 'package:flame/flame.dart'; | ||||||
| import 'package:flame/game.dart'; | import 'package:flame/game.dart'; | ||||||
| import 'package:flame_tiled/src/flame_tsx_provider.dart'; | import 'package:flame_tiled/src/flame_tsx_provider.dart'; | ||||||
|  | import 'package:flame_tiled/src/mutable_transform.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/group_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/group_layer.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/image_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/image_layer.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/object_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/object_layer.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/renderable_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/renderable_layer.dart'; | ||||||
| import 'package:flame_tiled/src/renderable_layers/tile_layer.dart'; | import 'package:flame_tiled/src/renderable_layers/tile_layer.dart'; | ||||||
|  | import 'package:flame_tiled/src/tile_stack.dart'; | ||||||
| import 'package:flutter/painting.dart'; | import 'package:flutter/painting.dart'; | ||||||
| import 'package:tiled/tiled.dart' as tiled; | import 'package:tiled/tiled.dart' as tiled; | ||||||
|  |  | ||||||
| @ -115,6 +117,74 @@ class RenderableTiledMap { | |||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /// Select a group of tiles from the coordinates [x] and [y]. | ||||||
|  |   /// | ||||||
|  |   /// If [all] is set to true, every renderable tile from the map is collected. | ||||||
|  |   /// | ||||||
|  |   /// If the [named] or [ids] sets are not empty, any layer with matching | ||||||
|  |   /// name or id will have their renderable tiles collected. If the matching | ||||||
|  |   /// layer is a group layer, all layers in the group will have their tiles | ||||||
|  |   /// collected. | ||||||
|  |   TileStack tileStack( | ||||||
|  |     int x, | ||||||
|  |     int y, { | ||||||
|  |     Set<String> named = const <String>{}, | ||||||
|  |     Set<int> ids = const <int>{}, | ||||||
|  |     bool all = false, | ||||||
|  |   }) { | ||||||
|  |     return TileStack( | ||||||
|  |       _tileStack( | ||||||
|  |         renderableLayers, | ||||||
|  |         x, | ||||||
|  |         y, | ||||||
|  |         named: named, | ||||||
|  |         ids: ids, | ||||||
|  |         all: all, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// Recursive support for [tileStack] | ||||||
|  |   List<MutableRSTransform> _tileStack( | ||||||
|  |     List<RenderableLayer> layers, | ||||||
|  |     int x, | ||||||
|  |     int y, { | ||||||
|  |     Set<String> named = const <String>{}, | ||||||
|  |     Set<int> ids = const <int>{}, | ||||||
|  |     bool all = false, | ||||||
|  |   }) { | ||||||
|  |     final tiles = <MutableRSTransform>[]; | ||||||
|  |     for (final layer in layers) { | ||||||
|  |       if (layer is GroupLayer) { | ||||||
|  |         // if the group matches named or ids; grab every child. | ||||||
|  |         // else descend and ask for named children. | ||||||
|  |         tiles.addAll( | ||||||
|  |           _tileStack( | ||||||
|  |             layer.children, | ||||||
|  |             x, | ||||||
|  |             y, | ||||||
|  |             named: named, | ||||||
|  |             ids: ids, | ||||||
|  |             all: all || | ||||||
|  |                 named.contains(layer.layer.name) || | ||||||
|  |                 ids.contains(layer.layer.id), | ||||||
|  |           ), | ||||||
|  |         ); | ||||||
|  |       } else if (layer is TileLayer) { | ||||||
|  |         if (!(all || | ||||||
|  |             named.contains(layer.layer.name) || | ||||||
|  |             ids.contains(layer.layer.id))) { | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (layer.indexes[x][y] != null) { | ||||||
|  |           tiles.add(layer.indexes[x][y]!); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return tiles; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /// Parses a file returning a [RenderableTiledMap]. |   /// Parses a file returning a [RenderableTiledMap]. | ||||||
|   /// |   /// | ||||||
|   /// NOTE: this method looks for files under the path "assets/tiles/". |   /// NOTE: this method looks for files under the path "assets/tiles/". | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								packages/flame_tiled/lib/src/tile_stack.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								packages/flame_tiled/lib/src/tile_stack.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | import 'package:flame/components.dart'; | ||||||
|  | import 'package:flame/effects.dart'; | ||||||
|  | import 'package:flame_tiled/src/mutable_transform.dart'; | ||||||
|  |  | ||||||
|  | /// A select group of tiles from RenderableTiledMap that can be animated. | ||||||
|  | /// | ||||||
|  | /// Tiles are nothing more than an x/y coordinate in each layer. TileStack lets | ||||||
|  | /// you collect a certain group of tiles out of all the layers, and then | ||||||
|  | /// set their positions.  This is typically done by using Flame's effects. | ||||||
|  | class TileStack extends Component implements PositionProvider { | ||||||
|  |   final List<MutableRSTransform> _tiles; | ||||||
|  |  | ||||||
|  |   /// The number of tiles in this stack. | ||||||
|  |   int get length => _tiles.length; | ||||||
|  |  | ||||||
|  |   TileStack(this._tiles); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Vector2 get position => _tiles.first.position; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   set position(Vector2 position) { | ||||||
|  |     for (final tile in _tiles) { | ||||||
|  |       tile.position = position; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,13 +1,14 @@ | |||||||
| import 'dart:ui'; | import 'dart:ui'; | ||||||
|  |  | ||||||
| import 'package:flame/sprite.dart'; | import 'package:flame/sprite.dart'; | ||||||
|  | import 'package:flame_tiled/src/mutable_transform.dart'; | ||||||
| import 'package:meta/meta.dart'; | import 'package:meta/meta.dart'; | ||||||
|  |  | ||||||
| /// Caches transforms for staggered maps as the row/col are switched. | /// Caches transforms for staggered maps as the row/col are switched. | ||||||
| @internal | @internal | ||||||
| class TileTransform { | class TileTransform { | ||||||
|   final Rect source; |   final Rect source; | ||||||
|   final RSTransform transform; |   final MutableRSTransform transform; | ||||||
|   final bool flip; |   final bool flip; | ||||||
|   final SpriteBatch batch; |   final SpriteBatch batch; | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <map version="1.9" tiledversion="1.9.1" orientation="isometric" renderorder="right-down" width="5" height="5" tilewidth="128" tileheight="64" infinite="0" nextlayerid="4" nextobjectid="1"> | <map version="1.9" tiledversion="1.9.1" orientation="isometric" renderorder="right-down" width="5" height="5" tilewidth="128" tileheight="64" infinite="0" nextlayerid="5" nextobjectid="1"> | ||||||
|  <tileset firstgid="1" name="isometric_spritesheet" tilewidth="128" tileheight="256" tilecount="4" columns="1"> |  <tileset firstgid="1" name="isometric_spritesheet" tilewidth="128" tileheight="256" tilecount="4" columns="1"> | ||||||
|   <image source="isometric_spritesheet.png" width="128" height="1024"/> |   <image source="isometric_spritesheet.png" width="128" height="1024"/> | ||||||
|  </tileset> |  </tileset> | ||||||
| @ -8,9 +8,14 @@ | |||||||
|    AgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAQAAAACAAAAAwAAAAMAAAACAAAAAwAAAAIAAAADAAAAAgAAAAIAAAAEAACAAgAAAAMAAAACAAAAAwAAAAIAAAACAAAAAgAAAA== |    AgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAQAAAACAAAAAwAAAAMAAAACAAAAAwAAAAIAAAADAAAAAgAAAAIAAAAEAACAAgAAAAMAAAACAAAAAwAAAAIAAAACAAAAAgAAAA== | ||||||
|   </data> |   </data> | ||||||
|  </layer> |  </layer> | ||||||
|  <layer id="2" name="item" width="5" height="5"> |  <layer id="2" name="item" class="items" width="5" height="5"> | ||||||
|   <data encoding="base64"> |   <data encoding="base64"> | ||||||
|    AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAACAAAAAAAAAAAAAAAAAAAAAAA== |    AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAACAAAAAAAAAAAAAAAAAAAAAAA== | ||||||
|   </data> |   </data> | ||||||
|  </layer> |  </layer> | ||||||
|  |  <layer id="4" name="emty" width="5" height="5"> | ||||||
|  |   <data encoding="base64"> | ||||||
|  |    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== | ||||||
|  |   </data> | ||||||
|  |  </layer> | ||||||
| </map> | </map> | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								packages/flame_tiled/test/goldens/tile_stack_all_move.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/flame_tiled/test/goldens/tile_stack_all_move.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 102 KiB | 
							
								
								
									
										
											BIN
										
									
								
								packages/flame_tiled/test/goldens/tile_stack_single_move.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/flame_tiled/test/goldens/tile_stack_single_move.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 104 KiB | 
| @ -310,8 +310,8 @@ void main() { | |||||||
|  |  | ||||||
|   Future<Uint8List> renderMapToPng( |   Future<Uint8List> renderMapToPng( | ||||||
|     TiledComponent component, |     TiledComponent component, | ||||||
|     int width, |     num width, | ||||||
|     int height, |     num height, | ||||||
|   ) async { |   ) async { | ||||||
|     final canvasRecorder = PictureRecorder(); |     final canvasRecorder = PictureRecorder(); | ||||||
|     final canvas = Canvas(canvasRecorder); |     final canvas = Canvas(canvasRecorder); | ||||||
| @ -320,7 +320,7 @@ void main() { | |||||||
|  |  | ||||||
|     // Map size is now 320 wide, but it has 1 extra tile of height becusae |     // Map size is now 320 wide, but it has 1 extra tile of height becusae | ||||||
|     // its actually double-height tiles. |     // its actually double-height tiles. | ||||||
|     final image = await picture.toImageSafe(width, height); |     final image = await picture.toImageSafe(width.toInt(), height.toInt()); | ||||||
|     return (await image.toByteData(format: ImageByteFormat.png))! |     return (await image.toByteData(format: ImageByteFormat.png))! | ||||||
|         .buffer |         .buffer | ||||||
|         .asUint8List(); |         .asUint8List(); | ||||||
| @ -624,6 +624,65 @@ void main() { | |||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   group('TileStack', () { | ||||||
|  |     late TiledComponent component; | ||||||
|  |     final size = Vector2(256 / 2, 128 / 2); | ||||||
|  |  | ||||||
|  |     setUp(() async { | ||||||
|  |       Flame.bundle = TestAssetBundle( | ||||||
|  |         imageNames: [ | ||||||
|  |           'isometric_spritesheet.png', | ||||||
|  |         ], | ||||||
|  |         mapPath: 'test/assets/test_isometric.tmx', | ||||||
|  |       ); | ||||||
|  |       component = await TiledComponent.load('test_isometric.tmx', size); | ||||||
|  |     }); | ||||||
|  |     test('from all layers', () { | ||||||
|  |       var stack = component.tileMap.tileStack(0, 0, all: true); | ||||||
|  |       expect(stack.length, 2); | ||||||
|  |  | ||||||
|  |       stack = component.tileMap.tileStack(1, 0, all: true); | ||||||
|  |       expect(stack.length, 1); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('from some layers', () { | ||||||
|  |       var stack = component.tileMap.tileStack(0, 0, named: {'empty'}); | ||||||
|  |       expect(stack.length, 0); | ||||||
|  |  | ||||||
|  |       stack = component.tileMap.tileStack(0, 0, named: {'item'}); | ||||||
|  |       expect(stack.length, 1); | ||||||
|  |  | ||||||
|  |       stack = component.tileMap.tileStack(0, 0, ids: {1}); | ||||||
|  |       expect(stack.length, 1); | ||||||
|  |  | ||||||
|  |       stack = component.tileMap.tileStack(0, 0, ids: {1, 2}); | ||||||
|  |       expect(stack.length, 2); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('can be positioned together', () async { | ||||||
|  |       final stack = component.tileMap.tileStack(0, 0, all: true); | ||||||
|  |       stack.position = stack.position + Vector2.all(20); | ||||||
|  |  | ||||||
|  |       final pngData = | ||||||
|  |           await renderMapToPng(component, size.x * 5, size.y * 5 + size.y / 2); | ||||||
|  |       expect( | ||||||
|  |         pngData, | ||||||
|  |         matchesGoldenFile('goldens/tile_stack_all_move.png'), | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('can be positioned singularly', () async { | ||||||
|  |       final stack = component.tileMap.tileStack(0, 0, named: {'item'}); | ||||||
|  |       stack.position = stack.position + Vector2(-20, 20); | ||||||
|  |  | ||||||
|  |       final pngData = await renderMapToPng(component, size.x * 5, size.y * 5); | ||||||
|  |       expect( | ||||||
|  |         pngData, | ||||||
|  |         matchesGoldenFile('goldens/tile_stack_single_move.png'), | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| class TestAssetBundle extends CachingAssetBundle { | class TestAssetBundle extends CachingAssetBundle { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 John McDole
					John McDole