[英]How Camera works in Libgdx and together with Viewport
如果您使用LibGdx,它将花费很长时间,直到您进入“摄影机”和视口。 如果您是第一次使用相机和视口,则会遇到一些有关其工作原理和使用方法的问题。 所以:
首先,重要的是要知道相机适用于世界单位而不适用于像素。 世界单位不是常规单位。 您可以自行定义一个世界单位的数量。 以后更多。
首先,我们创建一个OrthographicCamera
一个SpriteBatch
和一个Texture
:
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)清除屏幕,如果不这样做,则每个Texture都会在另一个上绘制,如果绘制Animation,我们将看到旧的Frames。
(2) batch
是我们的抽屉,他绘制我们的图像,动画等。默认情况下,他绘制的世界具有很多世界单位,例如屏幕具有像素,因此在这种情况下1世界单位= 1像素。 但是现在我们将看到50 x 50世界单位与屏幕有多大无关。 要说他应该绘制通过摄像机看到的批处理,我们必须调用: batch.setProjectionMatrix(camera.combined);
(3)现在我们在位置0,0上绘制img
,但是0,0并不意味着在像素位置0,0上,这意味着图像将在世界位置0,0上绘制,宽度和高度也不在像素中,它们是以世界单位为单位,因此img
将绘制在0,0 25x25世界单位大位置上。 因此,在50x50的视口中,图像占满整个屏幕的四分之一。
图像完全按预期填充了整个屏幕的四分之一。 但是,为什么它在右上角而不在左下角?
因此,我们的图片绘制在位置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 Pixels。 现在我们绘制一个25 x 25世界单位大的图像,SpriteBatch知道他必须绘制25 * 4 = 100像素大的图像。
因此像素仍然存在,但是在世界单位中更容易思考。 如果不清楚,这里有一些更详细的描述: Libgdx的世界单位
Box2d
如果您使用Box2d,则在World Units中进行思考也非常重要,因为Box2d与Meters一起使用。 因此,如果您在x轴上创建的力关闭了5,则该物体的速度为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构造函数中,我们定义视口的宽度和高度以及Camera。
现在,如果具有不同的屏幕尺寸,我们将获得与以前相同的结果,图像将被拉伸。
FitViewport
也许我们不会拉伸图像,我们将对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);
在我们的视口之外,将以您在此处定义的颜色绘制: Gdx.gl.glClearColor(1, 1, 1, 1);
延伸视口
也许我们不会在侧面放置酒吧,然后我们可以使用ExtendViewport。 ExtendViewport通过在一个方向上扩展世界来保持世界的长宽比而无障碍。 在屏幕上宽度和高度之间的纵横比更大时,意味着您会看到更多的世界。
在屏幕宽高比=(400/200 = 2)的屏幕上,您看到的比在屏幕300x200(300/200 = 1.5)上多;
要显示此内容,请创建一个ExtendViewport并绘制大于视口的Image和第二个小Image:
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,将会清除一些有关Camera and Viewport的问题: https : //github.com/libgdx/libgdx/wiki
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.