【问题标题】:Can't figure out inverse of get world coords function for isometric game无法计算等距游戏的获取世界坐标函数的逆
【发布时间】:2009-08-19 19:19:26
【问题描述】:

我正在编写一个等距游戏,但不幸的是,我在编写用于从屏幕坐标映射回世界坐标的算法时遇到了困难(反之亦然)。无论如何,我无法弄清楚与我的 GetScreenX/Y 方法相反的实现。这是一些代码。 width 和 height 表示以图块为单位的视口区域的宽度/高度。

有了正确的实现,这应该可以顺利进行。您可以在 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;
}

很抱歉不得不问,但我无能为力!

【问题讨论】:

    标签: isometric


    【解决方案1】:

    我不明白你的 WrappingMod 函数。你似乎计算了屏幕坐标,然后取模视口尺寸(两次)只是为了它的地狱。这使您的世界->屏幕映射非双射,因此它没有逆。

    你为什么一开始要在彼此的顶部绘制几块瓷砖?

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

    【讨论】:

    • 嗯。我承认,这看起来有点古怪。 Actaully 我正在做的是制作一个客户端服务器应用程序。客户端将视口边界发送到服务器,然后服务器尝试确定哪些图块对客户端可见(使用需要实现的方法),并将这些图块的数据发送回客户端。然后客户端使用 GetScreen 方法在屏幕上定位图块。
    • 它进行包装模型的原因是将它们带回屏幕上的位置,因此当 y = 0 和宽度 = 8 时,x 位置 -12、-4、4、8、12 等. 全部设置到位置 4
    • 您需要向服务器提供一个参数,了解哪些图块位于视口中。最终解决方案取决于您如何处理视口移动,看起来您当前的解决方案是“跳到下一组”。在这种情况下,您只需 GetWorldX(int x, int y, int offsetX) {return x/2+y+offsetX;}
    【解决方案2】:

    您需要两个矩阵:一个用于从视图转换为世界坐标,另一个用于转换它的逆矩阵。

    // 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-26
      • 1970-01-01
      • 1970-01-01
      • 2014-12-22
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多