New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle higher resolution screens? #3

Closed
hexdie opened this Issue Aug 26, 2016 · 4 comments

Comments

Projects
None yet
3 participants
@hexdie
Copy link

hexdie commented Aug 26, 2016

I guess I'll be the first asking a question here :D

I haven't really utilized the web target until recently and I noticed an issue on higher resolution screens where my viewport is twice the size that I actually set. I first noticed it on a macbook pro, but I was able to reproduce it with the chrome device emulator.

This is how the game is intended to look:

devicescale1

And this is how it is displaying on higher resolution displays:

devicescale2

So my question is, how do I go about making it look like that first image on higher resolution displays?

Here's the source in case it's helpful: https://bitbucket.org/hexdie/onebuttonjam16/src

Thanks!

@nebbishhacker

This comment has been minimized.

Copy link

nebbishhacker commented Aug 26, 2016

The simplest solution I can think of is to set the camera size explicitly in ready(), like so:

Luxe.camera.size = new Vector(gameResolution.x, gameResolution.y);

That way regardless of the canvas size, things should still be scaled appropriately.

@underscorediscovery underscorediscovery changed the title Web Target - How to handle higher resolution screens? How to handle higher resolution screens? Aug 26, 2016

@underscorediscovery

This comment has been minimized.

Copy link
Member

underscorediscovery commented Aug 26, 2016

Thanks @hexdie, good question.
In fact it should actually come up on native as well, so I adjusted the title.

coordinating

This stuff in particular needs to be documented with some more examples, but essentially the way it works is that there are some coordinate spaces that exist:

  • device (window size)
  • pixels (rendering surface size)

When you specify window.width in the config function, what you're speaking to is the first one, to the device pixels. This means that you're telling the window manager (the browser, the os) that you want it to appear as a window of that size.

On a high-DPI screen, or a screen with a content scaling factor (in Apple terms, retina) what you get is a scalar that exists with the device coordinates.

device != pixels

So when you have a scaling factor, the literal pixels that end up on the screen aren't in device coordinates anymore, they're scaled: 960 * 2x , 640 * 2x. This means you'll get maybe a quarter of your view, on a macbook with 2x scaling factor.

in luxe, coordinates are in renderable pixels,
except for the window config since that's talking to the device itself.

options

This leaves you with a few choices on what to do.

  • You can draw your sprites at their size * scaling factor
  • You can tell the camera to view the world at device size, not pixel size

Scale the world up, or scale the camera to show you the world scaled up.

The third coordinate space

There is a third space, which is the world you're creating. Making games means deciding this, how big is the space that you see on screen?

It can be convenient to treat this in the window space coordinates, but this will obviously change if the window size changes - different resolutions will have a different size world. This has always been a problem for games, unless you don't allow resizing, and hardcode the window size. What you're actually doing is...

Separate the coordinate spaces, and define a fixed size for your world. All this means is saying: When you look at the world at any given time, how many world units are displayed?

Let's take for example a simple tile based game, that has 5 tiles vertically on screen. If the world coordinates said one tile is 1 unit, then your world size is 5 on the y axis, in relation to the screen. A lot of pixel art games that scale up use this approach by picking a fixed resolution to work in - then drawing it bigger.

Making sense of the three combined

This leaves you with basically one actual choice/question: What coordinates/units am I using for my world, and how can I convey the world correctly on screen?

  • camera size mode facility
    • As @nebbishhacker said - tell the camera to handle automatic scaling for you
    • You tell it the world units size, choose fit, contain, or cover
    • It handles the rest
    • Try it here and press space bar , source is in tests/wip/camera_scale
  • manually set the camera viewport and positioning
    • Do what the camera size mode does yourself
  • use dynamic scaling or sizing
    • This basically is listen for resize events, and resize your content to match

converting

If you wanted to handle the resizing or setting sprites sizes, you'd need to keep in mind that luxe only speaks in the raw pixel sizes. If you use the device size, and need to convert back, you divide by device_pixel_ratio.

  • device size = pixel size / Luxe.screen.device_pixel_ratio
  • pixel size = device size * Luxe.screen.device_pixel_ratio

If you need to convert from the screen/camera space to the world space, you use the camera.world_to_screen and camera.screen_to_world, this is demonstrated in the above linked sample, displaying the mouse coordinates in world units.

Always consider the coordinate space you're dealing with.

ok

Hopefully that helps clarify what's happening. When you set the window size, you're telling the window device size a fixed device size. If you use Luxe.screen.w it returns the pixels that the device size has to draw on, which may be scaled compared to the device coords.

If you use a numeric position or size in the game, you're using world coordinates, like sprite.size = [these are in world units].

Your world units might match the device size at 1x scale, but when non 1x scale comes along, you see more of it, because the world units are not fixed.

Let me know if that clarifies things.

@hexdie

This comment has been minimized.

Copy link

hexdie commented Aug 26, 2016

Thanks @underscorediscovery! That does clarify things. The camera size mode seems most applicable to my situation, so I'll try getting that to work tonight.

@underscorediscovery

This comment has been minimized.

Copy link
Member

underscorediscovery commented Feb 14, 2017

For anyone reading this after the fact, the default behaviour has changed to be more user friendly. The full details and how this works are posted in this status post: https://luxeengine.com/dev-status-2/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment