Showing same number of tiles regardless of resolution

Hi, I’ve been banging my head against this for a while now and would appreciate any insight anyone has to offer. I think it will be simplest to describe my requirements and my problem in list form:

[]I’m developing a game for desktop.
[
]I’m using libGDX’s Scene2d.
[]I’m intending to limit the aspect ratio of my game area to 16:9. If someone has a 4:3 or 16:10 screen I’ll solve that by introducing letterboxing, but that is not what I’m concerned with right now and not the reason I’m writing this post.
[
]My game is 2d, with a top down viewpoint, and tile based.
[]I’m not going for a pixel art look. My original textures will be larger than their ultimate display size, at least at 1920x1080 (unless someone can explain why this is a bad idea).
[
]My main requirement/problem: I want to display the same number of tiles on screen, in both x and y, regardless of resolution.
[]The map will only scroll in terms of discrete tile positions. The map will only ever show partial tiles while in the middle of scrolling. When the map is stationary only whole tiles will be visible.
[
]In the y direction I want the tiles to cover the entire screen height. In the X direction the tiles will extend from the left of the screen rightwards as far as they need to.
[*]The number of tiles in both x and y is odd, so that there is a well defined center tile at all times.

I determine the onscreen tile size by dividing the screen height by the number of vertical tiles. The problem is that the number of vertical tiles doesn’t always divide evenly into the screen height. This results in non integer tile size and consequently non-integer tile positions, resulting in “shimmering” artifacts as the camera pans. I’m also drawing vertical and horizontal grid lines at tile boundaries and the shimmering problems are especially noticeable with these.

The solution I came up with is to calculate the tile size and overall map size as follows:

[]Divide the screen height by my vertical tile count.
[
]Floor this number to the nearest integer. This is my tile size.
[*]Calculate the size of the viewable map area by multiplying the tile size by me horizontal and vertical tile counts.

This solution works as it gives me integer tile size and integer viewable map area. The problem is that at most vertical resolutions the viewable map area ends up being shorter than the screen height. Below is an example of what this looks like (I’ve centered the viewable area so the black space at top and bottom is the same. Also, the right hand side will be a UI area):

This isn’t the most awful thing in the world but it does look kind of ugly and and it’s something I’d like to avoid if at all possible.

I’ve tried the following to remedy this:

[]Render the tiles at their original dimensions to a Frame Buffer. Then set glViewport to the dimensions I want (maintaining the correct aspect ratio) and render.
[
]As above, except simply set the Scene2d Stage size to accommodate the tiles at original dimensions, then set glViewport to appropriate screen size.

Both these methods result in the same kind of visual artifacts you get when using non integer tile sizes and positions. In fact it often looks worse as the grid lines I’m drawing (see above image) often get completely filtered out when stationary and only appear/disappear in a shifting pattern when panning the camera.

So, can anyone suggest any solutions to this? Would a custom shader be of any use here (I should point out that I only have a basic idea of what a shader is, let alone how to write one)?

Thanks in advance.

Create a camera with a fixed viewport and then use the stage to set the camera.



OrthographicCamera cam = new OrthographicCamera(640, 480);
stage.setCamera(cam);

This will force the stage to never resize if resolution changes however no idea how this will affect the rest of your code.

Me personally I use like 2-3 cameras lol, I normally have one for UI, one for Box2D and then if using Scene2D for menus one for that as well.

Okay, I just gave that a try, using native stage dimensions derived from my actual texture sizes, and glViewport set to the appropriate on-screen size. Here’s the result:

Note that there should be black lines on every visible tile boundary. In the original camera dimensions they’re 1px wide, but since the whole map is being down-sampled(?) to a smaller size here, it seems that many of the 1px lines are not being sampled at all. Which isn’t surprising, I guess. Also, when I pan the camera, the grid lines flicker on and off like crazy as they move.

Also when panning, I can see slight shimmering artifacts at the tile edges.

UPDATE: I just tried setting the texture minification filter to both Nearest and Linear and the problems remain. Seems the problem is not with texture filtering, but from projecting a larger area down to a smaller area.

I suppose while I’m here I’ll ask if anyone has an opinion on the existence of the small black bars in my game (see here). Does it look cheap, shoddy or incompetent? In fullscreen the bars are much less noticeable, assuming you have a black bordered monitor.

If your map scrolls, then yes, they look bad. If the map doesn’t scroll, it doesn’t matter a much, but it will make the game look a little less “put together”. Either way the lines won’t look as professional. But hey, it’s just a project right? :slight_smile:

A somewhat hacky solution just occurred to me. Instead of leaving the black bars in place, if necessary I’ll simply make the window shorter at runtime (i.e. somewhere in the resize method). I don’t intend to allow the user to arbitrarily re-size the window anyway, resolution will only be picked from a launcher or an options menu. The problem with this is that I may end up lying to the user about the size of the window they’ll be getting. I could provide a footnote explaining this in the launcher/options menu.

Of course, this method won’t help with fullscreen, but the black bars are barely visible there anyway.

What do you think? Would you be miffed if a game misrepresented it’s window dimensions to you? I honestly think most people wouldn’t notice as the black bars are usually no more than a dozen pixels high anyway.