Mobile screen size adaption

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Mobile screen size adaption

Post by hasen » Fri Feb 23, 2018 8:58 am

There's a few threads from this in the past but I'm still really not clear how this is done properly. I've tried many things and it's quite a nightmare so far. I tried using

Code: Select all

local scaleW, scaleH = screenwidth/internalwidth, screenheight/internalheight

function love.draw()
  love.graphics.scale(scaleW, scaleH)
  game:draw()
end
Which works okish...apart from iPhone 6 plus or the higher res iPads it starts to look weird. Then I found my on screen buttons for movement have a different position to their click zone with this graphics scale enabled. It's got to the point where I feel I need to set the sizes of every sprite, tile and image in my game as a fraction of the screen size rather than a value in pixels but that is somewhat hard to do since the values would be hard to read in the code and there are many places where graphics don't take a value for their size.

Has anyone here made any mobile games with Love2d that can share how they solved this problem? Thanks.

PGUp
Citizen
Posts: 73
Joined: Fri Apr 21, 2017 9:17 am

Re: Mobile screen size adaption

Post by PGUp » Fri Feb 23, 2018 9:06 am

-

hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Mobile screen size adaption

Post by hasen » Fri Feb 23, 2018 9:22 am

PGUp wrote:
Fri Feb 23, 2018 9:06 am
https://github.com/CodeNMore/CScreen
I tried it but it didn't work very well. The camera was made to be off centre and some of the graphics were off screen. Did you use this to make a mobile game successfully? What camera lib did you use?

It actually seems to have the opposite effect that is needed here. For example I set a target resolution of 1334x750 for iPhone 6 but if the device is iPhone 4s with resolution 960x640 the graphics are scaled smaller when in fact they should be made bigger. Not sure if this is not a library for desktop resolutions rather than mobile screen size adaption.

Hikitsune-Red
Prole
Posts: 4
Joined: Sun Mar 05, 2017 5:57 pm

Re: Mobile screen size adaption

Post by Hikitsune-Red » Fri Feb 23, 2018 10:02 am

Personally, I draw everything that is a part of the game itself to a canvas, then scale that, leaving the mobile-specific bits out to be drawn and updated relative to the device, that way they are not scaled with everything else. Not exactly a catch-all solution (at least, not the way I have it set up), and it works really well for small resolution projects, as it can help maintain pixel integrity, but for other things it could probably point you in the right direction.

For reference, this was a setup on a recent project (not elegant, but it worked) :

Code: Select all

-- Draw

function love.draw()
  lg.setCanvas(canvas)
    lg.clear()
    lg.rectangle("fill", 0, 0, canvas:getWidth(), canvas:getHeight())
    drawScene()
    --Fade Overlay
    color(fadec, fade[1])
    lg.rectangle("fill", 0, 0, canvas:getWidth(), canvas:getHeight())
  lg.setCanvas()
  
  canvasScale = {1, w = lg.getWidth() / canvas:getWidth(), h = lg.getHeight() / canvas:getHeight()}
  -- Draw canvas scaled according to setting
  if not allowStretching then
    canvasScale[1] = math.min(canvasScale.w, canvasScale.h)
    if maintainAspectRatio then
      canvasScale[1] = math.floor(canvasScale[1])
    end
    lg.draw(canvas, (lg.getWidth() / 2) - ((canvas:getWidth() * canvasScale[1]) / 2), (lg.getHeight() / 2) - ((canvas:getHeight() * canvasScale[1]) / 2), 0, canvasScale[1])
  else
    lg.push()
      lg.draw(canvas, 0, 0, 0, canvasScale.w, canvasScale.h)
    lg.pop()
  end
  
  if isMobile then
    -- Draw mobile UI
    lg.draw(dpad, 64, lg.getHeight() - 64 - dpad:getHeight())
    lg.draw(actions, lg.getWidth() - 64 - actions:getWidth(), lg.getHeight() - 64 - actions:getHeight())
  end
