20
\$\begingroup\$

I'm developing a pixel art 2D platformer for PC and smartphone, but I'm stuck on a technical issue.

I chose to have a 32x32 tile resolution, and a 64x64 character sprite resolution. The levels are divided in to sections that I call "screens", and in each screen I've got 40x22.5 tiles, approximated to 40x23, so the minimum resolution is 1280x720.

In the game, I have got a double-jump mechanic, so I need to have a good vertical view range on each "screen".

Here comes the issue: 1280x720 is not a very high resolution. On HD monitors the window would be not be big, and if I upscale the resolution by 2x, it will be in 2560x1440 and the window would be much larger than an actual HD monitor. If I try sizes in between 1280x720 and 2560x1440 the graphics start to stutter, or are deformed.

How can I solve this issue? Is there a solution that does not require me to redraw all the tiles and the sprites in 16x16 format?

\$\endgroup\$
7
  • \$\begingroup\$ Is reducing the resolution but having a camera move the screen an acceptable design choice? ie resolution is now 640 x 360 however your screens are still 1280x720 but you need to move around the room, kinda like Metroid or Axiom Verge? \$\endgroup\$
    – lozzajp
    Commented Oct 14, 2016 at 8:00
  • \$\begingroup\$ You are on the wrong spot, even if it is a 2d game, you need to define a camera. So the camera defines the viewing resolution, fov and angles, and you present the data simply to the camera. That way your game is resoultion independent \$\endgroup\$ Commented Oct 14, 2016 at 8:02
  • 1
    \$\begingroup\$ Unfortunately @YoshSynergi this is not true for pixel art. Scaling pixel art the way we might stretch a highres texture or 3D scene introduces noticeable artifacts, and even games with a virtual camera still need to carefully choose their assets, cropping, and padding to ensure any scaling to fit a target resolution is a whole-number ratio. Any fractional scale, no matter where it happens in the pipeline, will create artifacts. \$\endgroup\$
    – DMGregory
    Commented Oct 14, 2016 at 10:24
  • \$\begingroup\$ Just trying to be sure what the problem is exactly. Are you saying that because your 1280X720 map display is smaller than say a 1920X1080 monitor display then you wish to upscale your map display to be as 'fullscreen' as possible? I'm confused as drawing 16X16 tiles would not solve the problem ( as I understand it ) anyway. \$\endgroup\$
    – RobM
    Commented Oct 14, 2016 at 10:39
  • \$\begingroup\$ @DMGregory, if you can provide me some examples with artifacts in scaling when using fractional scale, that would be awesome as I can't imagine a single scenario where when I scale an image in both directions the same amount no mather if the amount is a whole or fractional number, that artifacts appear. with artifacts i mean things, that should't be there, which is different from blur, occuring on to high scaling without enough pixels. \$\endgroup\$ Commented Oct 14, 2016 at 10:41

3 Answers 3

23
\$\begingroup\$

For anyone wondering why this is an issue for pixel art, here's a quick example using a scene from Super Mario World:

Example of pixel art scene scaled, showing artifacts

If we just scale a pixel art game from 720 to 1080 at runtime (the way a typical game camera might), we get artifacts because of the non-integer ratio of screen pixels per source texel. Check out the inconsistency in the numbers from the scaled example on the right, and how garbled the leaf and Mario's ear look.

It's playable, but it's lost that charming pixel art crispness. And in motion these artifacts can crawl across a sprite, making it look shimmery.

Using a filtering mode that blends adjacent pixels will avoid the ripples, but smear and blur the pixel art instead, so it's also not very desirable.


Unfortunately the 1.5x ratio between 720p and 1080p is the worst case scenario we can encounter.

As you note, scaling 1x is too small and 2x is too big, by just as wide a margin both ways, and there's no whole-numbered scaling ratio in between for us to choose.

Your options boil down to:

  • Tolerate 1x scale, showing your game in a window 1/3 smaller than the screen, adding decorative borders if you need to fill the space.

    • You may be able to extend the cropping, showing more of your scene at a time on high-res screens. This reduces the padding/letterboxing needed, but you'll have to evaluate whether it impacts how the game plays

      (eg. does it give players on some devices an unfair advantage or let them spot secrets they shouldn't see so easily?)

  • Scale up by 2x and crop your scene, so the player sees less of the scene at a time (about 3/4 as far as they could see before).

    This too can affect how the game plays, eg. by making it hard for the player to see the places they need to double-jump to.

    • You may by able to compensate for this with camera logic, having the view pan to follow or anticipate the player, so the important content is still visible in one screen at the smaller crop, but there's no universal best camera to use.

    If you decide to go this route, try sharing some details of your gameplay and current camera, and an example scene. With that, we might be able to help tune the camera behaviour to compensate (or your game might just flat-out require more visibility)

  • Create alternate assets at a different resolution. (Yeah, this is a lot of work, but gives you the most options to control the look & feel of the game)

    This doesn't mean you have to throw out your existing assets that look great on 720p. This article describes contextually swapping between different asset sets to support a wider range of target resolutions (in Unity, but the principle can be applied in non-Unity games too).

    • As you note, redrawing all your assets at half size (16x16 tiles, 32x32 character) will let you handle 720p at 2x scale, and 1080p at 3x scale, with the same number of tiles shown as you have now. You may find the small tile resolution more restrictive visually though.

    • You could also draw an alternate, "large format" asset set that's 150% larger (48x48 tiles, 96x96 character), which would handle 1080p at 1x scale. (You'd use your existing assets for 720p or 1440 etc). The larger resolution should help you retain the fidelity of your current art, so you don't have to sacrifice the style & details you have now.

      Example of an asset redrawn at 150% scale

    • A third option is to draw an only slightly smaller asset set (24x24 tiles, 48x48 character), which can handle 1080p at 2x scale, and again might mean less sacrifice of detail than halving all your asset sizes.

      All three of these options will let you keep your framing and gameplay exactly the same at 720 & 1080, but at the cost of roughly double the asset work.

