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).

2 Likes

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

2 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.

6 Likes