private OrthographicCamera camera;
private SpriteBatch batch;
private Texture img;
@Overridepublicvoidcreate() {
//We create a OrthographicCamera through which we see 50x50 World Units
camera = newOrthographicCamera(50,50);
batch = newSpriteBatch();
img = newTexture("badlogic.jpg");
}
我们创建一个OrthographicCamera并在构造函数中定义如果我们通过这个相机进入我们的世界,我们会看到多少个世界单位。在我们的示例中,50 x 50 世界单位是视口宽度和高度。所以我们创建了一个视口宽度和高度为 50 的相机。
在 render() 方法中,我们渲染我们的图像:
@Overridepublicvoidrender() {
//Clear the screen (1)
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//Set ProjectionMatrix of SpriteBatch (2)
batch.setProjectionMatrix(camera.combined);
batch.begin();
//Draw image on position 0, 0 with width 25 and height 25 (3)
batch.draw(img, 0, 0, 25, 25);
batch.end();
}
如何在 LibGdx 中使用相机?什么是视口宽度和高度?
首先,重要的是您要知道相机与世界单位而不是像素一起使用。世界单位不是常规单位。您可以自己定义一个世界单位是多少。以后更。
首先,我们创建
OrthographicCamera
aSpriteBatch
和 aTexture
:private OrthographicCamera camera; private SpriteBatch batch; private Texture img; @Override public void create () { //We create a OrthographicCamera through which we see 50x50 World Units camera = new OrthographicCamera(50,50); batch = new SpriteBatch(); img = new Texture("badlogic.jpg"); }
我们创建一个
OrthographicCamera
并在构造函数中定义如果我们通过这个相机进入我们的世界,我们会看到多少个世界单位。在我们的示例中,50 x 50 世界单位是视口宽度和高度。所以我们创建了一个视口宽度和高度为 50 的相机。在 render() 方法中,我们渲染我们的图像:
@Override public void render () { //Clear the screen (1) Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); //Set ProjectionMatrix of SpriteBatch (2) batch.setProjectionMatrix(camera.combined); batch.begin(); //Draw image on position 0, 0 with width 25 and height 25 (3) batch.draw(img, 0, 0, 25, 25); batch.end(); }
(1) 清除屏幕,如果我们不这样做,每个纹理都会覆盖另一个,如果我们绘制动画,我们将看到旧的帧。
(2) 这
batch
是我们的抽屉,他绘制了我们的图像、动画等。默认情况下,他绘制了一个世界,它有很多世界单位,比如屏幕有像素,所以在这种情况下 1 个世界单位 = 1 个像素。但现在我们将看到 50 x 50 世界单位,不管屏幕有多大。要说批次他应该画出我们通过相机看到的东西,我们必须调用:batch.setProjectionMatrix(camera.combined);
(3) 现在我们
img
在位置 0,0 上绘制,但是 0, 0 并不意味着在像素位置 0,0 上,这意味着图像将在世界位置 0,0 上绘制,宽度和高度也不是它们所在的像素世界单位,因此img
将在位置 0,0 25x25 世界单位大上绘制。因此,在 50x50 的视口上,图像占据了整个屏幕的四分之一。图像完全按预期填充了整个屏幕的四分之一。但是为什么它在右上角而不是在左下角呢?
问题是相机点的中心在位置 0,0
所以我们的图像被绘制在位置 0,0 他填充右上角。我们必须设置相机的位置,使 0,0 在左下角:
camera = new OrthographicCamera(50,50); camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
在 render() 方法中,我们必须添加,
camera.update()
因为每次我们更改相机的位置或比例或其他内容时,我们都必须更新相机。现在图像在左下角。
像素在哪里?
我们总是谈论世界单位,但像素在哪里?像素还在。如果我们的屏幕尺寸为 200 x 200 像素,则批处理将始终绘制 200 x 200 像素。用这个方法
batch.setProjectionMatrix(camera.combined);
我们只说一批多少世界单位是一个像素。如果我们有一个 200 x 200 像素的屏幕并且我们创建一个具有 50 x 50 世界单位的视口的相机,那么 SpriteBatch 知道 1 WorldUnit = 4 像素。现在我们绘制一个 25 x 25 World Units 大的图像,SpriteBatch 知道他必须绘制 25 * 4 = 100 像素大的图像。
所以像素仍然存在,但在世界单位中更容易思考。如果还不够清楚,这里有一点更详细的描述:Libgdx's World Units
Box2d
如果您使用 Box2d,考虑使用世界单位也非常重要,因为 Box2d 与米一起使用。因此,如果您在 x 轴上创建一个 Force off 5 的 Body,该 Body 的速度为 5 m/s。
现在使用 World Units 非常酷,因为您可以说 1 World Unit = 1 Meter,这样您就可以创建一个宽度为 10 的对象,并且您知道一秒钟后 Body 将位于对象的中心。如果您使用像素,如果您有不同的屏幕尺寸,您将遇到问题。
什么是视口,如何使用它以及它如何与相机一起使用?
现在我们遇到了关于不同屏幕尺寸的大问题。突然我们有了一个 350 x 200 像素的屏幕尺寸,现在图像将被拉伸,看起来不像以前那么漂亮了。
对于这个问题,我们使用视口,一些视口是
StretchViewport
,FitViewport
和ExtendViewport
。您可以在此处找到所有视口:https : //github.com/libgdx/libgdx/wiki/Viewports。首先什么是视口。
想象一下相机是一个说英语的演讲者。不同的屏幕尺寸是说德语、法语、中文等的其他人,而视口是翻译器。译者不会改变说英语的人所说的话的意义,但他会对其进行改编,以便其他人能够理解。相机和视口也是如此。如果您运行程序,视口不会说出或更改您在屏幕上看到的内容。他只处理您在不同屏幕尺寸上总是看到相同的情况。相机可以在没有视口的情况下生存。一个没有相机的视口。
添加视口对象:
private Viewport viewport;
和 resize() 方法:
@Override public void resize (int width, int height) { viewport.update(width, height); }
拉伸视口
创建一个 StretchViewport:
camera = new OrthographicCamera(50, 50); camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0); viewport = new StretchViewport(camera.viewportWidth, camera.viewportHeight, camera);
在 StretchViewport 构造函数中,我们定义了视口的宽度和高度以及相机。
现在我们得到与以前相同的结果,如果我们有不同的屏幕尺寸,图像将被拉伸。
适合视口
也许我们不会拉伸我们的图像,我们会关心 x 和 y 的比率。
x 和 y 的比率意味着:是一个对象 2 宽度和 1 高度,他总是宽度是高度的两倍,例如 200x100、30x15 但不是 20x15。
创建一个 FitViewport:
camera = new OrthographicCamera(50, 50); camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0); viewport = new FitViewport(camera.viewportWidth, camera.viewportHeight, camera);
现在图像将永远是一个正方形。要查看侧面的条形图,让我们将图像绘制为与我们的视口一样大:
batch.draw(img, 0, 0, 50, 50);
由于 50(宽度)/50(高度)= 1,图像的比率为 1,因此图像将始终具有相同的宽度和高度。侧面的条在我们的视口之外,将以您在此处定义的颜色绘制:
Gdx.gl.glClearColor(1, 1, 1, 1);
扩展视口
也许我们不会在旁边放置栏,然后我们可以使用 ExtendViewport。ExtendViewport 通过在一个方向上扩展世界来保持世界纵横比没有条。意味着在宽高比较大的屏幕上,您将看到更多的世界。
在 400x200 纵横比 = (400/200 = 2) 的屏幕上,您将看到比在 300x200 (300/200 = 1.5) 的屏幕上更多的东西;
为了显示这一点,创建一个 ExtendViewport 并绘制比视口更大的图像和第二个小图像:
camera = new OrthographicCamera(50, 50); camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0); viewport = new ExtendViewport(camera.viewportWidth, camera.viewportHeight, camera); // in render() method batch.begin(); batch.draw(img, 0, 0, 100, 50); batch.draw(img, -20, 0, 20, 20); batch.end();
如果我们现在以 200x200 的屏幕尺寸启动我们的程序,我们会看到:
如果我们在 x 轴上调整屏幕的大小来使屏幕更宽:
现在我们可以看到第一张图片和第二张图片的更多信息,但比例始终相同。图像只是因为我们将其绘制为 100x50 而不是因为调整大小而被拉伸。
我希望这能解决一些关于相机和视口的问题,如果您将了解更多信息、阅读并查看一些教程并阅读 LibGdx wiki:https : //github.com/libgdx/libgdx/wiki