无法弄清楚等距游戏获得世界坐标函数的逆

时间:2009-08-19 19:19:26

标签: isometric

我正在写一个等距游戏,但遗憾的是我已经陷入困境,用于从屏幕坐标映射回世界坐标的算法(或者可能反之亦然)。无论如何,我无法弄清楚与我的GetScreenX / Y方法相反的实现。这是一些代码。 width和height表示tile中视口区域的宽度/高度。

如果执行得当,这应该没有任何问题。你可以在Linqpad中运行它。

void Main()
{
    for(int width = 1;width<15;width++)
    {   
        for(int height = 1;height<10;height++)
        {
            for(int x = -50;x<50;x++){          
                for(int y = -50;y<50;y++){
                    var screenX = GetScreenX(x, y, width, height);
                    var screenY = GetScreenY(x, y, width, height);
                    var worldX = GetWorldX(screenX, screenY, width, height);
                    var worldY = GetWorldY(screenX, screenY, width, height);
                    if (worldX != x || worldY != y)
                    {
                        throw new Exception("Algorithm not right!");    
                    }
                }   
            }
        }
    }
}

protected int GetScreenX(int x, int y, int width, int height)
{
    return WrappingMod(x + y, width);
}

protected int GetWorldX(int x, int y, int width, int height)
{
    return 1; //needs correct implementation
}

protected int GetWorldY(int x, int y, int width, int height)
{
    return 1; //needs correct implementation
}

protected int GetScreenY(int x, int y, int width, int height)
{
    return WrappingMod((int) ((y - x)/2.0), height);
}

static int WrappingMod(int x, int m)
{
    return (x % m + m) % m;
}

很抱歉不得不问,但我的智慧结束了!

2 个答案:

答案 0 :(得分:0)

我不明白你的WrappingMod功能。你似乎计算了屏幕坐标,然后把它模数视口尺寸(两次)只是为了它的地狱。这使得你的world-&gt;屏幕映射非双射,因此它没有反转。

为什么你要在彼此之上绘制几块瓷砖?

当世界坐标不适合视口时,您应该想要引发异常,而不是取模数。

答案 1 :(得分:0)

你需要两个矩阵:一个用于从视图转换为世界坐标,另一个用于转换为另一种方式。

// my matrices are in 4x4 column-major format

// projection matrix (world -> view)
this.viewTransform.identity()
    .translate(this.viewOrigin)
.scale(1, 0.5, 1)
.rotate(this.viewRotation, 2); // 2 = Z axis

var m = this.viewTransform.current().m;
this.context.setTransform(m[0], m[1], m[4], m[5], m[12], m[13]);

// construct inverse projection matrix (view -> world)
this.viewTransformInv.identity()
    .rotate(-this.viewRotation, 2)
    .scale(1, 2, 0)
    .translate(new Vect4(-this.viewOrigin.x, -this.viewOrigin.y));

// calculate world and map coordinates under mouse
this.viewTransformInv.project(this.mousePos, this.worldPos);

// convert coordinates from view (x, y) to world (x, y, z)
this.worldPos.z = this.worldPos.y;
this.worldPos.y = 0;
this.mapPos[0] = Math.floor(this.worldPos.x / this.TileSideLength);
this.mapPos[1] = Math.floor(this.worldPos.z / this.TileSideLength);