Open biouxtai opened 13 years ago
Why is an object area not feasible?
Note that since 0.6.0 you can also place tiles on an object layer, in which case you can assign them individual properties.
The issue is that I would need an object layer per tile I want to set properties on. In the game I am developing this would require an object layer per tile placed. If I were able to set properties at the cell level rather than the tileset level I would not need any object layers as all custom properties could be contained in the cell.
I should add that I am not using Tiled to create the actual map that you walk on. I am using it as a top down map editor to place the various features I need. For example a wall with a door in it. It would be unrealistic to create either a custom tile per permutation of the features a door can have, or create a new object layer with the properties applied. The same goes for creating a new tile layer with custom properties there.. it becomes ... cumbersome. I have written a custom exporter that generates the xml I need in the map file format I use. In theory, I could extend my plugin to handle this, but that would require clever ways of using the layers to get the same effect of simply right clicking on the cell and adding the property there. I do think that the property should exist in the layer, but I don't think it should be limited to the tilesets themselves.
Another example from my project is that each tile has different requirements that have to be met before a player can step in that direction. Again, keeping in mind that my game is not top-down nor isometric, but rather first person. I am not directly using the map as you see it in Tiled. It first has to be exported.
One thought I had was that if you have custom properties defined at the tileset, when you place the tile in the layer, it can copy those to the cell. I think there should still be a properties object at the layer level, but also one specific to each cell.
On Jul 6, 2011, at 12:54 PM, bjorn wrote:
Why is an object area not feasible?
Note that since 0.6.0 you can also place tiles on an object layer, in which case you can assign them individual properties.
Reply to this email directly or view it on GitHub: https://github.com/bjorn/tiled/issues/31#issuecomment-1513782
Why can't you just set properties on the objects? Maybe the feature is too hidden. You can set properties on objects (and tile objects) by using the 'Select Objects' tool and right-clicking on your objects.
In the next version this right-click menu will be available in all object tools.
Object layers will become cumbersome in that I will need one layer for each unique combination of features I want. So for a door: is it lockable, openable, trapped, keyed, magicked, the list goes on, however for just these five features I now require an object layer for each unique combination. This is a burden on map developers. At the cell level, I would not need any new map layers. I could simply right-click on the tile in the mapview and set the properties there. Quick and simple. Going back to my prior (updated) comment, I am not using this to generate the actual map being used. I am using it to draw from a top down perspective the walls I need. As it is, I need a layer for walls on each of the compass points and then for the ground. That is already parsing 5 layers in my plugin. Not a big deal, but I would rather not have to require map editors to get super clever to handle this. The cell properties would simplify not only the plugin, but also the map creation.
Going for another example: Under the current setup, you would have to have 5 tiles defining small changes in stats all using the same artwork, or 5 object layers with the same differences in properties.
With cell level stats, (going with the tile properties from the tileset) you could define one tile with defaults, then set the properties at the cell level to adjust for custom settings.
Having written the plugin, I deal with the cell to get the tile I need. Could a properties object be added there and then the UI calls to enable them to be set? One more piece of code to copy tileset properties to the cell when placed?
I just looked at the object properties. That is really close to what I need. The only problem is it isn't tile based. it is floating point based and therefore not what I need. I need it based on the tile at a specific x,y... that leads me back to the cells. My prior comment on the 5 tiles can be handled with this object based properties. But the object layer is still assuming I am using the map as you see it in tiled and not the way I am. Think more of Bard's Tale. First person, turn based, cell based. Something that is not bound to x,y is not useful to what I am working on.
If you need your objects to align to tiles, then you can enable the 'Snap to Grid' option in the 'View' menu, and just divide your object coordinates by the tile size to get tile coordinates. You could do that already in your custom exporter (then there isn't even a need to do the division, since MapObject has position in tiles).
I ran a bunch of tests last night. The amount of effort to design a map using objects vs. tiles defeats the ability to put properties on an object. A map of 1000x1000 tiles will take a tremendous amount of time this way compared to painting tiles. Looking around the program, one thing I see is that every object is allowed properties; the tile layers, the map, the objects, the object layers, the tiles in the tilesets. The only thing that is not allowed to have properties is the individual cell in the layer.
The object layers deal with one object at a time when inserting. This slows down what can be down with them by quite a bit. The fact that you have to click to insert each object with the possibility of laying two objects on the same spot make it so it is not feasible to use this opposed to tiles. There are several features of the tile layers, that while they don't make sense in the object layers, I rely on them to keep map development fast and clean.
Having looked at the code a bit more after my testing last night, I can see some of the things that need to be done to add properties to the cells. Inherit from Object for the Cell definition. Maybe pull it out of tilelayer.h and put it in it's own class files. I see that you tie the right-mouse functionality to the tool being used so maybe a tiletool that does only properties, or a tiletool that is a select with a context menu for editing properties of the cell.
On Thu, Jul 7, 2011 at 14:34, biouxtai reply@reply.github.com wrote:
I ran a bunch of tests last night. The amount of effort to design a map using objects vs. tiles defeats the ability to put properties on an object. A map of 1000x1000 tiles will take a tremendous amount of time this way compared to painting tiles. Looking around the program, one thing I see is that every object is allowed properties; the tile layers, the map, the objects, the object layers, the tiles in the tilesets. The only thing that is not allowed to have properties is the individual cell in the layer.
Of course, you're not expected to replace your entire tile layer with an object layer. Rather, you'd use a tile layer for the bulk of your map, and then use an object layer for only those tiles on which you want to set properties. Usually these are just the doors, npcs, spawn areas, teleports, etc. and not every piece of floor.
The object layers deal with one object at a time when inserting. This slows down what can be down with them by quite a bit. The fact that you have to click to insert each object with the possibility of laying two objects on the same spot make it so it is not feasible to use this opposed to tiles. There are several features of the tile layers, that while they don't make sense in the object layers, I rely on them to keep map development fast and clean.
Having looked at the code a bit more after my testing last night, I can see some of the things that need to be done to add properties to the cells. Inherit from Object for the Cell definition. Maybe pull it out of tilelayer.h and put it in it's own class files. I see that you tie the right-mouse functionality to the tool being used so maybe a tiletool that does only properties, or a tiletool that is a select with a context menu for editing properties of the cell.
That does sound like the right approach. Also some change to the MapRenderers will be needed to be able to indicate which tiles have properties set on them, and the map reader/writer will need to store these properties in the TMX file in some way. If you have any questions feel free to ask. Personally I've always been reluctant to add this feature, since I think it's not very scalable. But when implemented in a nice way I'm not against accepting such a feature.
I ran a bunch of tests last night. The amount of effort to design a map using objects vs. tiles defeats the ability to put properties on an object. A map of 1000x1000 tiles will take a tremendous amount of time this way compared to painting tiles. Looking around the program, one thing I see is that every object is allowed properties; the tile layers, the map, the objects, the object layers, the tiles in the tilesets. The only thing that is not allowed to have properties is the individual cell in the layer.
Of course, you're not expected to replace your entire tile layer with an object layer. Rather, you'd use a tile layer for the bulk of your map, and then use an object layer for only those tiles on which you want to set properties. Usually these are just the doors, npcs, spawn areas, teleports, etc. and not every piece of floor.
This is where how I am using Tiled doesn't work with the object method. Every tile in my map will have properties. A lot of them are generic enough to be stored at the tileset layer, but many of them will have custom properties set on them. Up to 50% of the tiles will have custom properties. This is why the cell level makes more sense. it is more dynamic and granular than the tileset level.
As a side note: I built a 10x10 map as a test and it took me longer to make with objects for the walls as was needed for a 30x30 map with tile layers.
This is probably more a limitation on my part coding-wise, but if I were to use the object layers in a limited fashion to hold only those that need custom properties, I would have to build the map definition in an object in memory defined the way I need it defined before I could export. As it is now, the exporter is very fast because it can parse everything out per x,y based on the layers. Keeps it simple and all processing for that x,y is done when I finish that part of the loop. If I were to avoid building the map in memory I would need to search through all object layers and objects to find any that sit on that x,y. This would have to be repeated for every x,y and that would not scale well. The first method with an in memory object would require a vast amount of memory to be allocated depending on map size.
The object layers deal with one object at a time when inserting. This slows down what can be down with them by quite a bit. The fact that you have to click to insert each object with the possibility of laying two objects on the same spot make it so it is not feasible to use this opposed to tiles. There are several features of the tile layers, that while they don't make sense in the object layers, I rely on them to keep map development fast and clean.
Having looked at the code a bit more after my testing last night, I can see some of the things that need to be done to add properties to the cells. Inherit from Object for the Cell definition. Maybe pull it out of tilelayer.h and put it in it's own class files. I see that you tie the right-mouse functionality to the tool being used so maybe a tiletool that does only properties, or a tiletool that is a select with a context menu for editing properties of the cell.
That does sound like the right approach. Also some change to the MapRenderers will be needed to be able to indicate which tiles have properties set on them, and the map reader/writer will need to store these properties in the TMX file in some way. If you have any questions feel free to ask. Personally I've always been reluctant to add this feature, since I think it's not very scalable. But when implemented in a nice way I'm not against accepting such a feature.
My thoughts on this: A cell shouldn't have properties attached unless there is a tile in it. That will help limit overhead. When a tile gets placed, all default values of the properties can be copied from it's definition in the tileset to the cell. That way when the cell properties tool is used, it can pull up a list of predefined properties that can be edited or added to. Then, with the properties at all levels, however you wanted to handle things, either in an exporter or using a tmx loader, it would provide you with more options. An indicator for properties would definitely be nice. Maybe a box with a little p in the corner. Or better! let it be configurable but scale it to the tile size and limit how big it can be. Some users may already be using tiles that have a similar design, so letting the indicator be configurable would be more flexible. I am thinking that the storing and loading of the properties could be handled like the current properties. Since it is being stored at the cell level, it should be stored in the
I am curious about the scaling limitation. I am not sure I see how it wouldn't scale out. Much like the other properties aspects, if there are none, then there won't be any defined in the TMX file.
It's a feature that I see a need for (most prominently mine), so I will keep exploring and once I get to understand more of what I am doing with the code I will see about working on it. I appreciate the offer of help and any nudges in the right direction are always nice.
I wouldn't bother trying to only have properties on cells that are non-empty. Some people might want it, and actually I don't see any way to avoid overhead in that case. Deriving Cell from Object will make it larger by a single pointer, and I don't think you can do any better (QMap is already optimized for the empty case, in which case it implicitly shares the internal data structure with all other empty QMap instances).
What I wouldn't do is copy the tile properties into the cell. This is unnecessary duplication of information. If you want to show these properties when editing the properties of the cell, then this functionality could just be coded into the properties dialog without needing to copy things around.
Ok. So what I have so far...
You can click on the property tool, click a cell and the property dialog opens. add some, remove some.. whatever... The dialog behaves as expected. Now it is time to investigate storing them in the TMX file. Any preferences? I tend to lean to attributes over elements.. but I am not sure what you envision for the format. I would like to keep it in line with that. After storing is loading from TMX. Then I will explore pulling over defaults. I had thought that it might be simpler to copy the defaults over to the cell at the time you drop the tile on the map since I use properties on every tile. However, this should be designed with more than just my usage in mind. So keeping the defaults over in the tileset makes sense until you actually edit the properties of the cell. Then it can pull them over. A question I have is do I test in the property dialog or the property model? I am re-using the standard layer/map propertydialog class. So my question breaks down to where would I pull that data over? I would need to test the Object* to see if it matches Cell* so I can pull the Tile* and get to the default properties I am trying to bring over.
Ok. I have a lot of testing to do, but as it is now the feature is in the code. It works for saving in TMX, loading from TMX, setting the cell properties with the property tool. To get this done quickly without refactoring a lot of code, I am storing them as attributes to the tile in the TMX. I have blocked the loading of the gid attribute as that is internal for the actual tile being drawn. I have done some debugging that tests the features I need, but it is in no way fully tested.
Outstanding on this feature is an indicator to mark cells that have properties. Converting the properties to be child elements of tile like all others. Showing the tileset based properties when you open the dialog for the cell. ----possibly creating a new ui dialog that would let you move defaults from the tileset to the cell and adjust their value..? Testing..Testing..Testing.... I don't want to have introduced any instability to Tiled with these changes, so I will test them extensively for a couple weeks before calling them done. I want to see if any crashes occur during heavy use and see if they are related to anything I did.
Thanks for the info on where to get started.
Why not fork Tiled on github and push your changes there? They don't need to be final, but it would allow me to check out your changes and comment on them, if I have some time (I'm rather short on time, hence no promises).
One change I plan to make it to introduce a much more advanced property editor based on a Qt Solution. That one will make it possible to display the base properties of a tile, and mark in bold the ones you changed for a single cell. And then we can only save the changed ones, I'd say.
Still new to Github and git. So I will see how to do that and push them up later today or tomorrow. Comments are definitely welcome and probably needed. ;)
One change I made was to add calls to tile layer to also return a pointer vs just a reference. I was having difficulty getting the property dialog and a few other things to work dealing with the reference. It may just be inexperience on my part, but adding the pointer helped get it all working.
Sent from my iPad
On Jul 8, 2011, at 11:02 AM, bjornreply@reply.github.com wrote:
Why not fork Tiled on github and push your changes there? They don't need to be final, but it would allow me to check out your changes and comment on them, if I have some time (I'm rather short on time, hence no promises).
One change I plan to make it to introduce a much more advanced property editor based on a Qt Solution. That one will make it possible to display the base properties of a tile, and mark in bold the ones you changed for a single cell. And then we can only save the changed ones, I'd say.
Reply to this email directly or view it on GitHub: https://github.com/bjorn/tiled/issues/31#issuecomment-1533774
I've got it forked. https://github.com/biouxtai/tiled
Did you forget to push? ;)
push? bjorn has asked that I fork it so he can look over the changes. If you want me to push it up, I will have to look up how to do that, and I can do it today.
There is nothing for me to look at if you don't actually push your changes into that fork. :-)
I thought the commits I was doing did that. is there a command I need to run?
We're calling it 'push' because the command is 'git push'. :-)
But you may seriously want to consider reading some starters guide on git. This site even has some very nice ones specifically targeted at using github.com: http://help.github.com/
Well 'git commit' adds your changes to your local repository, so no bytes are leaving your computer into the internet ;) If you want to put your changes here at your fork at github, you will need to do 'git push' so you issue git to feed your changes upstream.
I found the graphics at this place quite useful for understanding git: http://whygitisbetterthanx.com/#everything-is-local
Thanks for the pointers. Definitely a newbie mistake. I am used to a couple other systems where a commit actually pushes to the remote repository because there is no local one. I didn't see the push command down past the commit in the help area when I first set this up.
Thanks. Push has been executed.
For what its worth, just thought I'd mention I have exactly the same need as biouxtai.
@ruuzo You may want to try out biouxtai's fork then and see if his work also solves your use-case.
I finally got a chance to compile and run biouxtai's fork (my 1st time trying to compile Tiled from source), its very close to what I need, the only part that is missing is that I'm using the lua exporter which it doesn't integrate with.
I am still trying to find some time to finish this fork. I need to update the base code so that it works for all native formats. I can look at the exporter, but I am not sure if it qualifies as a base module. I think it was developed for the mana team but I am not positive on that.
On Aug 12, 2011, at 4:32 PM, ruuzoreply@reply.github.com wrote:
I finally got a chance to compile and run biouxtai's fork (my 1st time trying to compile Tiled from source), its very close to what I need, the only part that is missing is that I'm using the lua exporter which it doesn't integrate with.
Reply to this email directly or view it on GitHub: https://github.com/bjorn/tiled/issues/31#issuecomment-1795311
Thank you biouxtai for your efforts!
The Lua export plugin was developed for the Moai SDK, but it's useful for any Lua-based game that uses tile-based maps and is meant to contain all the information normally saved in the TMX file.
How will per tile properties interact with compression? It's much nicer to work with when the data can be directly compressed and decompressed to a list of integers.
Once I get some more time, I will be making this compatible with all output formats supported by Tiled. Sometime this weekend I think.
Code has been pushed to the fork. For those that want to test, the url is https://github.com/biouxtai/tiled
Definitely needs testing with real data, but my canned tests I ran worked.
This (tiles - i.e. individual cells - in a layer actually inheriting default properties from the tileset and allowing edits) is exactly what I need, for all of the same reasons biouxtai mentioned. Were the forked changes ever integrated? I'm experimenting with v0.9.1 and if the functionality exists it's not intuitive. And I can't find a "property tool" as referenced in this statement above..."You can click on the property tool, click a cell and the property dialog opens".
@tpbradt I've found a nice explain here: http://www.raywenderlich.com/29460/collisions-and-collectables-how-to-make-a-tile-based-game-with-cocos2d-2-x-part-2
I know it's old, but tiled is useless on my usecase without this feature and I don't know where to upvote this feature. So here is my bump.
Tried @biouxtai fork, but it is unstable on my side (it crash a lot on osx). I will try to merge with the new codebase to check if it fix the issues.
Ported to the current version here: https://github.com/samueldr/tiled/tree/feature/cellproperties
Added lua export, still missing the others since we only use the lua one.
Also still missing a way to tell which cell have properties. I don't really need this feature, but I can see how it would be useful.
Just chiming in here saying that I really would love the functionality from the fork to land sometime.
@twistedjoe Would you be interested in opening a pull request for your changes? This feature is still requested occasionally and a pull request would make it easier for me to review the changes and provide feedback.
Sure! I think it would still need some "visual feedback", but it does the trick for us.
There you go. https://github.com/bjorn/tiled/pull/1139
We were working on a quite old version. So this might require some adjustment.
@twistedjoe Thanks!
Selecting individual tiles in a map, and being able to assign properties to them is essential. This is a ridiculously simple and basic feature that any tile editor should have. How is it sill not implemented, despite a multitude of people requesting it, explaining the very obvious use case, and re-iterating that using object layers is not a good option?
Snapping objects to tiles, with a human error possibility of creating multiple at the same spot, and then writing an exporter that estimates which tile the object position pixel value would correspond to, seems like an incredibly tedious and counterproductive thing. I honestly can't believe anyone can even reasonably suggest it as a solution.
Isn't it clear that this leads to tiles of the same type, such as floor tiles, to be split into two different layers of different kinds, one a tile layer and one an object layer? That is illogical and would lead to so many inconveniences.
I hope you can see, as any reasonable developer, that a feature that is consistently requested, re-opened in many re-formulations by many people over several years (and even at one point implemented in a fork that somehow you stubbornly chose not to merge), is a feature people want. Not because they misunderstand how to use the software, but because it is simply lacking from the toolset.
Learn to listen.
@kass-kass PR #1139 is the closest this ever came to being mergeable, please see my https://github.com/bjorn/tiled/pull/1139#issuecomment-159733386 on the matter there. For what it's worth, I agree that Tiled could use some way to associate data directly with cells.
Please respect that choosing what to work on next is driven by many factors. Every day I spend on Tiled I'm trying my best to improve this tool, and unlike with many other tools "on the market", you're free to join me in that effort.
This is an old thread but a lot of people seem to want this kind of property. It's possible with a little bit of creativity to solve it, and old games (old pokemon games, snes titles, and others) had clever solutions.
First, a use case. Suppose you have a map of a dungeon. You need to assign certain floor tiles to be pitfall traps; you need some walls to be destructible; you need some tiles to be light sources; and you'd like to make most tiles have a "encounter chance" between 0% and 100%.
Here's what you can do. First, for each property, create a new tile layer. You can save space by making properties share a layer if they're mutually exclusive; in our case, we can store pitfall traps (only on floor tiles) and destructible walls (only on wall tiles) in one layer. Then we have a light-sources layer, and we have an encounter-chance layer.
Next, make a new tileset. Make tiles with english words, letters, simple colors, or simple shapes - they're only visible to you, the level designer, so they can be whatever is easiest to draw. In our case, we're going to make a tile labeled "T" for trap, a tile labeled "D" for destructible, a tile labeled "L" for lightsource, and tiles labeled "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", and "100%".
Okay. Now back to Tiled. Create a new tileset file using the new image, then use the tile properties as needed. In this case, we'll assign the numbers 0.1, 0.2, 0.3, ... to the tiles named "10%", "20%", "30%", etc, using a custom property. That'll make working with these tiles in code a little bit nicer.
Go back to your map file. On the trap layer, place the new tile layers above the original dungeon layer. For each new layer, set the opacity to about 50%, and set the type field to something useful like "metadata".
On the trap layer, use the T tile wherever you want a pit trap, and a D tile wherever you want a destructible wall. Continue over to the light-source layer, and place an L tile wherever you want a light source. On the encounter-chance layer, use one of the probability tiles (10% - 100%) to assign probabilities throughout the dungeon.
Finally, in your game code, add an additional rule to never draw a layer if its type is "metadata".
This technique of metadata-tiles is very old - the oldest use I'm aware of is Pokemon Gold/Silver, where "cutscene" triggers are coded using invisible tiles, among other things.
That said, it does give a hint about how we could implement this directly in tiled.
We can setup a "virtual" tile-layer per property added to tiles. In the UI, it'll feel like selecting a tile and changing properties, particularly something like "painting" a property using existing tile placement tools. Indicating the presence of properties can be just a semi-opaque first-letter-of-property-name thing.
I think that it's very important to keep the feature-set of tile properties and the feature-set of object layers as separate as possible. Limiting it to enum-style data, for example, to simulate the above tileset technique. That would keep things very performant, because we're back to CSV and binary data, rather than arbitrary property maps.
@bjorn just to add to this discussion: I recently encountered an issue where I wanted to place a chest tile, and it would be nice to customize the contents of the chest using a text/json.
I have been told by eishiya that I should use a object. The problem is that is bad for a couple of different reasons: The position may be off by a bit so may round down to the wrong position. You may say turn snapping on but then you are 'emulating' the grid by doing so, which is philosophically wrong. Also when you save as an object, its in a separate part of the saved datastructure that is processed differently than tiles on most game logic code. For example I might have a switch satement for rendering tiles, and there may be another switch statement for rendering enemies that are objects. The problem is that you will have chest in amongst the enemies, which doesnt make sense really. On my game client a chest IS a tile, just like a dirt block, so I need to handle it in the same axiomatic conceptual grouping as the dirt tile.
It would be better to have another dictionary from grid positon => text/json content, that would show up if there is at least one object with tile metadata/properties.
@AJLProjects That is exactly the use case for objects. Which would you rather 1) have an entire separate parser specification, custom parsing code, that is fixed in place, or 2) call round()
on the x and y coordinates, with the flexibility to move it to a different location if your level layout changes?
if you really want to have the tile as a chest, you can add a spriteless object on top with the data.
If this feels messy, welcome to game development. Every map and video game is cobbled together with shortcuts and almost-aligned things.
@Phlosioneer NO. Objects are for free floating objects like moving entities e.g. mobs. If it needs to conform to the grid and is a grid tile, then it should remain as a tile. Stop the mental gymnastics, thinking in terms of what already exists.
Snapping to the grid exists to make it easy to make grid-conforming Objects. This sort of thing is part of their purpose, and things like treasure chests and warp zones are among the purposes they're intended to serve. They can also be used for moving entities, but that's not their sole purpose.
This issue covers a different kind of scenario, the kind that currently requires a lot of Objects or a lot of extra tile layers to pull off, situations where most cells need some bespoke data associated with them. For sparsely placed dynamic objects like collectibles and chests (they don't move, but they change since they can be picked up), Objects are the intended way, and not a "hacky workaround" as you described it in your other issue. This is the way most games/engines handle things like chests as well - as the in-engine equivalent of an object, even if the coordinates in that engine are always whole tiles. Using a data layer (which seems the likely outcome of this issue, if it's implemented) would be overkill for treasure chests and other such collectibles, unless half your map is covered in treasure chests xP
A chest is not a grid conforming object, it IS a tile (In my game). What if you had a door tile which has a boolean open closed state, would you also say that is a object, and not a tile?
In minecraft a chest still takes up a voxel and isnt processed like an entity. Instead its a tile with metadata. ( What I'm saying is that it depends on what best fits the usecase, so you can't be presumptuously prescriptive)
Also objects come in as a floating point, so what if there is a rounding error...
I would like to see a feature for having properties based on a cell in a layer rather than base it on the tileset. Tileset is too global. If I have a small sample of tiles in a map that need one specific property (object area is not feasible) then creating a new tileset to handle this doesn't make sense. Especially if there are several permutations of the property needed with the same tile. Custom properties on the cell in the layer would be much better.