A
A
Alexander2015-11-28 16:31:34
JavaScript
Alexander, 2015-11-28 16:31:34

How to calculate the drawing position of a tile on an isometric grid?

There is an isometric grid, you need to place objects on the grid. The peculiarity of the grid is that each of its cells has subcells:

property int mapWidth: 6 // количество клеток по горизонтали
property int mapHeight: 6 // количество клеток по вертикали
property int cellSize: 128 // размер клетки
property int cellDivider: 2 // делитель клетки (каждая клетка имеет 4 подклетки)
// property int cellDivider: 3 // каждая клетка имеет 9 подклеток

55c579aeacc74757bf99f50d5d303c3c.png
A standard tile must occupy exactly one cell (cell), it is described as follows:
{ 
    "row": 4, // строка
    "col": 2, // колонка
    "wsize": 2, // занимаемая ширина в "подклетках"
    "hsize": 2, // занимаемая высота в "подклетках"
    "wpos": 1, // позиция в строке "подклетки"
    "hpos": 1, // позиция в колонке "подклетки"
    "source": "/tiles/tree1.png", // путь к изображению
    "width": 300, // оригинальный размер изображения
    "height": 200,
}

To place such a tile on the map, I derived the following creepy formulas:
property int tileWidth: 128 // ширина стандартного тайла
property int tileHeight: tileWidth/2 // высота стандартного тайла

function createTile(tileInfo) {
    // тут нормализуется размер тайла
    var tile_w = tileWidth * tileInfo.wsize / cellDivider
    var tile_h = tileWidth/tileInfo.width * tileInfo.height * tileInfo.hsize / cellDivider
    // tileWidth/tileInfo.width => ratio

    var tile_x = (map.width/2 + tileInfo.col*tileWidth/2 - tileInfo.row*tileWidth/2 - tileWidth/2)
    var tile_y = (tileInfo.row*tileHeight/2 + tileInfo.col*tileHeight/2) - tile_h + tileHeight/2
    /* ... */
}

where:
  • map.width - full map width: map.width = mapWidth * cellSize (6 * 128)
  • tileInfo - information about the tile
  • - tile_h + tileHeight/2 - here the height of the resulting image is subtracted to mark the image in the center of the cell

Well, it seems to have turned out and drawn:
52286b12bcee475ea52aef80bce60175.png
But now you need to draw a small "tile" in the floor of the cage:
{ 
    "row": 4,  // строка
    "col": 2, // колонка
    "wsize": 1, // занимаемая ширина в "подклетках"
    "hsize": 1, // занимаемая высота в "подклетках" 
    "wpos": 1, // позиция в строке "подклетки"
    "hpos": 1, // позиция в колонке "подклетки"
    "source": "/tiles/smalltile.png", 
    "width": 300, 
    "height": 200,
}

and this is where it was drawn:
2720d679dcfb42739b51bc45ace0a567.png
The big blue cell is like a representation of the coordinates of the "subcells" The
small blue cell under the tree is the "subcell" where the tile was supposed to be located, but the presented formula does not process the wpos and xpos parameters , because I couldn't fit them in correctly :-) no matter what I tried to do, tiles of different sizes started jumping in different directions relative to the main cell.
Actually, the question itself is: how to correctly draw up a formula according to the initial data?
And another passing question: how much is this approach right / wrong? Is there an easier/better method?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Alexander, 2015-11-28
@wxmaper

In general, this is what happened:

property var mapObjects: [
        { "row": 4, "col": 2, "wsize": 1, "hsize": 1, "wpos": 0, "hpos": 0,
            "source": "qrc:/tiles/002-000-00.png", "width": 500, "height": 373 },
        { "row": 4, "col": 2, "wsize": 2, "hsize": 2, "wpos": 1, "hpos": 1,
            "source": "qrc:/tiles/001-001-00.png", "width": 2079, "height": 3249 }, // tree
        { "row": 4, "col": 3, "wsize": 2, "hsize": 2, "wpos": 1, "hpos": 1,
            "source": "qrc:/tiles/001-002-00.png", "width": 1100, "height": 823 }, // tree
        { "row": 4, "col": 2, "wsize": 1, "hsize": 1, "wpos": 1, "hpos": 1,
            "source": "qrc:/tiles/002-000-00.png", "width": 500, "height": 373 }, 
        { "row": 4, "col": 3, "wsize": 1, "hsize": 1, "wpos": 1, "hpos": 0,
            "source": "qrc:/tiles/002-000-00.png", "width": 500, "height": 373 },
        { "row": 4, "col": 3, "wsize": 1, "hsize": 1, "wpos": 1, "hpos": 1,
            "source": "qrc:/tiles/002-000-00.png", "width": 500, "height": 373 },
    ]

function createMapObjects() {
    mapObjects.map(function(tileInfo) {
        // нормализация размера создаваемого тайла
        var tile_w = tileWidth * tileInfo.wsize / cellDivider
        var tile_h = tileWidth/tileInfo.width * tileInfo.height * tileInfo.hsize / cellDivider

        // левая верхняя координата описывающего клетку прямоугольника
        var tile_sx = (map.width/2 + tileInfo.col*tileWidth/2 - tileInfo.row*tileWidth/2 - tileWidth/2)
        var tile_sy = (tileInfo.row*tileHeight/2 + tileInfo.col*tileHeight/2) - tile_h

        // координата создаваемого тайла
        var tile_x = tile_sx + tileWidth/cellDivider * tileInfo.wsize/cellDivider
                + (tileWidth/cellDivider * tileInfo.wsize/cellDivider * tileInfo.wpos) * (cellDivider - tileInfo.wsize)
                - (tileHeight/cellDivider * tileInfo.hsize * tileInfo.hpos)

        var tile_y = tile_sy + tileHeight/cellDivider * tileInfo.hsize/cellDivider
                + (tileHeight/cellDivider * tileInfo.hsize/cellDivider * tileInfo.hpos) * (cellDivider - tileInfo.hsize)
                + (tileHeight/cellDivider * tileInfo.wsize/cellDivider * tileInfo.wpos) * (cellDivider - tileInfo.wsize)
    })
}

The formulas are wild and, as it turned out, are only suitable for cellDivider = 2 ;-(
I'm sure you can make it simpler and more correct :D
2cff51d94cac4f358074b1df04ea80ed.png

A
Alexander Taratin, 2015-11-28
@Taraflex

Some approaches are described
here habrahabr.ru/post/269653

X
xmoonlight, 2015-11-28
@xmoonlight

Use all calculations on a grid with a cell of the same size - "pixel".
When forming random thickets - use a group of pixels = "brush" size.
Filling with such a brush is prescribed in advance: the percentage of small tiles.
When applied - the brush REPLACES everything that is in its field.
Watch the Age of Empires II map editor for an example: https://www.youtube.com/watch?v=TX4bg98uYZ8

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question