Code Monkey home page Code Monkey logo

tiled.dart's Introduction

Tiled Dart

Pub cicd Discord

A Dart Tiled library.

Install from Dart Pub Repository

To include the package as a depencency in your pubspec.yaml, run the following (or add it manually):

dart pub add tiled

Usage

Import the package like this:

    import 'package:tiled/tiled.dart';

Load Tmx Files

Load a TMX file into a string by any means, and then pass the string to TileMapParser.parseXml():

    final String tmxBody = /* ... */;
    final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody);

If your tmx file includes a external tsx reference, you have to add a CustomParser

class CustomTsxProvider extends TsxProvider {
  @override
  Parser getSource(String fileName) {
    final xml = File(fileName).readAsStringSync();
    final node = XmlDocument.parse(xml).rootElement;
    return XmlParser(node);
  }
}

And use it in the parseTmx method

    final String tmxBody = /* ... */;
    final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody, tsx: CustomTsxProvider());

Load Json Files

Alternatively load a json file.

    final String jsonBody = /* ... */;
    final TiledMap mapTmx = TileMapParser.parseJson(jsonBody);

Implementation

For further information and more usage examples, please take a look at the examples in flame_tiled.

tiled.dart's People

Contributors

arne1303 avatar bung87 avatar devoncarew avatar diegomgarcia avatar doodlezucc avatar feroult avatar hwan-seok avatar klapacz avatar kurtome avatar lfraker avatar luanpotter avatar natebot13 avatar radicaled avatar schnurber avatar signmotion avatar spydon avatar supagu avatar synchronisator avatar ufrshubham avatar wolfenrain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tiled.dart's Issues

How to get a Tile's x, y coordinates in 0.7.0?

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.

Spacing field in tmx file is not working

tiles-5

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.

flutter_01

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

Bug in objectalignment parsing

final objectAlignment = parser.getObjectAlignment(
'objectalignment',
defaults: ObjectAlignment.unespecified,
);

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.

Dart SDK compatibility

What could be improved

Remove requirement for dart:ui and therefore the Flutter SDK

Why should this be improved

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.

Any risks?

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:

  • Color, which I replaced with color_models and a little bit of code for hex parsing
  • Rect, which I simply replaced by dart:math's Rectangle

More information

These 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!

Ability to access the image rect for tiles

Problem to solve

Each tile in a tileset has an Image Rect property which doesn't seem to be accessible in tiled.dart. Getting access to that property would allow users to use tiles from Object layers to spawn in sprite based components.

image

Proposal

More information

Bump xml to latest (6.1.0)

What could be improved

Bump xml to latest (6.1.0)

Why should this be improved

Because we cannot upgrade packages that load both tiled and xml

Any risks?

More information

Test Function on custom TsxProvider`s

What could be improved

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.

Why should this be improved

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

Any risks?

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.

More information

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.

Bit shifts processing tile flips break down around gid=>2^28

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

RangeError on Layer.tiles in 0.4.0

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.

Template parsing does not work

Current bug behaviour

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.

Expected behaviour

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.

More information

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.

Make it easier and more efficient to access a property by name

What could be improved

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.

Why should this be improved

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.

Any risks?

This would be a breaking change.

The Template cannot be properly parsed.

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.

flutter_test from sdk is incompatible with flame >=0.24.0

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.

Object Layers expect ints, which prevents tmx file from loading

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

FormatException when parsing a tmx file

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>

Issue when parsing multiple external tilesets.

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!

ObjectGroup on tiles not getting parsed from .tsx file

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?

Map Export

What could be improved

Exporting Maps from this package to tmx and json

Why should this be improved

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!

parser.dart not imported in v0.7.0

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

[proposal] Omit empty TiledImage from TiledMap.tiledImages

What could be improved

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.

final imageSet = <TiledImage>{};
for (var i = 0; i < tilesets.length; ++i) {
final image = tilesets[i].image;
if (image != null) {
imageSet.add(image);
}
for (var j = 0; j < tilesets[i].tiles.length; ++j) {
final image = tilesets[i].tiles[j].image;
if (image != null) {
imageSet.add(image);
}

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

Why should this be improved

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".

Any risks?

This cannot be true but there might be some users that use the empty Tiledimage.

More information

Parse JSON produces no data inside layers

Current bug behaviour

Returned object has no layers

Expected behaviour

A List with the objects as shown on the json

Steps to reproduce

Flutter doctor output

Output of: flutter doctor -v

More environment information

Tiled version: 1.9.2
Platform: Web Chrome
Package version: 0.9.0

Log information

Output
image (127)

Source files
tiles.zip

More information

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.