flame-engine / tiled.dart Goto Github PK
View Code? Open in Web Editor NEWA Dart Tiled library. Parse your TMX files into useful representations. Compatible with Flame.
Home Page: https://flame-engine.org/
License: MIT License
A Dart Tiled library. Parse your TMX files into useful representations. Compatible with Flame.
Home Page: https://flame-engine.org/
License: MIT License
See this example including sample data:
https://gist.github.com/pgainullin/bdf8ac141e9501958c993bb4467685fb
Running it in DartPad shows several IDs turn to 268435492 and 268435498 post flag-clearing. Given that there are bit shifts in this code and 2^28=268435456 it looks like some sort of an overflow error.
I can't see any issues just by looking at the code in tiled/src/layer.dart assempleTileMatrix vs the docs (https://doc.mapeditor.org/en/stable/reference/tmx-map-format/) but I don't know enough about bitwise operations in Dart to really understand it
This is for version 0.9.0
of package:tiled. I get a FormatException when parsing a specific tmx file. I believe this is due to some empty terrain values in some tile elements; for example, <tile id="4" terrain=",,,0"/>
.
The following FormatException was thrown building FutureBuilder<void>(dirty, state:
_FutureBuilderState<void>#f3561):
Invalid number (at character 1)
^
The relevant error-causing widget was:
FutureBuilder<void>
FutureBuilder:file:///Users/devoncarew/.pub-cache/hosted/pub.dev/flame-1.4.0/lib/src/game/game_widget/game_widget.dart:358:28
When the exception was thrown, this was the stack:
#0 int._handleFormatError (dart:core-patch/integers_patch.dart:124:7)
#1 int.parse (dart:core-patch/integers_patch.dart:50:14)
#2 MappedListIterable.elementAt (dart:_internal/iterable.dart:414:31)
#3 ListIterator.moveNext (dart:_internal/iterable.dart:343:26)
#4 new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:189:27)
#5 new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
#6 new List.of (dart:core-patch/array_patch.dart:52:28)
#7 ListIterable.toList (dart:_internal/iterable.dart:214:7)
#8 new Tile.parse (package:tiled/src/tileset/tile.dart:64:20)
#9 MappedListIterable.elementAt (dart:_internal/iterable.dart:414:31)
#10 ListIterator.moveNext (dart:_internal/iterable.dart:343:26)
#11 new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:189:27)
#12 new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
#13 new List.of (dart:core-patch/array_patch.dart:52:28)
#14 ListIterable.toList (dart:_internal/iterable.dart:214:7)
#15 Parser.getChildrenAs (package:tiled/src/parser.dart:88:42)
#16 new Tileset.parse.<anonymous closure> (package:tiled/src/tileset/tileset.dart:127:20)
#17 XmlParser.formatSpecificParsing (package:tiled/src/parser.dart:41:15)
#18 new Tileset.parse (package:tiled/src/tileset/tileset.dart:125:26)
#19 new TiledMap.parse.<anonymous closure> (package:tiled/src/tiled_map.dart:285:26)
#20 MappedListIterable.elementAt (dart:_internal/iterable.dart:414:31)
#21 ListIterator.moveNext (dart:_internal/iterable.dart:343:26)
#22 new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:189:27)
#23 new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
#24 new List.of (dart:core-patch/array_patch.dart:52:28)
#25 ListIterable.toList (dart:_internal/iterable.dart:214:7)
#26 Parser.getChildrenAs (package:tiled/src/parser.dart:88:42)
#27 new TiledMap.parse (package:tiled/src/tiled_map.dart:280:29)
#28 TileMapParser.parseTmx (package:tiled/src/tile_map_parser.dart:19:21)
#29 TiledMap.fromString (package:tiled/src/tiled_map.dart:145:26)
<asynchronous suspension>
#30 RenderableTiledMap.fromString (package:flame_tiled/src/renderable_tile_map.dart:209:17)
<asynchronous suspension>
#31 TiledComponent.load (package:flame_tiled/src/tiled_component.dart:93:7)
<asynchronous suspension>
#32 TiledGame.onLoad (file:///Users/devoncarew/projects/devoncarew/mushamils/example/tiled_example.dart:23:9)
<asynchronous suspension>
#33 _GameWidgetState.loaderFuture.<anonymous closure> (package:flame/src/game/game_widget/game_widget.dart:201:11)
<asynchronous suspension>
#34 _FutureBuilderState._subscribe.<anonymous closure> (package:flutter/src/widgets/async.dart:628:33)
<asynchronous suspension>
Instead of checking by filename TsxProvider (or a new base class) could provide a function to check if a source can be resolved by the Provider.
As I have mentioned in #69 (nice) I am currently working on a CLI to optimize tmx files. For this I resolve tsx files relative to the respective tmx file. Currently this has to be done by parsing to XML beforehand and resolving the tsx locations and then generating a TsxProvider for each. This seems rather inefficient
I believe that this carries minmal risk, since the current functionality could be easily kept as a implementation of a new TsxProviderBase. Therefore no public contracts, naming or functionality would need to change, while greatly extending the capability of custom TsxProvider`s.
I would gladly prepare a PR for this and improving documentation both in the README.md (which currently is wrong) and in code to explain this behaviour! I have already implemented this in the "#70-tsx-provider" branch of my fork.
tiled.dart/packages/tiled/lib/src/layer.dart
Line 144 in d71d0c8
Is this line supposed to return null? This seems to make tileData for the layer be null, causing a null assertion failure in flame_tiled that assumes tileData is not null.
Root causing this one was a bit of a wild chase through two repos, but it seems like when parsing a tiled map that references multiple external tilesets, all parsed tileset properties are all overwritten by the first external tileset file.
If I'm understanding the design correctly, if the Tileset is external and referenced in the .tmx file, via the 'source' property, then you need to pass in a TsxProvider to TileMapParser.parseTmx.
When parsing the tiled map in the flame engine, the code pulls the first tileset external reference, if available, and passes it in (https://github.com/flame-engine/flame/blob/5c47d7f6d7ed4705a3f19e9119364d9c6e6cff55/packages/flame_tiled/lib/src/renderable_tile_map.dart line 65):
TsxProvider? tsxProvider;
if (tsxSourcePath != null) {
tsxProvider = await FlameTsxProvider.parse(tsxSourcePath);
} else {
tsxProvider = null;
}
return TileMapParser.parseTmx(contents, tsx: tsxProvider);
This provider is passed through the parse tree for every tileset in the map (https://github.com/flame-engine/tiled.dart/blob/main/lib/src/tiled_map.dart line 221):
final tilesets = parser.getChildrenAs(
'tileset',
(e) => Tileset.parse(e, tsx: tsx),
);
Subsequently, when each tileset is parsed, if a TsxProvider is given, it seems like every property that appears in the provided external reference overwrites the properties of the tileset being parsed (e.g. name, tilecount, etc.) See _checkIfExtenalTsx method, https://github.com/flame-engine/tiled.dart/blob/main/lib/src/tileset/tileset.dart line 165.
I've been able to produce a repro of this issue with a local unit test. I've only tested multiple external tilesets, but it seems like an external + embedded tileset would potentially run into the same issue where the embedded tileset would be overwritten by the external tileset properties.
Since TsxProvider is simply a passthrough everywhere except the TileSet parser, would it be possible to generate the TsxProvider on the fly for each tileset here, rather than having the external caller pass it in?
(https://github.com/flame-engine/tiled.dart/blob/main/lib/src/tiled_map.dart line 221):
final tilesets = parser.getChildrenAs(
'tileset',
(e) => Tileset.parse(e, tsx: tsx),
);
It seems like the way it was setup today was to support when a caller want's to pass in an external reference that isn't found in the .tmx file (not sure if this is a common use case)?
I plan to proceed with embedding all of the tilesets into my map file, so this is probably a lower-pri ask, but it would be nice to have this fix at some point if possible!
Properties on tiles and objects are unique, but are returned as List<Property>
, which makes it difficult to access a property by name and requires iterating through the entire list each time.
So, I'm suggesting changing tile.properties
and object.properties
(and anywhere else applicable) to Map<String, Property>
, for better access.
The Tiled editor doesn't allow multiple properties with the same name, and accessing the properties by name would better match the Tiled editor. In addition, if the properties are keyed by name it will be more efficient.
This would be a breaking change.
Hello, flutter_test
from sdk is incompatible with flame >=0.24.0
. Can you help me?
Because every version of flutter_test from sdk depends on xml 3.6.1 and tiled >=0.4.0 depends on xml ^4.2.0, flutter_test from sdk is incompatible with tiled >=0.4.0.
And because flame >=0.24.0 depends on tiled ^0.6.0, flutter_test from sdk is incompatible with flame >=0.24.0.
So, because simiapp depends on both flame ^0.24.0 and flutter_test any from sdk, version solving failed.
pub get failed (1; So, because flutter_app depends on both flame ^0.24.0 and flutter_test any from sdk, version solving failed.)
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.17.5, on Mac OS X 10.15.4 19E287, locale
zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 11.4.1)
[✓] Android Studio (version 3.6)
[!] IntelliJ IDEA Community Edition (version 2020.1.1)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[!] VS Code (version 1.42.1)
✗ Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)
! Doctor found issues in 2 categories.
Later.tiles was recently changed from a one dimensional list of Tiles to a two dimensional List. (ie from List to List<List> the test needs to be updated accordingly.
The TmxObject.fromXML expects ints for x,y, width. height & rotation, but Tiled files have doubles. T
NodeDSL.on(element, (dsl) {
name = dsl.strOr('name', name);
type = dsl.strOr('type', type);
x = dsl.intOr('x', x);
y = dsl.intOr('y', y);
width = dsl.intOr('width', width);
height = dsl.intOr('height', height);
rotation = dsl.intOr('rotation', rotation);
gid = dsl.intOr('gid', gid);
visible = dsl.boolOr('visible', visible);
});`
Bump xml to latest (6.1.0)
Because we cannot upgrade packages that load both tiled
and xml
Exporting Maps from this package to tmx and json
I will be creating an exporter (at least for xml/tmx) anyway, if you are interested in this functionality I would be happy to submit a PR to add this functionality to this package. If not I will create a seperate package for it 😄
I have not implemented this yet, but will probably get to it next week. If you have any insights, recommendations or wishes I would appreciate a comment!
A RangeError is generated when accessing the Layer.tiles getter on non-square maps. Latest 0.4.0 version. This is due to the _tiles list being [x][y] and the tileMatrix and tileFlips lists being [y][x]. One or the other should be changed, or the addressing changed. Someone else can decide which way to go with it.
When I tested correcting it, I got past the range errors but tiles in the map still didn't look right. Its not my map (Flame's test map) so I didn't pursue it further at this time.
tiled.dart/lib/src/tileset/tileset.dart
Lines 108 to 111 in 7873565
This should instead be:
final objectAlignment = parser.getObjectAlignment(
parser.getString('objectalignment', defaults: 'unspecified'),
defaults: ObjectAlignment.unespecified,
);
or, instead could be simplified to:
final objectAlignment = ObjectAlignment.values.byName(
parser.getString('objectalignment', defaults: 'unspecified'),
);
Along with this, ObjectAlignment.unespecified
is misspelled, and the attribute is not copied from external tilesets.
Remove requirement for dart:ui
and therefore the Flutter SDK
Currently this package/parser is only usable with the Flutter SDK. However I believe there are valid use-cases for the Dart SDK. For example I'm currently working on a CLI to optimize tmx to only include the tiles actually used in a map in it's tilesets. This is not possible using the Flutter SDK.
This improvement would require the removal of all dart:ui dependencies. However there are only two in this project, which I replaced in the "#69-dart-sdk branch" on my fork:
dart:math
's RectangleThese changes would break public contracts and therefore require some work on the flame_tiled plugin.
However I believe this would be minimal. I did not look into this further, but from what I changed this would only require converting Rect to Rectangle and casting ColorModel to Model, which is implemented in flutter_color_models.
I believe this would be worth it and I am prepared to submit PRs both here and in flame_tiled to make these rather simple changes. However if you would consider this to be too invasive, I am happy to just keep this as a fork!
The above tiles image in Tiled Map Editor with spacing = "1"
is working fine. But when it comes to flame_tiled its not working.
The output I get is the below image with those yellow lines which are from the tile image above.
I am just a noob and I don't know if this occurs due to my code. Also, in the example file of flame_tiled repo the image doesn't have those yellow grid lines.
The tmx file can be found in the repo attached below.
Please run this game for further reference
https://github.com/Jcupzz/Super-Mario.git
There is also missing support for properties in classes: Layers, TileMap, and position and size as float numbers in objects.
I'm new to Flame and Tiled, so I may be doing something wrong, but I am trying to annotate collidable tiles in Tiles Collision Editor to simplify the work of creating repeated collidable game objects. When I import the TileMap via
final TiledComponent tiledMap = await TiledComponent.load('tilemap.tmx', Vector2.all(50));
The objectGroup value is null on all Tiles, even though in the .tsx file there is an objectgroup node populated:
<tile id="30" probability="0.5">
<objectgroup draworder="index" id="6">
<object id="11" x="3.25359" y="4.52951" width="25.3907" height="20.2233">
<ellipse/>
</object>
</objectgroup>
</tile>
I was looking through the repo, and it seems like the issue could simply be a camelCase instead of lowercase name in the Tile parser. in https://github.com/flame-engine/tiled.dart/blob/cb08bc937f82a6ed42cb47fa9b526446ea8e9f76/lib/src/tileset/tile.dart on line 59, the parser tries to parse an 'objectGroup' node instead of an 'objectgroup' node:
objectGroup: parser.getSingleChildOrNullAs('objectGroup', Layer.parse)
Parsing objectGroups works correctly for tileMaps since the layer parsing code path uses the lowercase name (https://github.com/flame-engine/tiled.dart/blob/f719702b6be93edb46f972bceb1c431e40bf0f7d/lib/src/layer.dart on line 246):
xml.getChildrenAs('objectgroup', Layer.parse)
Please let me know if the above camelCase is intended, or if my use is not a supported case?
Is there another recommended way to simplify the defining of collision boxes on multiple terrain tiles?
Returned object has no layers
A List with the objects as shown on the json
Output of: flutter doctor -v
Tiled version: 1.9.2
Platform: Web Chrome
Package version: 0.9.0
Source files
tiles.zip
Note: I am not sure if this is a bug or a proposal.
Change the TiledMap.tiledImages
to return only tilesets that have an actual source
.
tiled.dart/packages/tiled/lib/src/tiled_map.dart
Lines 205 to 215 in 1d3043f
As-is
if (image != null) {
imageSet.add(image);
}
imageSet.addAll(layers.whereType<ImageLayer>().map((e) => e.image));
To-be
if (image?.source != null) {
imageSet.add(image!);
}
imageSet.addAll(layers.whereType<ImageLayer>().map((e) => e.image)).where((e) => e.source != null);
At present, TiledMap.tiledImages
collects all images in the map including those without the source
.
I think the TiledImages
without source
is not actually the "image".
For example, the following is a bare image layer without the source:
<imagelayer id="4" name="Image Layer 2"/>
I think it is a layer but doesn't include any image.
The following is another example:
<tileset firstgid="1810" name="tileset 1" tilewidth="1" tileheight="1" tilecount="0" columns="0"/>
Also, this is a tileset but not includes any "image".
This cannot be true but there might be some users that use the empty Tiledimage
.
in tiled.dart I see:
import 'src/parser.dart';
should this be:
export 'src/parser.dart';
as I cant return a Parser from my TsxProvider
The TiledObject.parse()
function tries to find a <template>
child of <object>
. However according to the TMX Documentation and the dartdoc comment above the class such an element is not allowed as a child.
Tiled uses the template reference in the template
attribute of <object>
to find the external template file. Maybe a lookup mechanism like TsxProviders is needed.
Together with the extension to TsxProviders in #70 it might be worth generalizing a Provider for Tsx, template files and images.
I would be interested in working on a PR for this, however I do not need this functionality atm, so I wouldn't get to it for a few weeks.
static TiledObject parse(Parser parser) {
...
final template = parser.getSingleChildOrNullAs('template', Template.parse);
...
}
static Template parse(Parser parser) {
return Template(
tileSet: parser.getSingleChildOrNullAs('tileset', Tileset.parse),
object: parser.getSingleChildOrNullAs('object', TiledObject.parse),
);
}
Template is provided as a file, but the file is not loaded here.
0.6.0 had an x and y value for the Tile, in 0.7.0 this is missing, so if I pass a tile around I can't generate its world coordinates unless you know its row/column values.
Also it would seem helpful for a Tile to have a reference back to the TileLayer it belongs too.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.