What is my complete thinking algorithm to understand all possible width/height transformations on the path 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 .
Later on this PixMap will be shown on the physical Screen of some physical device. 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...
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). Texture
does not have any sizes (OK, it is just a container for PixMap(s).
Now Texture
is wrapped into Sprite
( new Sprite(Texture)
). Sprite has its own width/height. Sprite is some visible part of my game (moving robot, ball, tank, missile, etc). So Sprite size overrides PixMap size and therefore shall cause scaling somehow?
But is Sprite size what I actually see on the screen (if I never called sprite.scale()
)? sprite.setSize(float, float)
- means height/width in pixels??? Can Sprite automatically set size exactly to be the same as the underlying 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? So I can set Camera size equal to Gdx Application Window (config.width / config.height in Launcher class)? 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). But I see that ExtendViewPort and ScalingViewPort "tamper" with scaling, so they resize my Sprite/PixMap/Camera sizes?
Besides, all ViewPort
classes have minHeight/minWidth
in their constructors - another size transformation / scaling?
PS Another issue is coordinates in all those cases. 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).
The OrthographicCamera defines a window into a world with some kind of virtual units of width and height. 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. 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.
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. 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. You will likely never use that directly for a 2D game.
Pixmap is image data loaded to heap memory. Creating a Texture from a Pixmap means it is transferring that image data to GPU memory so it can be used with OpenGL.
Sprite is a subclass of TextureRegion. A TextureRegion is a window into a part of a Texture.
IMO, you should almost never use the 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. 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.
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. 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. 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).
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. You could alternatively use FitViewport, but IMO users are annoyed by letterboxing. I think if you submit your game to the iOS App Store with letterboxing, they'll straight up reject it.Otherwise:
minWidth
and minHeight
parameters of the ExtendViewport constructor.minHeight
is 3 meters, then your source image of a 1m tall character 1 / 3 * 1080
= 360
should have 360 pixels of height.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.