Tomoso
Tomoso

Reputation: 105

How can I determine the size of an Isometric map of any size?

I have managed to load and display an isometric map using SpriteKit and Swift by writing my own .TMX parser. Orthogonal maps work fine, but this is my first time using Isometric maps and the math is confusing me.

My tiles are 64x32, and the map can be any size.

Ideally I would like the left most edge of the map (the tile at [0, maxRow]) to be sitting at zero on the x-axis, and the bottom most edge of the may (the tile at [maxCol, maxRow]) to be sitting on the 0 y-axis.

The origin of the map is the tile at the top. X goes from Top to Right, Y goes from Top to Left.

SpriteKit also has a reversed y-axis. The code below is how i am positioning tiles based on their coords, and retrieving them using a position on screen. This code works fine.

So to offset the position correcting so I can place the map where I want I need to be able to find the width and height of an isometric map of any size and I have no idea where to start.

  func positionForCoord(col: Int, _ row: Int) -> (x: CGFloat, y: CGFloat) {

    var x: CGFloat = 0
    var y: CGFloat = 0

    x = (CGFloat(col - row) * CGFloat(tileSize.width)) / 2
    y = (CGFloat(col + row) * -CGFloat(tileSize.height)) / 2

    return (x, y)
}

  func coordForPosition(x: CGFloat,_ y: CGFloat) -> (col: Int, row: Int) {

    var col: Int = 0
    var row: Int = 0

    let tileWidthHalved = CGFloat(tileSize.width) / 2
    let tileHeightHalved = CGFloat(tileSize.height) / 2

    col = Int(floor(((x / tileWidthHalved) - ((y - tileHeightHalved) / tileHeightHalved)) / 2))
    row = Int(ceil(((((y - tileHeightHalved) / -tileHeightHalved) - (x / tileWidthHalved)) / 2)))


    return (col, row)
}

Upvotes: 0

Views: 452

Answers (1)

Thorbjørn Lindeijer
Thorbjørn Lindeijer

Reputation: 2112

Since you tagged this with Tiled, one way to start is by looking at Tiled's source code to see how it calculates it. It's really only this small bit of code in isometricrenderer.cpp:

QSize IsometricRenderer::mapSize() const
{
    // Map width and height contribute equally in both directions
    const int side = map()->height() + map()->width();
    return QSize(side * map()->tileWidth() / 2,
                 side * map()->tileHeight() / 2);
}

To understand it I usually draw a small piece of isometric map on paper and look at how its bounds are derived from its tile size. You would see that for each additional tile row, the map bounds grow by the same amount as for each additional tile column. And the amount is exactly half the tile size.

Upvotes: 0

Related Questions