end
(It even looks like I have fragments of other code I hadn't cleaned up in there... Whoops...)

If you want to see what that looks like in action, you're more than welcome to open the project's (patently messy) code, run it on a mobile device, or run it with a "-mobile" command line argument to see how the screen and UI react to different resolutions.
Project is here

PGUp
Citizen
Posts: 73
Joined: Fri Apr 21, 2017 9:17 am

Re: Mobile screen size adaption

Post by PGUp » Fri Feb 23, 2018 10:08 am

Put CScreen.update() after CScreen.init() and it should be working
-

hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Mobile screen size adaption

Post by hasen » Fri Feb 23, 2018 10:33 am

PGUp wrote:
Fri Feb 23, 2018 10:08 am
Put CScreen.update() after CScreen.init() and it should be working
Yes I set it all up correctly of course. I think it's not designed for this use.

hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Mobile screen size adaption

Post by hasen » Fri Feb 23, 2018 10:35 am

Hikitsune-Red wrote:
Fri Feb 23, 2018 10:02 am
Personally, I draw everything that is a part of the game itself to a canvas, then scale that, leaving the mobile-specific bits out to be drawn and updated relative to the device, that way they are not scaled with everything else. Not exactly a catch-all solution (at least, not the way I have it set up), and it works really well for small resolution projects, as it can help maintain pixel integrity, but for other things it could probably point you in the right direction.

For reference, this was a setup on a recent project (not elegant, but it worked) :

Code: Select all

-- Draw

function love.draw()
  lg.setCanvas(canvas)
    lg.clear()
    lg.rectangle("fill", 0, 0, canvas:getWidth(), canvas:getHeight())
    drawScene()
    --Fade Overlay
    color(fadec, fade[1])
    lg.rectangle("fill", 0, 0, canvas:getWidth(), canvas:getHeight())
  lg.setCanvas()
  
  canvasScale = {1, w = lg.getWidth() / canvas:getWidth(), h = lg.getHeight() / canvas:getHeight()}
  -- Draw canvas scaled according to setting
  if not allowStretching then
    canvasScale[1] = math.min(canvasScale.w, canvasScale.h)
    if maintainAspectRatio then
      canvasScale[1] = math.floor(canvasScale[1])
    end
    lg.draw(canvas, (lg.getWidth() / 2) - ((canvas:getWidth() * canvasScale[1]) / 2), (lg.getHeight() / 2) - ((canvas:getHeight() * canvasScale[1]) / 2), 0, canvasScale[1])
  else
    lg.push()
      lg.draw(canvas, 0, 0, 0, canvasScale.w, canvasScale.h)
    lg.pop()
  end
  
  if isMobile then
    -- Draw mobile UI
    lg.draw(dpad, 64, lg.getHeight() - 64 - dpad:getHeight())
    lg.draw(actions, lg.getWidth() - 64 - actions:getWidth(), lg.getHeight() - 64 - actions:getHeight())
  end
end
(It even looks like I have fragments of other code I hadn't cleaned up in there... Whoops...)

If you want to see what that looks like in action, you're more than welcome to open the project's (patently messy) code, run it on a mobile device, or run it with a "-mobile" command line argument to see how the screen and UI react to different resolutions.
Project is here
Ok I'll have a look at it. Thanks.

hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Mobile screen size adaption

Post by hasen » Fri Feb 23, 2018 12:35 pm

Hikitsune-Red wrote:
Fri Feb 23, 2018 10:02 am
Personally, I draw everything that is a part of the game itself to a canvas, then scale that, leaving the mobile-specific bits out to be drawn and updated relative to the device, that way they are not scaled with everything else. Not exactly a catch-all solution (at least, not the way I have it set up), and it works really well for small resolution projects, as it can help maintain pixel integrity, but for other things it could probably point you in the right direction.

For reference, this was a setup on a recent project (not elegant, but it worked) :

Code: Select all

-- Draw

function love.draw()
  lg.setCanvas(canvas)
    lg.clear()
    lg.rectangle("fill", 0, 0, canvas:getWidth(), canvas:getHeight())
    drawScene()
    --Fade Overlay
    color(fadec, fade[1])
    lg.rectangle("fill", 0, 0, canvas:getWidth(), canvas:getHeight())
  lg.setCanvas()
  
  canvasScale = {1, w = lg.getWidth() / canvas:getWidth(), h = lg.getHeight() / canvas:getHeight()}
  -- Draw canvas scaled according to setting
  if not allowStretching then
    canvasScale[1] = math.min(canvasScale.w, canvasScale.h)
    if maintainAspectRatio then
      canvasScale[1] = math.floor(canvasScale[1])
    end
    lg.draw(canvas, (lg.getWidth() / 2) - ((canvas:getWidth() * canvasScale[1]) / 2), (lg.getHeight() / 2) - ((canvas:getHeight() * canvasScale[1]) / 2), 0, canvasScale[1])
  else
    lg.push()
      lg.draw(canvas, 0, 0, 0, canvasScale.w, canvasScale.h)
    lg.pop()
  end
  
  if isMobile then
    -- Draw mobile UI
    lg.draw(dpad, 64, lg.getHeight() - 64 - dpad:getHeight())
    lg.draw(actions, lg.getWidth() - 64 - actions:getWidth(), lg.getHeight() - 64 - actions:getHeight())
  end
end
(It even looks like I have fragments of other code I hadn't cleaned up in there... Whoops...)

If you want to see what that looks like in action, you're more than welcome to open the project's (patently messy) code, run it on a mobile device, or run it with a "-mobile" command line argument to see how the screen and UI react to different resolutions.
Project is here
I built it for iOS with Xcode and it didn't seem to work? The dpad was huge and the screen was a tiny square in the middle of the iphone screen. Also the character moved incredibly slowly. It worked fine as a love file on my computer though of course.

Hikitsune-Red
Prole
Posts: 4
Joined: Sun Mar 05, 2017 5:57 pm

Re: Mobile screen size adaption

Post by Hikitsune-Red » Sat Feb 24, 2018 12:01 pm

Hmm... Interesting.

I have no iOS devices of my own to test it with, so I've never seen how it reacted there, but on Android all is well and fine. I can understand a potential resolution issue, but speed? That is interesting.

Again, the principle holds the same. Draw the game content to a canvas, scale that, then draw your UI on top of it. That way, the UI is independent of the gamescreen's rescaling. The unfortunate trick is finding the right numbers to fit most screens; i.e., getting the UI to scale consistently. If you look at the controls module, you'll notice I use a small hack in order to allow the scaling of UI (which I never got around to doing properly) by making it read the color of a pixel touched by the touchscreen on an image with 0 opacity that fits the control UI. For instance, underneath the DPad, each arrow area is one of four colors, when a touch is registered, it gets the color of the area being touched and uses that as a reference for which control is being touched and responds accordingly. This way, I don't have to math out the areas, instead, all I have to do is scale the hidden image with the same scale as the UI.

hasen
Party member
Posts: 157
Joined: Sat Jan 20, 2018 2:01 pm

Re: Mobile screen size adaption

Post by hasen » Sat Feb 24, 2018 2:16 pm

Hikitsune-Red wrote:
Sat Feb 24, 2018 12:01 pm
Hmm... Interesting.

I have no iOS devices of my own to test it with, so I've never seen how it reacted there, but on Android all is well and fine. I can understand a potential resolution issue, but speed? That is interesting.
It may not have been speed, it may have been the controls not responding well when I clicked on them. Could have been an acceleration issue? After all, the dpad was bigger than the entire play screen! I didn't try it on a device, I just built it in Xcode and tried a few different models in the simulator.
Hikitsune-Red wrote:
Sat Feb 24, 2018 12:01 pm
Again, the principle holds the same. Draw the game content to a canvas, scale that, then draw your UI on top of it. That way, the UI is independent of the gamescreen's rescaling. The unfortunate trick is finding the right numbers to fit most screens; i.e., getting the UI to scale consistently. If you look at the controls module, you'll notice I use a small hack in order to allow the scaling of UI (which I never got around to doing properly) by making it read the color of a pixel touched by the touchscreen on an image with 0 opacity that fits the control UI. For instance, underneath the DPad, each arrow area is one of four colors, when a touch is registered, it gets the color of the area being touched and uses that as a reference for which control is being touched and responds accordingly. This way, I don't have to math out the areas, instead, all I have to do is scale the hidden image with the same scale as the UI.
Ok that makes regarding just scaling the game separately from the controls. Not sure what you mean by getting the colour of the touch though, why would there be a colour returned and why wouldn't you need to map out the coordinates of the touch areas?

Post Reply

Who is online

Users browsing this forum: JoshGrams and 5 guests