简体   繁体   English

Camera在Libgdx中以及与视口一起工作的方式

[英]How Camera works in Libgdx and together with Viewport

If you work with LibGdx it goes not long until you come to Camera and viewport. 如果您使用LibGdx,它将花费很长时间,直到您进入“摄影机”和视口。 If you work the first time with camera and Viewport you get some questions about how it works and how to use it. 如果您是第一次使用相机和视口,则会遇到一些有关其工作原理和使用方法的问题。 So: 所以:

  • How can I use a Camera in LibGdx? 如何在LibGdx中使用相机? What's viewport width and height? 什么是视口宽度和高度?
  • What is a Viewport, how can I use it and how it works together with the Camera? 什么是视口?如何使用视口?如何将其与相机配合使用?

How can I use a Camera in LibGdx? 如何在LibGdx中使用相机? What's viewport width and height? 什么是视口宽度和高度?

Firstly it's important that you know the Camera works with World units not with Pixels. 首先,重要的是要知道相机适用于世界单位而不适用于像素。 World units are not a regular Unit. 世界单位不是常规单位。 You self can define how much one World Unit is. 您可以自行定义一个世界单位的数量。 Later more. 以后更多。

First, we create an OrthographicCamera a SpriteBatch and a Texture : 首先,我们创建一个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");
}

We create a OrthographicCamera and in the Constructor we define how many World Units we see if we look through this camera into our world. 我们创建一个OrthographicCamera并在“构造函数”中定义如果我们通过此摄像机观察到的世界,可以看到多少个世界单位。 In our example 50 x 50 World Units these are the viewport width and height. 在我们的示例中,“ 50 x 50世界单位”是视口的宽度和高度。 So we have created a Camera with a viewport width and height of 50. 因此,我们创建了一个视口宽度和高度为50的相机。

In the render() method we render our image: 在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) Clear the Screen, if we don't do that every Texture will draw over the other and if we draw a Animation we will see the old Frames. (1)清除屏幕,如果不这样做,则每个Texture都会在另一个上绘制,如果绘制Animation,我们将看到旧的Frames。

(2) The batch is our Drawer he draws our Images, Animations etc. Default he draws a World which has so many World Units like the Screen has Pixels so in this case 1 World Unit = 1 Pixel. (2) batch是我们的抽屉,他绘制我们的图像,动画等。默认情况下,他绘制的世界具有很多世界单位,例如屏幕具有像素,因此在这种情况下1世界单位= 1像素。 But now we will see 50 x 50 World Units doesn't matter how big the screen is. 但是现在我们将看到50 x 50世界单位与屏幕有多大无关。 To say the Batch that he should draw what we see through our camera we must call: batch.setProjectionMatrix(camera.combined); 要说他应该绘制通过摄像机看到的批处理,我们必须调用: batch.setProjectionMatrix(camera.combined);

(3) Now we draw our img on Position 0,0 But 0, 0 doesn't mean on Pixel position 0,0 it means the Image will be drawn on World position 0,0 also width and height are not in Pixels they are in World units so the img will be drawn on Position 0,0 25x25 World Units big. (3)现在我们在位置0,0上绘制img ,但是0,0并不意味着在像素位置0,0上,这意味着图像将在世界位置0,0上绘制,宽度和高度也不在像素中,它们是以世界单位为单位,因此img将绘制在0,0 25x25世界单位大位置上。 So on a 50x50 viewport, the image fills one-quarter of the whole screen. 因此,在50x50的视口中,图像占满整个屏幕的四分之一。

在此处输入图片说明

The Image fill one-quarter of the whole screen exactly as expected. 图像完全按预期填充了整个屏幕的四分之一。 But why it is on the right top and not on the bottom left? 但是,为什么它在右上角而不在左下角?

The Problem is that the center of the Camera point on the position 0,0 问题是摄像头的中心在位置0,0上 在此处输入图片说明

So our Image is drawn on position 0,0 he fills the top right corner. 因此,我们的图片绘制在位置0,0处,他填充了右上角。 We must set the position of the camera so 0,0 is in the bottom left corner: 我们必须将摄像机的位置设置为0,0在左下角:

camera = new OrthographicCamera(50,50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);

In the render() method we must add camera.update() because every time we change the position or the scale or what else of the camera we must update the camera. 在render()方法中,我们必须添加camera.update()因为每次更改位置或缩放比例或相机的其他功能时,都必须更新相机。

Now the Image is in the bottom left. 现在,图像位于左下方。

Where are the Pixels? 像素在哪里?

We always speak about World units but where are the Pixels? 我们总是谈论世界单位,但像素在哪里? The pixels are still there. 像素仍然在那里。 If we have a Screen size of 200 x 200 pixels the batch will always draw 200 x 200 pixels. 如果我们的屏幕尺寸为200 x 200像素,则批处理将始终绘制200 x 200像素。 With the method batch.setProjectionMatrix(camera.combined); 使用方法batch.setProjectionMatrix(camera.combined); we only say the batch how much World Units are one Pixel. 我们只说一批像素的世界单位是多少。

If we have a Screen with 200 x 200 pixels and we create a Camera with a viewport of 50 x 50 world units the SpriteBatch know 1 WorldUnit = 4 Pixels. 如果我们有一个200 x 200像素的屏幕,并且我们创建了一个视口为50 x 50世界单位的相机,则SpriteBatch知道1 WorldUnit = 4 Pixels。 Now we draw a Image which is 25 x 25 World Units big the SpriteBatch knows he must draw the image 25 * 4 = 100 pixel big. 现在我们绘制一个25 x 25世界单位大的图像,SpriteBatch知道他必须绘制25 * 4 = 100像素大的图像。

So the pixels still there but it's easier to think in World Units. 因此像素仍然存在,但是在世界单位中更容易思考。 If it's not clear enough here is a little bit more detailed description: Libgdx's World Units 如果不清楚,这里有一些更详细的描述: Libgdx的世界单位

Box2d Box2d

It's also very important to think in World Units if you use Box2d because Box2d works with Meters. 如果您使用Box2d,则在World Units中进行思考也非常重要,因为Box2d与Meters一起使用。 So if you create a Body with a Force off 5 on the x axis, the Body is 5 m/s fast. 因此,如果您在x轴上创建的力关闭了5,则该物体的速度为5 m / s。

And now it's very cool to work with World Units because you can say 1 World Unit = 1 Meter so you can create a object with a width of 10 and you know after one second the Body will be in the Center of the Object. 现在使用World Units非常酷,因为您可以说1 World Unit = 1 Meter,因此您可以创建一个宽度为10的对象,并且您知道一秒钟之后,Body将位于对象的中心。 If you work with Pixels you will have a Problem if you have a different Screensize. 如果您使用像素,则如果屏幕尺寸不同,则会出现问题。

What is a Viewport, how can I use it and how it works together with the Camera? 什么是视口?如何使用视口?如何将其与相机配合使用?

Now we have the big Problem about different Screen sizes. 现在,我们遇到了有关不同屏幕尺寸的大问题。 Suddenly we have a Screen size of 350 x 200 pixels, now the Image will be stretched and don't look so nice as before. 突然我们的屏幕尺寸为350 x 200像素,现在图像将被拉伸并且看起来不像以前那么好。

For this Problem we use Viewports a few Viewports are StretchViewport , FitViewport and ExtendViewport . 对于这个问题,我们使用视口,一些视口是StretchViewportFitViewportExtendViewport All viewports you can find here: https://github.com/libgdx/libgdx/wiki/Viewports . 您可以在这里找到所有视口: https : //github.com/libgdx/libgdx/wiki/Viewports

Firstly what is a Viewport. 首先,什么是视口。

Imagine the camera is a speaker who speaks English. 想象一下,相机是讲英语的人。 Different Screen Sizes are other People who speak German, French, Chinese etc. and the Viewport is the translator. 屏幕大小不同的人会说德语,法语,中文等,而视口就是翻译。 The Translator doesn't change the sense of that what the English Speaker says but he adapts it so the others can understand it. 译者不会改变英语使用者所说的意思,但他会加以改编,以便其他人都能理解。 Same are camera and Viewport. 相机和视口也一样。 Viewport doesn't say or change what you can see on your screen if you run the program. 如果您运行该程序,则视口不会说或不会更改您在屏幕上看到的内容。 He only handles that you always see the same on different Screen sizes. 他只处理您始终在不同的屏幕尺寸上看到相同的内容。 A Camera can life without Viewport. 相机可以不使用视口而生活。 A Viewport not without Camera. 一个没有相机的视口。

