Scale property for objects in object layer

Hey there! We’re working on our own game engine and are currently using Tiled to design our levels. Our game engine cares about the scale (scaleX / scaleY) of objects in object layers, but by default Tiled exports a width and height only. Parts of our game engine would prefer to only know the scale of an object instead of width/height. Given how many game engines use scale / rotation for objects, I reckon it’s quite a common use case to want scale factors in your export.

Is there an easy way to get these properties from Tiled or will we have to build a convertor script to calculate the scale values and create a new level export our game engine can use?

Right now, scale would need to be derived by dividing the size of the object by the size of its tile.

Of course, if you’re implementing a custom export format, the exporter could calculate the scale, which the GameMaker exporter is doing for example:

If you’re relying on the default TMX or JSON formats, you could also write a scripted extension, that assigns custom “scaleX” and “scaleY” properties to tile objects in response to the assetAboutToBeSaved signal, for example.

I’ve not sure how much value is added by simply adding scalex and scaley attributes to the TMX format, which are derived from object size and tile size as above. It might be nice to eventually support scaling in addition to the object size. There is still the following issue open about that:

Thank you for the lightning fast response! I’m not familiar with building plugins or extensions for Tiled, but I’ll have a quick look. It might be faster to code a data converter on our end if that takes too much to learn. I can’t speak for others, but I personally see great value in an easy way to add these properties to objects.

Thanks again for the help!

1 Like

I think adding distinct scale properties would only make sense if Tile Objects can display tiles in some way other than stretching them to fit their size, e.g. if they have a “repeat tile” mode. Otherwise, scale will always just be objectSize/tileSize and redundant.

I think the implication in this request is that Tile Objects should have the same size as their tile and use the Scale property to resize, instead of changing the object size. I think this is just an unnecessary complication that would make Tile Objects inconsistent with other Objects, and it’s redundant since the tile’s size is known from the tileset anyway. It could make sense if all objects could have a size and scale, but I think this would just make for more annoying UI, and isn’t usually needed for anything but Tile Objects, where, as mentioned, the scale can be calculated at save time or at map load time.

Our goal is to keep the level files as small as possible. When we have 1000 barrel objects in our map at various sizes, it’s more efficient to store their scale rather than their width and height. To that end, we want the actual exported level files to only contain a scale property for each object with a scale not equal to 1. (Similarly for scaleX and scaleY if those happen to be different.) So the calculation cannot be done at runtime.

We’ve got a data converter to turn Tiled’s JSON exports into a JSON format that serves the needs of our engine, but it parses tileset and tilemap files separately. To add the scale to each object in a tilemap, we’ll now also need to input the data of its tilesets to get the information of the base sizes of each object, so we can then calculate the scale of each object. So for our needs it’s far from redundant and would be a very welcome feature to be able to export the scale via Tiled. Would save us some hours of tinkering. :slight_smile: But we’ll just go ahead and extend our converter. That seems to be the way to go.

In what way would storing the scale help? It’s still two variables, probably the same bit size (two 32-bit ints, vs probably two 32-bit or 64-bit floats).

The data is still redundant, since it can be calculated from properties that are already stored xP Saving some look-ups is convenient, but it’s not novel data.

Compare
{ w: 10.5, h: 13.5 }
to
{ s: 1.5 }

The latter is more compact, which does matter in data files with thousands of such objects. Also, JSON is stored as text, not as ints or floats. We could easily do the calculations in real-time. Performance is not the issue. This is about storage of level data, where this does save us hundreds of kilobytes that are being sent to thousands of clients. And our engine needs the scale, not the calculated width and height.

But let’s stay on-topic and not start discussing the per-project merits of such output. We’ll derail the topic. :wink:

It would be {sx: 1.5, sy: 1.5} though - scaling/sizing can be done independently on each axis in Tiled. So, in most cases you’d probably be saving 1-2 digits per axis - if your scales are tidy; if they’re not, you’ll probably be adding more digits, e.g. 1.20284000000001 instead of some 2-digit pixel size.

And size would almost certainly still be stored (for backwards compatibility, for consistency with other objects), so scale would only add more bytes to your files even in the tidiest case.

It would be {sx: 1.5, sy: 1.5} though - scaling/sizing can be done independently on each axis in Tiled. So, in most cases you’d probably be saving 1-2 digits per axis - if your scales are tidy; if they’re not, you’ll probably be adding more digits, e.g. 1.20284000000001 instead of some 2-digit pixel size.

Our objects (things like barrels, enemies, etc) in 99% of the cases get scaled normally without any stretching. In all the games we’ve produced, stretched enemies and map objects have only been a rare exception to the rule.

And size would almost certainly still be stored (for backwards compatibility, for consistency with other objects), so scale would only add more bytes to your files even in the tidiest case.

We don’t store width and height of objects in our level files. Only scale. The whole goal is to not store redundant data which increases the amount of data sent to clients.

Sounds like we’re just back at the start then: you’re better off implementing this in a custom format that only stores what you need (which you already do anyway!), instead of handling the general case like Tiled does. And that means you can just calculate the scale during saving/conversion from the tile size and object size, instead of requiring Tiled to store it in the TMX/TMJ. It doesn’t make sense for Tiled to store this entirely redundant data just so that you don’t have to calculate it. Even if Tiled had a scale feature that let you input exact scale numbers (which might be a nice convenience feature for when snapping is inadequate), it would probably still output the size in the TMX/TMJ.

By the way, to simplify your custom JSON conversion and avoid “hours of tinkering” every time you want to support a new feature, it might be worth the time to make this JSON into a Tiled map export format, instead of a separate tool. If the existing tool is JavaScript, it’s quite likely that a lot of the code can be copy+pasted, and you’d only need to change where the initial data comes from.
That way you’ll have access to all the map’s data, including its tileset, via Tiled’s API and don’t have to parse any files, avoiding reliance on formats that may change in the future (there are some non-compatible changes planned for JSON/TMJ in particular). I realise that this is also potentially “hours of tinkering” just to start with this, but this probably should’ve been the solution from the start xP Tiled has a lot of built-in functionality and access to data that makes writing map formats easier than converting a map JSON - there are convenience methods for converting from pixel to tile coordinates and vice versa, quick access to tilesets and tile properties, easy access to resolved/inherited properties that aren’t written out to TMX/TMJ files, etc. Tiled can also automatically export every time you save the map.