ID:2301165
 

Problem description:
To my understanding, stretch-to-fit is not a viable way to accomplish this. After some research I've gathered that to avoid stretch-to-fit I need to allow players with higher resolutions to have a larger view area, creating an unfair advantage in certain aspects of my would-be project. So it's either:
A) Give these players the advantage
B) Don't go completely full-screen
C) Use stretch-to-fit in hopes that by the time I release, BYOND will have figured a way to accommodate stretch-to-fit.

Is there a way around this I'm not seeing? Or some other option I should consider?
You can't stretch pixel art to fit and have it look good.

You can do a little math to optimize the total viewport area, decreasing the advantage/disadvantage of common resolutions.

Let's assume we want an upper maximum of 600 tiles in the view at any given time. We can calculate how many tiles would fit in the user's view as such:

screen_width / tile_width / zoom = view_width
screen_height / tile_height / zoom = view_height


We want to round these values up to ensure there is no black space at the edges of the map:

ceil(screen_width / tile_width / zoom) = view_width
ceil(screen_height / tile_height / zoom) = view_height


Next, we need to make sure that view_width and view_height are always odd to ensure that the screen can always be centered on a single tile.

if(!(view_width%2)) view_width += 1
if(!(view_height%2)) view_height += 1


Now here comes the interesting bit: We check if view_width*view_height >= our maximum value. If so, we increase zoom by 1 and try again.

Here's what the loop looks like:

var/area = 1#INF
var/zoom = 0
var/view_width, view_height
while(area>=MAX_TILES)
zoom += 1
view_width = ceil(screen_width / TILE_WIDTH / zoom)
view_height = ceil(screen_height / TILE_HEIGHT / zoom)
if(!(view_width%2)) view_width += 1
if(!(view_height%2)) view_height += 1
area = view_width * view_height


Let's Try this code out with some common screen resolutions:

http://store.steampowered.com/hwsurvey/
https://www.w3schools.com/browsers/browsers_display.asp

TILE_WIDTH = 32
TILE_HEIGHT = 32
MAX_TILES = 600

Format: view_widthxview_height@zoom (% of global marketshare)

1920x1080:  31x17@2  (56.7%)  16:9 Desktop standard: HD1080
1366x768:  23x13@2  (17.3%)  16:9 Netbook standard
1600x900:  25x15@2  ( 4.3%)  16:9 Laptop standard
1440x900:  23x15@2  ( 3.8%)
1680x1050:  27x17@2  ( 2.7%)
2560x1440:  27x15@3  ( 2.6%)  Dying Standard WQHD 16:9
1280x1024:  21x17@2  ( 2.6%)  SXGA
1360x768:  21x13@2  ( 2.1%)
1024x768:  17x13@2  ( 1.0%)
1280x800:  21x15@2  ( 1.0%)  WXGA
1920x1200:  31x19@2  ( 0.8%)
3840x2160:  31x17@4  ( 0.8%)  Future standard: UHD-1
1536x864:  25x15@2  ( 0.7%)
2560x1080:  27x13@2  ( 0.6%)  Dying Standard 21:9 UWHD
1280x720:  21x13@2  ( 0.5%)
3440x1440:  37x15@3  ( 0.2%)  Future standard 21:9 UWQHD
1280x768:  21x13@2  ( 0.2%)
4096x2160:  33x17@4  ( 0.0%)


If we get rid of all the resolutions that don't really matter and only focus on the future standards, current standards, and widest used ones, we can get a better handle on the kind of difference this kind of scaling makes:

1920x1080:  31x17@2  (56.7%)  16:9 Desktop standard: HD1080
1366x768:  23x13@2  (17.3%)  16:9 Netbook standard
1600x900:  25x15@2  ( 4.3%)  16:9 Laptop standard
1440x900:  23x15@2  ( 3.8%)
1680x1050:  27x17@2  ( 2.7%)
2560x1440:  27x15@3  ( 2.6%)  Dying Standard WQHD 16:9
1280x1024:  21x17@2  ( 2.6%)  SXGA
1360x768:  21x13@2  ( 2.1%)
3440x1440:  37x15@3  ( 0.2%)  Future standard 21:9 UWQHD
3840x2160:  31x17@4  ( 0.8%)  Future standard: UHD-1
4096x2160:  33x17@4  ( 0.0%)

For the most part, these are the resolutions you need to be thinking about targeting.

variance in x,y values as follows: 21-37 x 13-17. Realistically, at this tile size, that means a total variance of up to 4 tiles on either end of the viewport horizontally, and 2 tiles vertically.

This isn't a huge advantage, but it's definitely enough to make some players complain. It's a non-issue, though. Here's why:

We can create a windowed mode that always runs at 37x17. (Personally, I prefer 31x17, but w/e). Which gives you a window resolution of 1184x544. Then we can allow users to set their zoom to integers between 1 and min(round(screen_width/1184),round(screen_height/544)).

Disable manual resizing in windowed mode, and you are all set. Just built in a little menu that allows users to intelligently select windowed resolutions, or just straight toggle full screen mode with an automatic resolution.

Players can choose to go full screen, or have a constant viewport size. The only resolution that can't take advantage of these numbers is 1024x768... Which, let's be real, if you are still running a 1024x768 monitor, you need to take your ass out to goodwill and buy a better monitor for $10. Or hop the fence into a scrapyard.
A few additional notes:

I'd strongly recommend setting a fixed resolution of 31x17 at 32x32 tile sizes for testing until you are ready to go.

That is, if you are using screen-only and no ui elements.

21x15 is plenty fine if you have a bunch of panels and junk outside the map viewport.


512 includes new features that makes working with dynamic per-client resolutions much easier, including the LEFT, TOP, BOTTOM, and RIGHT screen loc anchors, and decimal-based percentage anchors:

http://www.byond.com/forum/?post=2189366

BYOND officially has everything you need to make this work with very little work on your part thanks to Lum's work on 512.


One thing I forgot to explain thoroughly: zoom.

When I mention zoom, I mean upscaling the icon-size of the map element (or setting its zoom property).

Because pixel art requires square pixel sizes (stretch to fit doesn't care about square pixels), you need to make sure that your art is displayed in integer multiples of your icon size:

Ergo, x1 = 32x32 -> x2 = 64x64 -> x3 = 96x96 -> x4 = 128x128, etc.

The trick to good looking pixel art is making sure that your viewport is scaled up by integer values.
Wow. Thank you for the speedy reply Ter, and thank you so much Lummox :D