So, unfortunately there's no easy win here, just different trade-offs.


For comparison, here's the same scene above using Domi's proposed method: Scaling up 2x (the next whole-number multiple) with nearest neighbour, then scaling down to 75% (to get a net scale difference of 150%, matching the 1080/720 ratio) with bilinear filtering. As with the example on the right, I scaled the result up an extra 4x so the pixels are easier to see on high-res screens.

Example with hybrid scaling

You can see it's more consistent than the fractional nearest neighbour scale alone, but does significantly blur the crisp edges of the pixel art shapes.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ you mention keeping the original scale and using decorative borders. Depending on the context, this might be the perfect place to put GUI elements, such as score and lives. If these borders are large enough to properly fit such information, it can make it look less like 'filler', and more 'content-full' and relevant to the game. \$\endgroup\$
    – Gnemlock
    Commented Oct 14, 2016 at 23:36
3
\$\begingroup\$

Elaborating specifically on @DMGregory's option of creating alternate assets at a different resolutions:

The best solution I know of is probably the least use to you at this this point: develop your art assets in a vector format & rasterize them as needed later. This isn't a magic bullet; most of the time you will find you need to make some small handcrafted modification after rasterizing.

The next best option I know is to try various image scaling algorithms, specifically, pixel art scaling algorithms. As before, this isn't a pancea; selecting a specific scaling algorithm is highly context specific. It has as much to do with your game's 'feel' as with the art itself & even with a good algorithm + art match up, you will probably need to tweak some sprites by hand.

In both cases, the idea is to use a tool to do the bulk of the work for you and focus the human effort on the remaining details. Like @DMGregory said, "there's no easy win here, just different trade-offs."


Edit regarding fractional scaling: Most pixel art scaling algorithms only increase by whole numbers. Short of rolling your own custom scaling algorithm, you're probably going to need to combine upscaling & downscaling to get the 1.5x change you're looking for. As a reference, here's the result of combining the scale3x algorithm to upscale & the fant algorithm to downscale by 50%:

Original:

enter image description here

Scaled:

enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ Unfortunately most pixel art scaling algorithms I've found still tend to handle only whole-number upscaling (2x, 3x, 4x usually) so they don't help much with the 720->1080 case. (Maybe one could use a 3x pixel upscaler then downsample by half...? Not sure if that would look better or worse than a direct upscale) \$\endgroup\$
    – DMGregory
    Commented Oct 14, 2016 at 15:46
  • \$\begingroup\$ Valid point. Edited a bit to address it. I also stumbled across this shader which does seem to support fractional scaling. \$\endgroup\$
    – Pikalek
    Commented Oct 14, 2016 at 20:23
  • \$\begingroup\$ +1 to the vector solution. You've gotta make your assets really large and downscale. \$\endgroup\$
    – Mark Aven
    Commented Jun 12, 2018 at 1:13
1
\$\begingroup\$

Scaling pixel art by fractional number factors is not trivial, as explained by the other answers.
It is still possible to do while getting good looking results though!


enter image description here

Nearest neighbor scaling distorts the shape of pixels.


enter image description here

Bilinear filtering significantly blurs the pixels.


It is possible to combine those scaling methods, keeping the benefits of both while reducing side effects.

You start with upscaling the scene by the next larger whole-number factor using nearest neighbor. Then you downscale that to the target resolution with bilinear (or any other preferred) filtering.

enter image description here

This will keep the centers of sprite pixels untouched, and only blur the boundaries between them. Therefore it will work better for more coarse sprites / larger scaling factors, where a single sprite pixel covers a lot of screen pixels.

Those pictures are taken from https://colececil.io/blog/2017/scaling-pixel-art-without-destroying-it/, where Cole explains how to achieve similar results using a custom shader.

Here is another, admittedly extreme example. The original image was upscaled 9x, and then downscaled by 10%. The blurred boundaries are only one screen pixel in size, barely noticeable until zoomed in.

enter image description here


For comparison, here are example images that have not been zoomed in (original image was 64x64 pixels, scaled to 96x96 / 150%):

enter image description here


\$\endgroup\$
2
  • \$\begingroup\$ Note that since the question is about scaling from 720p to 1080p, you won't be able to get the blended borders between solid pixels quite as narrow as in the example shown here. I've added an example to my answer showing what this upscale-then-downscale approach looks like for the 150% case. \$\endgroup\$
    – DMGregory
    Commented Oct 25, 2021 at 15:27
  • \$\begingroup\$ @DMGregory that is true, it doesn't look as clean for small scaling factors. But when not zooming in, it is less noticeable, although still not as crisp as integer scaling. I think providing examples at their target resolution (not zoomed in) could help to show the differences in a realistic scenario. \$\endgroup\$
    – Domi
    Commented Oct 26, 2021 at 6:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .