[英]LibGDX - Sprite / Pixmap / Camera / ViewPort sizes (width/height ) - algorithm of all size transformations from PixMap to (physical device) Screen
What is my complete thinking algorithm to understand all possible width/height transformations on the path PixMap -> (physical) Screen/monitor
?什么是我完整的思考算法来理解路径PixMap -> (physical) Screen/monitor
上所有可能的宽度/高度转换?
Sorry for the stupid question, but how do these sizes corellate / scale / interact?抱歉这个愚蠢的问题,但是这些尺寸如何相互关联/缩放/交互?
What size do I actually see on the screen and what scaling effects happen?我在屏幕上实际看到的尺寸是多少,会发生什么缩放效果?
I need a quick-start, but googling does not yield direct and systematic answers.我需要一个快速入门,但谷歌搜索不会产生直接和系统的答案。
PixMap
is a picture/image (from a file or some programmatically drawn primitive) with its width/height in pixels . PixMap
是一个图片/图像(来自文件或一些以编程方式绘制的图元),其宽度/高度以像素为单位。
Later on this PixMap will be shown on the physical Screen of some physical device.稍后此 PixMap 将显示在某些物理设备的物理屏幕上。 As I understand, actually it will be shown only in the part of the physical device screen - only within my game's application window ( config.width / config.height
in LwjglApplicationConfiguration
) - I guess it is in pixels...据我了解,实际上它只会显示在物理设备屏幕的一部分中 - 仅在我的游戏应用程序 window ( LwjglApplicationConfiguration
中的config.width / config.height
)中 - 我猜它是以像素为单位的......
PixMap
is wrapped into Texture
(I don't fully understand why - OpenGL says Texture is a container for one or more images, but new Texture(PixMap)
takes only a single PixMap). PixMap
被包装到Texture
中(我不完全理解为什么 - OpenGL 说 Texture 是一个或多个图像的容器,但是 new Texture(PixMap)
只需要一个 PixMap)。 Texture
does not have any sizes (OK, it is just a container for PixMap(s). Texture
没有任何尺寸(好吧,它只是 PixMap(s) 的容器。
Now Texture
is wrapped into Sprite
( new Sprite(Texture)
).现在Texture
被包裹到Sprite
( new Sprite(Texture)
) 中。 Sprite has its own width/height. Sprite 有自己的宽度/高度。 Sprite is some visible part of my game (moving robot, ball, tank, missile, etc). Sprite 是我游戏的一些可见部分(移动机器人、球、坦克、导弹等)。 So Sprite size overrides PixMap size and therefore shall cause scaling somehow?所以 Sprite 大小会覆盖 PixMap 大小,因此会以某种方式导致缩放?
But is Sprite size what I actually see on the screen (if I never called sprite.scale()
)?但是我在屏幕上实际看到的 Sprite 大小(如果我从未调用sprite.scale()
的话)? sprite.setSize(float, float)
- means height/width in pixels??? sprite.setSize(float, float)
- 表示高度/宽度(以像素为单位)??? Can Sprite automatically set size exactly to be the same as the underlying PixMap? Sprite 可以自动将大小设置为与底层 PixMap 完全相同吗?
Now Camera
size - Camera is what the user actually sees on screen (part of the Game World which might be larger than screen), right?现在Camera
尺寸 - 相机是用户在屏幕上实际看到的(游戏世界的一部分,可能比屏幕大),对吧? So I can set Camera size equal to Gdx Application Window (config.width / config.height in Launcher class)?所以我可以设置相机大小等于 Gdx 应用程序 Window(启动器类中的 config.width / config.height)? Or Camera size defines visible (displayed to the user) part of the physical screen?还是相机尺寸定义了物理屏幕的可见(显示给用户)部分? If my game fits the whole of the screen, I can set Camera size to be equal to screen size and that's all.如果我的游戏适合整个屏幕,我可以将相机尺寸设置为等于屏幕尺寸,仅此而已。 Why do I need Camera?为什么我需要相机? I think I fail to understand Camera completely.我想我无法完全理解相机。
And ViewPort
- it is "same" as Camera (it manages Camera).和ViewPort
- 它与相机“相同”(它管理相机)。 But I see that ExtendViewPort and ScalingViewPort "tamper" with scaling, so they resize my Sprite/PixMap/Camera sizes?但是我看到 ExtendViewPort 和 ScalingViewPort “篡改”了缩放,所以他们调整了我的 Sprite/PixMap/Camera 大小?
Besides, all ViewPort
classes have minHeight/minWidth
in their constructors - another size transformation / scaling?此外,所有ViewPort
类的构造函数中都有minHeight/minWidth
- 另一种尺寸转换/缩放?
PS Another issue is coordinates in all those cases. PS 另一个问题是所有这些情况下的坐标。 What relative to what?什么相对于什么?
This answer is also partially related and helpful.这个答案也部分相关且有帮助。
I'll explain for the 2D case only, which means you are using only OrthographicCamera (not PerspectiveCamera).我将仅解释 2D 情况,这意味着您仅使用 OrthographicCamera(而不是 PerspectiveCamera)。
The OrthographicCamera defines a window into a world with some kind of virtual units of width and height. OrthographicCamera 将 window 定义为具有某种宽度和高度的虚拟单位的世界。 These units can be whatever you want (in-game meters for example).这些单位可以是您想要的任何单位(例如游戏中的仪表)。 The camera's viewportWidth
and viewportHeight
variables define the size of the window you're looking through into your game's world.相机的viewportWidth
和viewportHeight
变量定义了您正在查看游戏世界的 window 的大小。 This window is stretched to fit the screen of the device, so usually, you will want the ratio of viewportWidth
to viewportHeight
to be the same as screen width to screen height, so the image will not look distorted.这个 window 被拉伸以适合设备的屏幕,所以通常,您会希望viewportWidth
与viewportHeight
的比率与屏幕宽度与屏幕高度的比率相同,这样图像就不会看起来失真。
Not all screens have the same aspect ratio, so the Viewport classes act as OrthographicCamera managers that can automatically adjust the viewportWidth
and viewportHeight
of the camera and also do letterboxing to prevent distortion.并非所有屏幕都具有相同的纵横比,因此 Viewport 类充当 OrthographicCamera 管理器,可以自动调整相机的viewportWidth
和viewportHeight
并进行信箱处理以防止失真。 By letterboxing, I mean that it can reduce the area of the screen that the camera's image is stretched onto.通过信箱,我的意思是它可以减少相机图像被拉伸到的屏幕区域。
Texture does have a height and width, which will match that of the Pixmap it was loaded with.纹理确实有一个高度和宽度,这将与它加载的像素图相匹配。 There's a different class, TextureArray, that is used for multiple images.有一个不同的 class,TextureArray,用于多个图像。 You will likely never use that directly for a 2D game.您可能永远不会直接将其用于 2D 游戏。
Pixmap is image data loaded to heap memory. Pixmap 是加载到堆 memory 的图像数据。 Creating a Texture from a Pixmap means it is transferring that image data to GPU memory so it can be used with OpenGL.从像素图创建纹理意味着它将图像数据传输到 GPU memory 以便它可以与 OpenGL 一起使用。
Sprite is a subclass of TextureRegion. Sprite 是 TextureRegion 的子类。 A TextureRegion is a window into a part of a Texture. TextureRegion 是一个 window 成为纹理的一部分。
IMO, you should almost never use the Sprite class. IMO,您几乎不应该使用 Sprite class。 It was an unfortunate design decision to make it subclass TextureRegion (violation of composition over inheritance) and it conflates an image asset with a specific game object.将其作为 TextureRegion 的子类(违反组合而不是继承)是一个不幸的设计决定,并且它将图像资产与特定游戏 object 混为一谈。 Instead, you should create your own GameObject class that has a TextureRegion variable and only the position/scale parameters you're actually going to use.相反,您应该创建自己的 GameObject class,它有一个 TextureRegion 变量并且只有您实际要使用的位置/比例参数。
When you draw a TextureRegion and don't provide an explicit width and height, it will draw to the game world with the assumption that each pixel from the original image is the same size as one of your virtual game units.当您绘制一个 TextureRegion 并且不提供明确的宽度和高度时,它将在假设原始图像中的每个像素与您的虚拟游戏单元之一大小相同的情况下绘制到游戏世界。 The only case where you should ever do something like this is if your game is supposed to have a retro look with big pixelly graphics.你应该做这样的事情的唯一情况是,如果你的游戏应该具有带有大像素图形的复古外观。 Otherwise you will want to draw it with an explicit width and height corresponding to how big it should look in the units of your game world.否则,您将需要使用与游戏世界单位中它应该看起来有多大相对应的明确宽度和高度来绘制它。
Also, when drawing a TextureRegion, the x and y parameters are where its bottom left corner go in the coordinate system of your game world.此外,在绘制 TextureRegion 时,x 和 y 参数位于游戏世界坐标系中其左下角 go 的位置。 It may or may not be fully visible, depending on whether that places it at a position in your game world that is viewable through the window of the OrthographicCamera (whose position can be moved in X and Y).它可能完全可见,也可能不完全可见,具体取决于它是否放置在游戏世界中的 position 上,可以通过 OrthographicCamera 的 window 看到(其 position 可以移动到 X 中)。
And so to sum up how to manage all of this:总结一下如何管理所有这些:
If you are doing "retro" graphics and prefer to work in units of pixels:如果您正在制作“复古”图形并且更喜欢以像素为单位工作:
minWidth
and minHeight
parameters of the ExtendViewport constructor.将这些作为 ExtendViewport 构造函数的minWidth
和minHeight
参数传递。 You could alternatively use FitViewport, but IMO users are annoyed by letterboxing.您也可以使用 FitViewport,但 IMO 用户对信箱处理感到恼火。 I think if you submit your game to the iOS App Store with letterboxing, they'll straight up reject it.我想如果你将你的游戏提交到 iOS 应用商店,他们会直接拒绝它。Otherwise:否则:
minWidth
and minHeight
parameters of the ExtendViewport constructor.决定一次应该可以看到多少米的游戏世界,并将它们作为 ExtendViewport 构造函数的minWidth
和minHeight
参数传递。minHeight
is 3 meters, then your source image of a 1m tall character 1 / 3 * 1080
= 360
should have 360 pixels of height.例如,如果您希望您的艺术作品在 1080 像素高的屏幕上看起来清晰,并且您的相机的minHeight
为 3 米,那么您的 1m 高角色的源图像1 / 3 * 1080
= 360
应该有 360 像素高度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.