Add a viewport Object: 添加视口对象:

private Viewport viewport;

and the resize() method: 和resize()方法:

@Override
public void resize (int width, int height) {
    viewport.update(width, height);
}

StretchViewport 拉伸视口

Create a StretchViewport: 创建一个StretchViewport:

camera = new OrthographicCamera(50, 50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
viewport = new StretchViewport(camera.viewportWidth, camera.viewportHeight, camera);

In the StretchViewport Constructor, we define the viewport width and height and the Camera. 在StretchViewport构造函数中,我们定义视口的宽度和高度以及Camera。

Now we get the same result as before if we have different Screensizes the Images will be stretched. 现在,如果具有不同的屏幕尺寸,我们将获得与以前相同的结果,图像将被拉伸。

FitViewport FitViewport

Maybe we won't stretch our Images we will matter about the ratio of x and y. 也许我们不会拉伸图像,我们将对x和y的比例很重要。

The ratio of x and y means: is an Object 2 width and 1 height he will always twice as wide as high for example 200x100, 30x15 but not 20x15. x和y的比值表示:是对象2的宽度和1的高度,他将始终是宽度的两倍,例如200x100、30x15但不是20x15。

Create a FitViewport: 创建一个FitViewport:

camera = new OrthographicCamera(50, 50);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
viewport = new FitViewport(camera.viewportWidth, camera.viewportHeight, camera);

Now the Image will always be a square. 现在,图像将始终是正方形。 To see the Bars on the Side lets draw the Image as big as our viewport: 要查看侧面的条形,请绘制与视口一样大的图像:

batch.draw(img, 0, 0, 50, 50);

在此处输入图片说明 在此处输入图片说明

The Image has a Ratio of 1 because of 50(width)/50(height) = 1 so the Image will always have the same width and height. 由于50(宽度)/ 50(高度)= 1,因此图像的比率为1,因此图像始终具有相同的宽度和高度。 The Bars on the side are outside of our Viewport and will be drawn in the color you define here: Gdx.gl.glClearColor(1, 1, 1, 1); 侧面的Gdx.gl.glClearColor(1, 1, 1, 1);在我们的视口之外,将以您在此处定义的颜色绘制: Gdx.gl.glClearColor(1, 1, 1, 1);

ExtendViewport 延伸视口

Maybe we won't Bars on the Side then we can take a ExtendViewport. 也许我们不会在侧面放置酒吧,然后我们可以使用ExtendViewport。 The ExtendViewport keeps the world aspect ratio without bars by extending the world in one direction. ExtendViewport通过在一个方向上扩展世界来保持世界的长宽比而无障碍。 Means on a screen where the aspect ratio between width and height are bigger you will see more of the world. 在屏幕上宽度和高度之间的纵横比更大时,意味着您会看到更多的世界。

On a screen 400x200 aspect ration = (400/200 = 2) you will see more than on a screen of 300x200 (300/200 = 1.5); 在屏幕宽高比=(400/200 = 2)的屏幕上,您看到的比在屏幕300x200(300/200 = 1.5)上多;

To show this create a ExtendViewport and draw the Image bigger than the viewport and a second small Image: 要显示此内容,请创建一个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();

If we now start our Program with a Screen size of 200x200 we see: 如果现在以200x200的屏幕尺寸启动程序,则会看到:

在此处输入图片说明

And if we resize the Screen on x axis To make the screen wider: 如果我们在x轴上调整屏幕的大小,请执行以下操作:

在此处输入图片说明

Now we can see more off the first Image and additinal the Second image but the ratio will always be the same. 现在,我们可以在第一个图像上看到更多,并在第二个图像上看到更多,但是比率将始终相同。 The Image is only stretched because we draw it 100x50 not because of resizing. 仅拉伸图像是因为我们将其绘制为100x50,而不是因为调整大小。

I hope this will clear some Questions about Camera and Viewport if you will learn more, read and look some tutorials and read the LibGdx wiki: https://github.com/libgdx/libgdx/wiki 我希望如果您能了解更多信息,阅读并看一些教程并阅读LibGdx Wiki,将会清除一些有关Camera and Viewport的问题: https : //github.com/libgdx/libgdx/wiki

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM