简体   繁体   English

LibGDX - Sprite / Pixmap / Camera / ViewPort 大小(宽度/高度) - 从 PixMap 到(物理设备)屏幕的所有大小转换的算法

[英]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.相机的viewportWidthviewportHeight变量定义了您正在查看游戏世界的 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 被拉伸以适合设备的屏幕,所以通常,您会希望viewportWidthviewportHeight的比率与屏幕宽度与屏幕高度的比率相同,这样图像就不会看起来失真。

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 管理器,可以自动调整相机的viewportWidthviewportHeight并进行信箱处理以防止失真。 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:如果您正在制作“复古”图形并且更喜欢以像素为单位工作:

  1. Decide how many pixels of artwork you want to see on screen.决定你想在屏幕上看到多少像素的艺术品。 Pass these as the minWidth and minHeight parameters of the ExtendViewport constructor.将这些作为 ExtendViewport 构造函数的minWidthminHeight参数传递。 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 应用商店,他们会直接拒绝它。
  2. Make your art assets as 1 pixel to 1 pixel ratio.将您的艺术资产设为 1 像素到 1 像素的比例。
  3. When you draw your TextureRegions, you don't need to specify width and height.绘制 TextureRegions 时,不需要指定宽度和高度。

Otherwise:否则:

  1. Think of your game world in meters.以米为单位考虑您的游戏世界。 Decide how many meters of game world should be visible at a time and pass these as the minWidth and minHeight parameters of the ExtendViewport constructor.决定一次应该可以看到多少米的游戏世界,并将它们作为 ExtendViewport 构造函数的minWidthminHeight参数传递。
  2. Decide what resolution of graphics you want your game to appear as, and save the assets at a high enough resolution to match.确定您希望游戏显示的图形分辨率,并以足够高的分辨率保存资源以匹配。 For example, if you want your art to look crisp only up to a screen that's 1080 pixels tall, and your camera's 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 像素高度。
  3. When you draw your TextureRegions, supply width and height of the asset in meters of game world.当您绘制 TextureRegions 时,以游戏世界的米为单位提供资产的宽度和高度。

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

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