我正在写一个等距游戏,但遗憾的是我已经陷入困境,用于从屏幕坐标映射回世界坐标的算法(或者可能反之亦然)。无论如何,我无法弄清楚与我的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;
}
很抱歉不得不问,但我的智慧结束了!
答案 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);