在LibGDX(Java)中更改坐标系

59

LibGDX使用的坐标系将(0,0)设为左下角。(类似于这张图片: http://i.stack.imgur.com/jVrJ0.png)

这让我感到十分头疼,主要是因为我正在移植一个已经使用了通常坐标系(其中0,0位于左上角)的游戏。

我的问题是: 是否有简单的方法可以更改这个坐标系?


当然,这就是我现在正在做的事情。但是有没有办法翻转坐标系呢?比如创建一个投影矩阵,使用我想要的坐标系。或者告诉Spritebatch根据特定的坐标系进行绘制...我已经疯狂地寻找了,但似乎找不到特别的东西...(如果有的话,实际代码是什么) - Sosavpm
2
这确实是一场噩梦。像SpriteBatch和sprites这样的东西从左下角开始。而像input和textureregion这样的东西则从左上角开始。导致编码非常尴尬,你需要经常在脑海中反复转换,以至于你的眼睛都要瞪出来了。无论如何,我建议你要习惯它,因为旋转相机会导致图像翻转,然后你需要将所有东西翻转回来,但不是所有东西,只有大部分东西,并让它们按预期方式绘制。LibGDX很棒,但坐标系统存在严重问题。最好要习惯它。 - Madmenyo
6个回答

127

如果你使用相机(你应该这样做),改变坐标系是相当简单的:

camera= new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
如果你使用TextureRegions和/或TextureAtlas,除此之外,你还需要调用region.flip(false,true)。
我们默认使用y-up的原因(如上所示,您可以轻松更改)是:
- 您的模拟代码很可能使用具有y-up的标准欧几里德坐标系。 - 如果您使用3D,则具有y-up。 - 在OpenGL中,默认坐标系统是右手坐标系,具有y-up。当然,您可以使用一些矩阵魔法轻松更改它。 libgdx中仅有两个使用y-down的地方:
- Pixmap坐标(顶部左侧原点,y-down) - 触摸事件坐标,给出的是窗口坐标(顶部左侧原点,y-down)
同样,您可以使用相机或一小部分矩阵数学轻松更改所使用的坐标系统。

19
来自创造者本身的答案。谢谢,非常有用! - Sosavpm
3
@badlogic提到应该使用相机,但如果我只使用SpriteBatch.draw方法并自己处理世界滚动和视锥剔除,会有哪些缺点?我正在开发一款俯视视角的策略游戏。 - Pasman
2
我认为它被开发成这样是有一些原因的,但是如果你根本没有使用任何相机,只是使用SpriteBatch.draw()来绘制纹理/像素图/字体等,那该怎么办呢?我有Pasman的确切问题。 - user796820
3
@Pasman,你可以使用batch.getProjectionMatrix().setToOrtho2D()。该方法可用于将投影矩阵设置为正交投影。 - NateS
3
一切都颠倒了!我可以翻转区域但无法改变质感。 - Ali
显示剩余4条评论

9

稍微解释一下badlogic上面说的,如果你正在使用TextureAtlas(带有TextureRegions),除了相机工作外,你还需要像badlogic所说的那样翻转它们。如果你正在使用TextureAtlas,你可以在加载atlas后立即使用以下代码:

String textureFile = "data/textures.txt";  
atlas = new TextureAtlas(Gdx.files.internal(textureFile), Gdx.files.internal("data"));  
// Let's flip all the regions.  Required for y=0 is TOP
Array<AtlasRegion> tr = atlas.getRegions();      
for (int i = 0; i < tr.size; i++) {
  TextureRegion t = tr.get(i);
  t.flip(false, true);
}

1
我该如何翻转普通的“Texture”?在我的游戏中,它们现在是倒着绘制的。 - MaxGyver

6
如果您想隐藏转换并在设置一次后不再考虑它,可以创建一个类,该类继承您所需的所有功能,但首先在传递给其父类函数之前对坐标进行转换。不幸的是,这需要很长时间。
或者,您可以创建一个方法,在每次操作之前对整个“Coordinate”对象(或您正在使用的任何内容)执行简单的“y' = height - y”转换。

嗯,这不完全是我想要的。但我做了这个,它很好地工作了,而且编码量也不多。(此外,我继续寻找,我认为没有其他方法)谢谢! - Sosavpm
不确定您的意思,但我认为一个“上帝”类来完成所有这些并不是一个很好的想法,所以我正在尝试扩展我需要的所有类,并根据需要覆盖方法。这也不是一个很好的解决方案。 - User
嗯,其实我想尝试使用那个OrthographicCamera类的解决方法,看看效果如何。 - User

5
有趣的图形库,我想说。我从下面的链接中找到了这个评估:
另一个问题是Libgdx在不同的部分使用了不同的坐标系。有时,坐标轴的原点位于左下角,y轴向上,有时位于精灵的左上角,指向下。当绘制网格时,原点甚至位于屏幕中心。这导致了相当多的困惑和额外的工作,以正确地将所有内容放置在屏幕上。

http://www.csc.kth.se/utbildning/kandidatexjobb/datateknik/2011/rapport/ahmed_rakiv_OCH_aule_jonas_K11072.pdf


1
这实际上是一个非常强大的Android游戏开发库。唯一奇怪的事情就是坐标处理,正如评估所指出的那样。 - Sosavpm
1
所以,如果你熟悉相机或矩阵,你可以拥有任何你想要的坐标系。 :) - badlogic
3
但如果你不使用相机,似乎就要没辙了,需要在API中包装一个外观来改变这个问题。啊啊啊..为什么不使用除了常见的标准左上坐标系以外的其他东西呢?为什么呜呜呜呜呜?:( - user796820
2
@Perce,因为数学。 - NateS
哈哈,那么其他使用左上角坐标系的9999个库没有利用数学。有趣。:p - User

1

我刚刚创建了一个继承自SpriteBatch的类,覆盖了某些方法,并添加了y = Gdx.graphics.getHeight() - y - height。简单而有效。


0

我成功地使用建议的翻转坐标系通过正交相机正确地渲染了纹理和字体。这是我所做的:

private SpriteBatch batch;
private BitmapFont font;
private OrthographicCamera cam;
private Texture tex;

@Override
public void create () {
    batch = new SpriteBatch();
    
    font = new BitmapFont(true);
    font.setColor(Color.WHITE);
    
    cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    cam.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    tex = new Texture("badlogic.jpg");
}

@Override
public void dispose() {
    batch.dispose();
    font.dispose();
    tex.dispose();
}

@Override
public void render () {
    cam.update();
    batch.setProjectionMatrix(cam.combined);
    
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    batch.begin();
    
    font.draw(batch, "Test", 50, 50);
    batch.draw(tex, 100, 100, tex.getWidth(), tex.getHeight(), 0, 0, tex.getWidth(), tex.getHeight(), false, true);
    
    batch.end();
}

需要注意的重要事项包括:

  • BitmapFont构造函数,布尔值翻转字体
  • 对于batch.draw(),您需要使用所有这些参数,因为您需要在最后使用一个布尔值flipY来翻转纹理(我可以扩展SpriteBatch或创建一个实用程序方法来避免一直传递这么多参数)。
  • 请注意render()中的batch.setProjectionMatrix(cam.combined);

现在我们将看看今晚是否会回到这里进行编辑,以修复任何其他问题或发现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接