Handle multiple resolutions with integer scaling

Godot 4.3

My game is a pixel art that runs at a resolution of 640 * 360, to handle the most common resolutions, the problem is that if the resolution is not a multiple of 640 * 360, black bars appear on the sides, I don’t know how avoid them and I have already tried several scripts and nothing seems to work, does anyone have a script or can guide me? this is the configuration

Change aspect to expand
as to why there’s black bars on left/right there you will need to add your own background outside the 640 width in your project, so anyone with wider screen doesn’t see the black bars
for example you can prepare up to 21:9 resolution, which is up to 840px width (and 360px height) image needed as background image

I had the same problem, and I solved it like this:
Your settings should be:

Strech
Mode: viewport
Aspect: expand
Scale: 1.0
Scale Mode: fractional

now in an appropriate script you can put:

@onready var window: Window = get_window() 
@onready var base_size: Vector2i = window.content_scale_size

func _ready():
    window.size_changed.connect(_on_window_size_changed) 
    var min_x = ProjectSettings.get_setting("display/window/size/viewport_width")
    var min_y = ProjectSettings.get_setting("display/window/size/viewport_height")
    
    window.min_size = Vector2i(min_x, min_y)

func _on_window_size_changed():
    var clamped_size = window.size
    var scale = clamped_size / base_size
	window.content_scale_size = window.size / (scale.y if scale.y <= scale.x else scale.x)

Hope that helps. You might have to clean up my script a little bit.

1 Like

It worked for me to put it in keep mode and only slight black bars are generated on the side when the resolution is not 16:9, the problem is that the game does not run so smoothly, it runs like pixel by pixel, unlike my initial configuration. :frowning:

Yes, an output resolution matching your project’s base resolution will not be able to draw a desired output pixel between two adjacent base pixels, so animation will look choppier. You might have to make a couple design decisions about what you ultimately want.

A resolution that is an integer multiple of your base will be able to represent various degrees of interstitial movement without changing the aspect ratio or drawing non-square pixels. Up-scaling your project’s assets (through settings, code, or other means) could accomplish that, so to get what you want, you might have to make the minimum size for your project a multiple of your base resolution.

That is to say, a 16 x 16 sprite on a 128 x 128 screen can’t move half a pixel, but a 32 x 32 sprite on a 256 x 256 screen that is the same size can move one pixel. If that 16 x 16 sprite has its pixels drawn at a minimum size of 1x1 original px = 2x2 final px, it will look identical on the 2x screen except that the minimum distance it can move is now half what it was on the 128 x 128 screen. Higher resolution = smoother movement, if the speed and distance moved stay the same.

Be aware that this sort of brings your base resolution up to that new minimum, and it’s an authenticity concern if you care about that (up to you). It could open you up to “mixels” as well if you’re not careful. A 640 x 360 screen will not be able to display any horizontal movements smaller than (horizontal screen size) / 640, or any vertical movements smaller than (vertical screen size) / 360. You’ll need a 1280 x 720 screen at the very minimum, assuming you go with 2x resolution.

I hope you’re able to get your game looking how you want it to, and good luck with the project.

2 Likes

Thank you very much for the information, you literally clarified all my doubts that hours of research did not clarify. :DDDDDDDD

1 Like