Why am I struggling so much to get my game to look right on mobile?

Why is it that for an engine that has mobile as one of its most attractive export option and mobile support, it is so difficult to get a consistent output resolution to work on android devices, I have been struggling with this for 3 days now. My game looks perfect on my device and that is how I intend my game to look like. But when I deploy it to mobile, it looks completely off. The resolution is off, the zoom value is off… I have asked this before where I thought the zoom value was not being set correctly on device and thought I had figured it out, but I was wrong: Defold camera zoom not working when running on Android.

I have been working with the default camera and have written my own functions for screen_to_world and world_to_screen… but as soon as I deployed on mobile I realized it may have been a mistake to rely on the default camera. As I was expected to write my own functions to handle different resolutions.

I then tried the two most recommended assets:

  • Defold Orthographic Camera: as discussed in my link above, it has the auto-zoom feature and thats what I used, and tried to reach near my design look by mutliplying the zoom value calculated with my editor zoom value. But the problem here is that it will look one way in main menu and then in other levels in will look different? Also even in main menu the look of the game is still either zoomed out when compared to editor or too zoomed in based on the values I multiply with.
  • Rendy Camera: Same problem as above, it has the resolution stretch, expand and center settings and in all of them it does not look like how I want my game to look or how it looks in editor.

Coming from Unity, I never had to struggle so much with this, In Unity however the game looks in editor game window, on device it looks more or less the same.

After searching the web and trying different things for 3 days now. I had to ask, why am I struggling with this so much? Because I could not find many people complaining about this.

I know many people here are deploying to mobile. What are you guys doing? which asset are you using? Can you please share your solutions please. In my other thread @selimanac shared his custom approach but I could not implement it as at the time I did not understand what M.game_width means versus display_width. And I did not follow up.

Can you guys please just give me a solution here please, My game display setting in game.project is 540 x 960 and my design zoom value is 2 (or 0.5 for rendy camera)

Thank you

I also shared the link to the source, where you can see what those are.

game_width / game_height is your game display size (in your case, 540x960).

display_width / display_height or window_width / window_height is the actual window size(which is your phones screen size), which you can get using window.get_size or, better, using window.set_listener.

You can calculate the zoom using those parameters. It is not useful to set the zoom manually, as it may vary depending on the window(display) size and window scale(device scale and dpi).

3 Likes

This is how I handle zoom in one of my example projects(this is for pixel art):

3 Likes

You need to calculate a zoom value when the dimensions of the display change from your “design resolution”, in your case 540x960 with a 2x zoom. I have created a sample project with the same screen dimensions and an initial zoom of x2:

adaptive_zoom.zip (3.7 KB)

There’s two background images, the blue is 540x960 and the green is 270x480 (ie half the size). There is an orthographic camera with a zoom of 2.

Attached to the camera there’s also a script which detects screen resolution changes and calculates a new zoom for the camera:

local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")

function init(self)
	local initial_zoom = go.get("#camera", "orthographic_zoom")
	local display_scale = window.get_display_scale()
	window.set_listener(function(self, event, data)
		if event == window.WINDOW_EVENT_RESIZED then
			local window_width = data.width
			local window_height = data.height
			local design_width = DISPLAY_WIDTH / initial_zoom
			local design_height = DISPLAY_HEIGHT / initial_zoom

			-- with max zoom your initial design dimensions will fill and expand beyond screen bounds
			local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale

			-- with min zoom your initial design dimensions will shrink and be contained within screen bounds
			--local zoom = math.min(window_width / design_width, window_height / design_height) / display_scale
			
			go.set("#camera", "orthographic_zoom", zoom)
		end
	end)
end

This is what you see when you run the project:

And this is how the camera behaves when I resize the window:

Notice that there are two ways to calculate a zoom. The “max zoom” calculation gives you the result seen above where your initial design dimensions will fill and expand beyond screen bounds.

local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale

If you switch to the “min zoom” calculation your initial design dimensions will shrink and be contained within screen bounds:

It is up to you how you want the zoom to behave, but you can use my example as a base. Perhaps you wish to also round (up or down) the zoom value to the nearest integer value to retain nicely sized pixels. Perhaps you want to set an upper or lower limit on the zoom calculation to deal with screen resolutions which vastly differ from your design resolution.

8 Likes

First off, I’m sorry for the late reply as I was travelling and was offline for 5 days.

Thank you, that is really helpful. I feel maybe this should be added to the official camera documentation :slight_smile:

so whats the best practice on setting screen resolutions? if my game content fits in the 270 x 480, then should that be the display size in settings.project? because your provided code works for some of my levels and in some levels the zoom needs to be tweaked to get the objects in the edges to come into frame as I am using max_zoom and the objects in the edges of the screen move out of view.

My game display size vs content size for my game is below:

The camera code works great and is much more consistent that any of my other efforts but I need to understand that should my game content be smaller or larger? is there any best practice? because on my device the objects on the edges of the screen move out of view in max_zoom. ? On the editor it looks fine and in the device the max_zoom moves the edge objects out of view.

Well, this is the thing with max_zoom. If the aspect ratio of the device is very different from your design resolution part of the level will extend beyond the edge of the screen. You need to consider this when you design your game content. Perhaps expand the level with non accessible and non playable content and use min-zoom instead?

1 Like

FYI turned this into a sample project: GitHub - defold/sample-adaptive-zoom: This sample project shows how to apply an adaptive zoom to your camera component to make content look good regardless of screen resolution

3 Likes

Great stuff.. This will greatly help newbies like myself struggling with the camera. :slight_smile: