4ian / GDevelop

🎮 Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.
https://gdevelop.io
Other
11.72k stars 886 forks source link

[$525 Bounty] Add support for tilemaps made in LDtk (build a parser for .ldtk files) #2434

Closed Silver-Streak closed 1 year ago

Silver-Streak commented 3 years ago

Description

Currently the Tilemap object in GD5 only supports Tilemap/Tileset JSON files made by Tiled Map Editor.

As discussed elsewhere, The Level Designer's Toolkit (LDtk) is a newer tilemap editor that has a much more user friendly interface, and allows for much faster iteration than what is available in Tiled Map Editor. LDtk is completely free and available at https://ldtk.io. It is developed by deepnight who is a dev at the studio Motion Twin, who have made a ton of retail games. (Dead Cells being a personal favorite of mine)

While LDtk does support exporting to Tiled TMX, this file cannot be consumed by GDevelop's tilemap objects, so it requires opening it in Tiled then exporting it as a JSON. This also strips some of the more advanced features in LDtk that are greatly beneficial for game development.

Solution suggested

Short-term solution :

Long-term solution (outside of the scope of this feature request):

Alternatives considered

I thought about asking to support TMX Format files since LDtk can export to that format, but those are in XML and would require a completely different interpreter. It also wipes out a lot of the more advanced features LDtk provides.

Bounty

Learn more about the bounty here: https://www.bountysource.com/issues/97132654-feature-request-add-support-for-tilemaps-made-in-ldtk-build-a-parser-for-ldtk-files

blurymind commented 3 years ago

I created a PR here, so we can start the review process going https://github.com/4ian/GDevelop/pull/2828

it can parse the ldtk examples already, just doesnt have a semi-transparency on layers. But I can add that while its reviewed - it requires jumping on the latest pixi-tilemap which doesnt work in Gdevelop atm

blurymind commented 3 years ago

ok some progress today, I finally got the latest pixi-tilemap to work in GD again, as well as add support for rendering opacity on layers. I addded some TODOs to the pr, but they shouldnt take too long to resolve - maybe by the end of the week tops image this is thanks to pixijs/tilemap#115

willianholtz commented 3 years ago

Hey @blurymind Sorry for my intrusion, but what exactly are you going to be able to do by merging LDtk with GDevelop? I ask this because I know there are a lot of things in LDtk, as well as the creation of worlds (gridvania). Will GD5 recognize this, or just the basemap (2D free map)? I know this is a long development, but it's just to satisfy my curiosity :)

Silver-Streak commented 3 years ago

Hit the wrong button, ignore the above. Sorry.

Silver-Streak commented 3 years ago

Hey @blurymind Sorry for my intrusion, but what exactly are you going to be able to do by merging LDtk with GDevelop? I ask this because I know there are a lot of things in LDtk, as well as the creation of worlds (gridvania). Will GD5 recognize this, or just the basemap (2D free map)? I know this is a long development, but it's just to satisfy my curiosity :)

In case Blurymind doesn't get a chance to respond respond, at this time I believe the PR being worked on is just .LDTK file support for the existing Tilemap object, not integration of LDTK itself as an editor/interpreter.

There IS a separate discussion/issue for integrating LDTK as the built-in tilemap editor, but I don't think that is the focus of this issue/PR/bounty.

blurymind commented 3 years ago

Hey @blurymind Sorry for my intrusion, but what exactly are you going to be able to do by merging LDtk with GDevelop? I ask this because I know there are a lot of things in LDtk, as well as the creation of worlds (gridvania). Will GD5 recognize this, or just the basemap (2D free map)? I know this is a long development, but it's just to satisfy my curiosity :)

This issue and the pr I created covers being able to read ldtk files in gdevelop. This includes multiple maps in the file yes - you can tell gdevelop which map to display via its index. Apart of that it can also do multiple tilesets.

