无法计算出等距游戏的获取世界坐标函数的反函数

发布于 2024-08-02 12:20:51 字数 1489 浏览 3 评论 0原文

我正在编写一个等距游戏,但不幸的是,我一直在使用用于从屏幕坐标映射回世界坐标的算法进行编写(或者反之亦然)。无论如何,我无法弄清楚与 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;
}

很抱歉不得不问,但我已经无计可施了!

I'm writing an isometric game, but unfortunately I've got stuck writing with the algorithm used to map back to world coordinates from screen coordinates (or possibly vice versa). Anyway I can't figure out the implementations which are the inverse of my GetScreenX/Y methods. Here's some code. width and height represent the width/height of the viewport area in tiles.

With the correct implementation, this should run through without any trouble. You can run it in 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;
}

Sorry to have to ask but I'm at my wits end!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光病人 2024-08-09 12:20:51

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

为什么一开始要在彼此之上绘制几块图块?

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

I don't understand your WrappingMod function. You seem to calculate the screen coordinate, and then take it modulo viewport dimension (twice) just for the hell of it. That makes your world->screen mapping non-bijective, so it has no inverse.

Why are you drawing several tiles ontop of each other to begin with?

Instead of taking the modulus, you should be wanting to raise an exception when the world coordinate doesn't fit in the viewport.

糖果控 2024-08-09 12:20:51

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

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

You need two matrices: one to convert from view to world coordinates, and its inverse to convert the other way.

// 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文