Hi there,
I’m trying to tackle the problem of intelligently loading image assets according to window resolution. I’ve read some of the threads on this forum already, but none of them seem to provide a full solution to the problem, at least, not one that meets all of my criteria.
My criteria are:
- Must support standard def (sd), high def (hd), and double hight def (hd2) screens
- I will export 3 pngs at 3 sizes, and the correct one must be loaded and used, depending on the window size
- The pngs that are not chosen must not be loaded into memory (eg: older devices with small screens and therefore less memory should not be loading enormous background images intended for hd2 devices)
I’ve only been able to come up with one solution to this problem in Defold. But I think you’ll agree that my solution is overly complex, and would be far too much work if I had to do this for every sprite used in a game.
As a small test case, I’ve written a “smart background object” called background.go that shows a backdrop for the game. The backdrop image is dynamicaly loaded according to my criteria as I described above. The end result is that this backdrop image looks pixel perfect, regardless of window resolution and aspect ratio.
To achive this, I have written a render script such that:
- The game operates in a standard “logical resolution”, regardless of window size and aspect (my “logical resolution” is the resolution specified in the project config)
- The ortho projection for the scene is essentially the logical width and logical height of the scene, however, it can capture slightly more or less width and height to compensate for different window aspect ratios. The logical positions of objects within the scene do not change.
The smart background object (background.go) and the various resources necessary to make this possible look like this:
Game objects:
background.go
- collection proxy ("background-collection-sd")
- collection proxy ("background-collection-hd")
- collection proxy ("background-collection-hd2")
- script ("background.lua")
Collections:
collection ("background-collection-sd")
- go (scale = 2)
- sprite (atlas = "background-atlas-sd")
collection ("background-collection-hd")
- go (scale = 1)
- sprite (atlas = "background-atlas-hd")
collection ("background-collection-hd2")
- go (scale = 0.5)
- sprite (atlas = "background-atlas-hd2")
Atlases:
atlas ("background-atlas-sd")
- image ("background-sd.png")
atlas ("background-atlas-hd")
- image ("background-hd.png")
atlas ("background-atlas-hd2")
- image ("background-hd2.png")
Scripts:
background.lua
- dynamically loads one of the three collection proxies according to the resolution of the window.
So, in summary, this works like a charm. It meets all of my criteria. Except it’s a lot of bloody work: 3 images, 3 atlases, 3 collections with sprites at different scales, and an object with 3 collection proxies and a script to manage the dynamic loading. All of that just to get a sprite on the screen that’s of an appropriate resolution, without wasting lots of memory? It’s just too much.
I very much think that this is a problem that the Defold engine could help us out with. Obviously I don’t know too much about the internals of the engine, but to me, it seems that the atlas is the natural level at which to introduce some intelligence. For instance, what if the atlas could have 3 possible source images (at 3 different resolutions)? It would also need to lie about the sizes of the images, so that a sprite that uses the atlas would have the same dimensions regardless of whether it’s using low, medium, or high res image data.
One open question that would need to be addressed is: Who would make the decision about which image source to use? The engine? The developer? And when would this decision be made? As the engine starts up? Dynamically at runtime by a script?
Anyway, I think being able to make efficient use of the memory on a mobile device is pretty important, so I don’t think the prevalent advice of “just use a giant image, and let opengl downsample it for you” is going to cut it, particularly for large background images which get up-sized to the nearest power of 2.
Hopefully that provides some food for thought. Thanks for reading, and thanks for all your hard work on this great engine!