There are a couple of things we can't do yet, such as automatic creation of collisions and game objects with properties on them. But I am more focused now in getting the base rendering to work right. Currently it does, I just need to address flipped tiles for ldtk and some other details.

If we are to also parse game objects, that would actually make them bundled inside the map and hard to manage in gdevelop. I wonder if it would be better if gdevelop creates them from the ldtk as normal sprite objects with properties on them, but that would create a new problem with having to pair them with the data. What happens if you edit them in gdevelop and then in ldtk - do they lose the edits they got in gdevelop?

One idea is to have them created only once and not sync them with the map data, but that would defeat the purpose of them being there. Another is to keep them in the map object, but have commands in gdevelop to get data from them, so you can create objects during runtime. That would also be kind of cumbersome imo.

In any case I can add an expression to gdevelop, which lets you get data from ldtk maps in the event sheet. From there on you can use it to set things. That would be potentially simple to do, but it will leave you with the task of manually setting things up with the event sheet. In any case - doing this for both tiled and ldtk should be for another pr imo. It needs some careful planning and discussion before work is done to get it there

willianholtz commented 3 years ago

Thanks for the answer @blurymind. I hope you can do everything you have in mind. GD can (and I believe it will) become a super known and pleasurable tool to work with. I really like how "RPG Maker" works on your tiles, maybe you can be inspired by it ;)

blurymind commented 3 years ago

Some progress today:

I finally added support for flipped tiles in ldtk via pixi-tilemap's rotate option image

blurymind commented 3 years ago

Thanks for the answer @blurymind. I hope you can do everything you have in mind. GD can (and I believe it will) become a super known and pleasurable tool to work with. I really like how "RPG Maker" works on your tiles, maybe you can be inspired by it ;)

Yes I believe so too. With such a big bounty I am motivated to also get ldtk bundled as a next pr once this one is closed. Getting this contribution from the creator of what is such a fantastic tilemap editor makes me want to make it better integrated than our other external editors.

If I make a react wrapper around it, it could become another tab in gdevelop. The tricky bit would be in protecting against any electron specific code crashing the web version of gdevelop. Maybe something to discuss at the other issue

blurymind commented 3 years ago

One idea I had for getting ldtk/tiled entities into gdevelop is to create some sort of an event sheet action which basically gets an entity you specify and assigns all of its variables to a gdevelop object which you specify. That way you can automatically transfer variables of an entity in ldtk to those of an object inside gdevelop.

@4ian @Bouh @Silver-Streak @deepnight what do you think of that approach? I am just trying to figure out a way we can get entity data into gdevelop quickly, but allow for flexibility of that entity to be edited in gdevelop. It needs some sort of pairing mechanism to link ldtk entities to gdevelop objects and allow those objects to be edited in gdevelop's ide

In any case dealing with entities with variables from tiled and ldtk needs its own pr/issue and could be tricky to get right imo.

Silver-Streak commented 3 years ago

@blurymind I think this is an awesome idea...but what about we take it out one level?

What if the entity data was imported as object variables (probably some kind of structure or array) of the tilemap object as part of using the LDTK map?

