mapeditor / tiled

Flexible level editor
https://www.mapeditor.org/
Other
11.06k stars 1.75k forks source link

Idea for a new tool: creating complex object shapes without the use of polygons. #1899

Open pouwelsjochem opened 6 years ago

pouwelsjochem commented 6 years ago

Current situation The polygon tool is now used to draw enclosed shapes in any form, but I guess we can improve the usability in cases where the shape actually consists of multiple 'single tile sized' objects connected to each other.

For example in the use case below, it can be drawn with the polygon tool, but because it has holes it requires to have some intersecting & diagonal lines. The output is also relatively hard to parse if you would like to know which tiles indices do actually have the defined object.

"polygon":[ { "x":0, "y":0 }, { "x":96, "y":0 }, { "x":96, "y":48 }, { "x":128, "y":48 }, { "x":128, "y":96 }, { "x":80, "y":96 }, { "x":80, "y":80 }, { "x":80, "y":64 }, { "x":64, "y":64 }, { "x":64, "y":80 }, { "x":80, "y":80 }, { "x":80, "y":112 }, { "x":32, "y":112 }, { "x":32, "y":96 }, { "x":0, "y":96 }, { "x":48, "y":48 }, { "x":64, "y":48 }, { "x":64, "y":16 }, { "x":48, "y":16 }, { "x":48, "y":48 }, { "x":0, "y":96 }],

screen shot 2018-03-03 at 12 30 15

Suggestion What I would like to suggest is to create a tool which is limited to just the tile grid (as defined in the map). This tool would allow you to create an tile-sized objects, which can extend by drawing additional tile-sized objects on any border.

I can imagine the output format in one of the following two different options (taking the screenshot above as example):

Option 1: An array of 'booleans' where every boolean tells you if the tile is used or not. The length of this array would always be the width * height in tiles. Our example object has a (calculated) width of 8 and a calculated height of 7 and would result in the following output: tiles = [ 1,1,1,1,1,1,0,0, 1,1,1,0,1,1,0,0, 1,1,1,0,1,1,0,0, 1,1,1,1,1,1,1,1, 1,1,1,1,0,1,1,1, 1,1,1,1,1,1,1,1, 0,0,1,1,1,0,0,0 ]

Option 2: An array of tile locations. Every location would be the delta tiles relative to the objects position. For example the following output would be the one for just the first row of tiles of the example object: tiles = {{"x":0, "y":0}, {"x":1, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}}

bjorn commented 6 years ago

Do you really need this area to be an object? If you want to mark some area with a special property and it is really tile-based like in your example, the easiest approach is generally to paint this area on a tile layer using a special tile.

pouwelsjochem commented 6 years ago

In my case I would indeed require this area to be an object, there are several properties I need to be able to set on this object. Every grass patch is different and is in fact one object/entity in my game.

I think it could be a common use case that objects have non square shapes (which is probably why the polygon tool is introduced). I guess most people 'hack' this in their game by just using multiple objects with the same properties (causes difficulties using it as a single entity in-game), or by using the polygon tool.

bjorn commented 6 years ago

Alright, I think it would make sense to add a kind of "tile region" object for this purpose. However, I don't see this becoming a priority solely based on general demand. Are you interested in adding this feature to Tiled yourself or to sponsor it as a patron?

pouwelsjochem commented 6 years ago

I can understand this not being a priority at the moment.

Since the tile region can be extracted from the polygon data it is also not one of my priorities at the moment. It is just that this tool could make it a little less messy. Sadly I won't be able to add it to Tiled myself (lack of Qt knowledge).

Perhaps this issue will notify someone about the possibilities and they prioritise it enough to support adding it to a later version of Tiled.

Ps. if someone is interested in how to extract the tiles from polygon data, below you can find a code snippet (Lua) which will verify if an x/y position is within the polygon data. You'll just have to find the minX, minY, maxX, maxY of the polygon data to extract the amount of tiles in width/height. Then for each tile you can use this function to verify if the tile is used or not.

local function insidePolygon(_polygonObjects, _x, _y)
    local oddNodes = false
    local j = #_polygonObjects
    for i = 1, #_polygonObjects do
        if _polygonObjects[i].y < _y and _polygonObjects[j].y >= _y or _polygonObjects[j].y < _y and _polygonObjects[i].y >= _y then
            if _polygonObjects[i].x + (_y - _polygonObjects[i].y) / (_polygonObjects[j].y - _polygonObjects[i].y) * (_polygonObjects[j].x - _polygonObjects[i].x) < _x then
                oddNodes = not oddNodes
            end
        end
        j = i
    end
    return oddNodes
end
pouwelsjochem commented 6 years ago

Instead of the referred "tile region" object, an other solution would be to be able to link objects together, as in they sync with each others properties, layer, location and name.

Sadly I still can't implement this myself, but just putting ideas out here in the case anyone ever wants to develop such feature in Tiled.

pouwelsjochem commented 6 years ago

Perhaps it can be considered when implementing #707, which is on the roadmap.