Smooth camera in pixel perfect game

Godot Version

4.4.1 stable

Question

So I have a pixel perfect game with a viewport of 320x180 and the camera feels way too jitterry and the parallax makes it even more visible, wich is a bad thing, i want a smooth camera, but always fail. By the way this is the root:

Main
-SubViewportContainer(stretch=on, strecth = 6)

  • SubViewport
  • -Game
    –Camera2D

Should I use remote transfom or? I really dont know how to make the camera transform be subpixelated

1 Like

I encountered the same issue when working with pixel sprites - frankly, I doubt there’s a practical workaround for this that allows smooth camera movement at at such a small raw resolution (at least I don’t know of any). To get past this, I recreated the project with all sprites scaled up ×10 (I drew them in Photoshop, so I kept the original files pixel-perfect and just exported them at 10× scale) and variables adjusted to accomodate the change; this allowed for much smoother camera movement and also seemed to result in much better physics regarding the player’s collision with tiles and other objects in the game. It might seem annoying to rebuild most of a project for this reason but I think it would be worthwhile.

I think @alajuelan 's fix if the only real way of solving this; use pixel assets at greater than 1:1 scale so you can do “sub-pixel” adjustments on positions and the camera.

You should be able to do this without manually rescaling any of your assets by setting the source texture filters to NEAREST, and setting a scale value.

1 Like

Cant the scale of the sprites be increased, instead of resaving the image 10x bigger ?
Ive also encoutered this problem passing from 2D to 3D, most the depth effects, ( distance blur /fog of war / bloom / pixellated depth ), dont work very well with normal pixel images… the effects values are really scale high to work with very big images

Actually, I think I just found a way to do what @Neonsise is looking for without the cumbersome fix I mentioned earlier - the scaling of an entire project’s window can be changed by accessing the scaling value with get_window().content_scale_factor and assigning it a value other than the default 1.0, so what I tried in the old project of mine was to assign this a value of 0.1 in the main script’s _ready(), like so:
func _ready() -> void: get_window().content_scale_factor = 0.1
and then I set the zoom values of the Camera2D attached to the player to 10.0, the inverse of the window scale factor, to balance it out - and the camera appears to move smoothly without having to do any rebuilding.

but if i just scale the game up, the camera would be smooth but not pixel perfect(when you rotate sprites the texture didnt change wich isnt really pixel perfect), there should be a way to make the camera render at the screens resolution, like i said, i could maybe use remote control2D but i failed when doing it

its works… but i think the effect is simillar to use Canvas Items in project Settings / window.

there are some problems in my case the GUI is very small, and the parallax’s2D go in the wrong position.
It also goes into same problem when using a subViewport and messing with the resolutions, the sprites inside subViewport are always displayed in a lower resolution

1 Like

but if i just scale the game up that way, the camera would be smooth but not pixel perfect(when you rotate sprites the texture didnt change wich isnt really pixel perfect), there should be a way to make the camera render at the screens resolution, like i said, i could maybe use remote control2D but i failed when doing it, so yeah. It’s almost impossible to fix

Hi, i don’t know if this’ll work or not but… try watching one (or both) of these two videos.

They explain how to fix it and why it does it.

I’ve watched those like a long time ago and they didn’t fix the issue :frowning:

1 Like

Mayyybeeeee… This?

It didn’t help :frowning:

1 Like

If you want a pixel look but sub-pixel movement/camera stuff use small sprites and scale them up for use in an HD game or set your viewport stretch mode to canvas_items rather than viewport.

then the game will not be pixel perfect and makes it look horrible

If your camera or parallax is moving in subpixels then your game isn’t pixel perfect anyway. Camera smoothing wasn’t made to work with pixel perfect games which is why old games avoided them or were jittery. There’s always a trade off the more modern or vintage you want to go.

2 Likes

Building on what @markdibarry said, jitter is fundamental to fully pixel perfect display. If you don’t want to allow subpixel movement (which is your call, obviously; it’s an aesthetic choice), you’re going to get jitter.

For example, let’s say you’ve got a platform that’s moving horizontally. To make the example simple, let’s say initially it moves at 10 pixels/second for the first second. If we assume a 30Hz frame rate, that means for the first half second, the positions will be:

(Terminology note: On Commodore 8bit systems, a Jiffy was a unit of time equal to one frame…)

         Ideal   Actual
Jiffy     Pos     Pos
  0       0.0      0
  1       0.33     0
  2       0.66     0
  3       1.0      1
  4       1.33     1
  5       1.67     1
  6       2.0      2
  7       2.33     2
  8       2.67     2
  9       3.0      3
 10       3.33     3
 11       3.67     3
 12       4.0      4
 13       4.33     4
 14       4.67     4
 15       5.0      5

You can see how the positions are getting snapped to pixel coords, and how they’re only actually updating every few frames. That’s where your jitter is coming from. It’s fundamental to pixel perfect display.

It’s particularly obvious when things are moving slower, especially if you have something moving on a diagonal so it’s jittering in two dimensions.

If you want pixel perfect, this is one of the things you have to accept; there’s no way to get rid of that jitter without allowing subpixel positioning.

If, on the other hand, you want the pixel art aesthetic but don’t want the jitter, you need to allow for subpixel positioning. Using scaled up models (so each “pixel” in your sprites is actually 2x2, 3x3, or maybe 4x4 pixels) will let you do that, and if you still want to be mostly pixel perfect you could always require that the rest positions for objects were snapped to your larger grid. So, if you use 4x4 pixels, for instance, make sure any rest position’s dimensions are integer multiples of 4.

yes, you’re right, but with pixel perfect i mean: movement, rotation and scaling, but the camera/ viewport can be subpixelated

You probably want the scheme I described in the last paragraph, then.

yes, i want that. but that also didn’t work

How did it not work? I can think of several things that could have gone wrong, but what in particular didn’t work for you?