Like, turning this from the output JSON into an array or structure variable on the tilemap object itself? image (probably without the need for the grid/pivot/etc, but the Name (identifier), UID (assuming we're not actively displaying the entities layer in some way, this would be important to know entity "order"), type (array), then a "Values" subarray which includes {Point, cx 10, cy 24}, {Point, cx14, cy21}, etc)

In theory this would allow all of the entity data to be visible in the Editor (by looking at the Tilemap's object variables), the user could use existing events and expressions to pull those variables for other needs, and you wouldn't have to worry about object creation?

blurymind commented 3 years ago

Some progress today

flipping is now done by pixi-tilemap instead of us,via the rotate option

     const pixiTilemapFrame = pixiTileMap.tile(
                tileTexture,
                xPos,
                yPos,
                { alpha: layer.opacity, rotate }
              );

@Silver-Streak can you create another issue to discuss how entities are handled and continue there? :) Already a lot of ideas

4ian commented 3 years ago

Ah nice, is the rotate something built recently in pixi tilemap?

In any case dealing with entities with variables from tiled and ldtk needs its own pr/issue and could be tricky to get right imo.

Yes, entities should be indeed a separate concern.

An action to get entities variables translated into an object is probably a good idea though, but that's for another day.

Silver-Streak commented 3 years ago

Discussion on handling entities created: https://github.com/4ian/GDevelop/discussions/2836

blurymind commented 3 years ago

Ah nice, is the rotate something built recently in pixi tilemap?

I believe @ivanpopelyshev added it in the end of 2019 https://github.com/pixijs/tilemap/commit/54ebaa379f92e72f54f019f6b563b53c572879df

Will it be ok if I also add support for varied animation speed in tiles for tiled format in the same pr? I recently added it to pixi-tilemap, so I am a bit eager to get that in the extension. When ldtk gets that at some point, it will also be easy to add.

I want to take advantage of all of pixi-tilemap's options

An action to get entities variables translated into an object is probably a good idea though, but that's for another day.

In any case dealing with entities with variables from tiled and ldtk needs its own pr/issue and could be tricky to get right imo.

Yes, entities should be indeed a separate concern.

Yes absolutely. Its a design task that has lots of caveats which need to be discussed in advance. @Silver-Streak thanks :) whatever we implement for entities will need to work with both tiled and ldtk in a consistent way- so its good to start thinking about how it would work sooner than later.

I see some overlap of dealing with entities and collisions from both apps, but they are very different in my head

blurymind commented 3 years ago

Some progress today, added ability to render tilemap backgrounds

image

with that all rendering features from Test_File_For_Api_showing_all_features.ldtk from ldtk's samples now work in the runtime and the IDE. The ide still doesnt render entities - but I think that should be done in the entities task.

The example file has these bits that dont contain any actual textures: image @deepnight are they supposed to render in the runtime of the game? I suppose I can make them only render in the IDE if they are required. I am thinking of doing that for entities - only render entities in the IDE

Btw this is how easy it is to set up switching between levels contained in a single ldtk file changeLevelsLdtk

MorphicDreamer commented 2 years ago

still open?

Silver-Streak commented 2 years ago

still open?

Yep! https://github.com/4ian/GDevelop/pull/2828

You can see active/linked pull requests at the bottom of any open issue.

MorphicDreamer commented 2 years ago

still open?

Yep! https://github.com/4ian/GDevelop/pull/2828

You can see active/linked pull requests at the bottom of any open issue.

Upon looking I noticed that another dev is currently writing a fix.

Silver-Streak commented 2 years ago

This has neared another birthday, and people are asking about this again on discord and the forums.

I've bumped up the bounty on this and the ldtk integration/bundling to hopefully renew drive/interest.

daiyam commented 2 years ago

Hello, is the bounty still active?

Silver-Streak commented 2 years ago

It is. The original person working on it has unfortunately gone silent. You can review their incomplete PR here, but you'd likely want to start from scratch as they were running into rodeblocks with the method they were working on.

I'd recommend reviewing and writing up a proposal on how you'd want to proceed, and one of the mainline devs can review and give you a green light. That way you don't waste to much time building something out if it'll just run into the same roadblocks.

daiyam commented 2 years ago

I've made some progress. Since that PR, the TileMap has been rewritten so I couldn't used it. I had to restart from "scratch". But it is/was still useful.

Here are my 3 main issues:

daiyam commented 2 years ago

Here what I have so far: LDtk

I'm having an issue with the shelfs in background because they are half step (x=8.5, y=10) on the grid. I'm not sure what to do...

Silver-Streak commented 2 years ago

I'd wait for one of the main contributors/devs to chime in, but I don't think Tiled supports floating positions either, so I don't know that there's a hard requirement to have the ldtk file support non-integers even if the base app does.

This is just my opinion on it, though.

daiyam commented 2 years ago

@Silver-Streak I've just tested. When exported from LDtk to Tiled, the shelves are shifted. I can do that.

4ian commented 2 years ago

@daiyam That looks like great progress :) On your issues, here is my thinking:

How to load the resources? I would like to automatically import the tilemap and all its resources when the tilemap is added. This will avoid the force the user to manually import all the resources.

That's the hard bit. The current resource system is basically one file = one resource (there are no "meta resources" linking to more than one file). How do you work currently? Do you ask for all resources manually by the user? Did you hardcode their loading?

Depending on what it looks like currently (or if we can look at the code directly), we can think of how to make this user friendly.

LDtk allows for different grid sizes to used in the same scene. For now, should we have only 1 size?

I guess so, we can add support for this later?

What about the collision map? Should it be another object or have dropdown to select the collision layer?

@D8H created a "Tilemap collision mask" object - I think ideally we should use it:

image

This is because this allows to have different objects, one for platforms, one for jump thrus, etc... For the user, this means they would use their ldtk file for the tilemap object and reuse it again for the "Tilemap collision mask" object.

daiyam commented 2 years ago

How do you work currently?

For I've changed the tilesets.relPath to SunnyLand_by_Ansimuz-extended.png then added a resource with the same name... I haven't done any work on how to load the resources since I knew you had some reservations to add new way to load resources. I want to validate with you before to make the needed changes. So I was more thinking that when adding a LDtk map, the editor will parse it and locate all the files and import all those files to the project as resources and then, rewrite the json with the corresponding resource ids.

@D8H created a "Tilemap collision mask" object - I think ideally we should use it:

I will look into that


LDtk has floating tiles. Now, they are rounded to the lower integer (like LDtk does when exporting for Tiled).

LDtk

daiyam commented 2 years ago

All the levels:

Capture

Silver-Streak commented 2 years ago

Just to clarify, LDTK doesn't currently natively have a collision layer of any kind. I suppose you could have it pick up x/y point entities (or enums) named in a certain way to have them mapped to collision polygons?

(Deepmind has collision and geometry handling on the roadmap, but I don't think there is any design around it done yet)

daiyam commented 2 years ago

@Silver-Streak true, I was misled by their example (a layer is called Collisions). Some grass and the ladders are that layer...

Silver-Streak commented 2 years ago

Yeah, with no current native collision support, I'd be interested in @D8H 's feelings on whether to map collisions to LDTK files at all before official support.

Even with an x,y (point) entities layer, the layer would have to be a different grid size (likely 1x1) to be used for collisions accurately, which would require supporting different grid sizes.

daiyam commented 2 years ago

which would require supporting different grid sizes.

LDtk does support that. That was one of my question.

I will wait for @D8H's inputs.


I was finally able to compile GDevelop.js, GnuWin was messing up the previous attempts... (or I was using Powershell or bash)

D8H commented 2 years ago

If you mean layer grid offsets, the extension doesn't handle it for Tiled. I don't think it's mandatory. It can be done in another PR.

Silver-Streak commented 2 years ago

If you mean layer grid offsets, the extension doesn't handle it for Tiled. I don't think it's mandatory. It can be done in another PR.

To be clear, layer grid offsets and collisions both could be handled in another PR, correct?

D8H commented 2 years ago

To be clear, layer grid offsets and collisions both could be handled in another PR, correct?

Correct

daiyam commented 2 years ago

I'm having an issue with adding a new TilemapResource for supporting .ldtk files. I can get it working and all but then, the old tilemap resources which are mapped to JsonResource can't be reassigned anymore. The old tilemap are correctly displayed but if you remove the property from the object and re-add it, you get an error!

What to do? New object type?

daiyam commented 2 years ago

I've pushed my PR. I made some substantial changes so you might have some concerns...