I’ve tried a lot to achieve a pixel-perfect style in my game, but one annoying issue I can’t solve is jittering when I use Snap 2D Transforms to Pixel and Snap 2D Vertices to Pixel.
I use constant speed multiplied by normalizedInput.get_vector, CharacterBody2D.velocity and move_and_slide().
I’ve also experimented a lot with the Camera settings, but it doesn’t resolve the problem. Currently, my Camera settings include 4x Zoom, Limit, Horizontal and Vertical Drag. I call camera.reset_smoothing() and camera.force_update_scroll() in the _ready function. Physic or Idle process callback doesn’t make any differences.
Adjusting the Window settings doesn’t solve the problem. I experience this issue in all stretch modes. My current approach is to keep Stretch – Mode – disabled and only adjust the camera zoom.
The sprites are 1:1 pixel-perfect. v4.2.2.stable.official
Is this an issue with physics interpolation, perhaps? I have a 144hz monitor and always get physics jitter with a 60hz physics tick rate without using the legendary smoothing addon:
2D physics interpolation was recently added to 4.3, but 4.2.2 doesn’t feature built-in physics interpolation. (3D physics interpolation should be in 4.4)
Also, the tooltip for those two Snap 2D settings (in 4.3 at least) say not to use them together as having both setting enabled could make things less smooth. Maybe try only using one or the other and see if that changes anything.
I updated Godot to 4.3 and left only Snap 2D Transforms to Pixel enabled. I also changed the stretch mode to Viewport and turned off all zoom features in the camera.
Still have problems with jittering
Maybe I’ll try add-on later…
I don’t see any jittering issues in your video, but what you’re probably confusing for jitter is the classic diagonal stepping problem, which is unfortunately the natural behavior of snapping pixels when your actual positions are floats underneath.
Here’s a video showing what it looks like when you snap the item’s rendering while the actual position moves at a 45 degree angle. The lines represent the actual float position of the boxes. The left starts exactly at a whole number and moves to another whole number. The middle is offset by 0.25, and the right is offset by 0.5.
As a matter of fact, there are a lot of new games that have come out recently that still suffer from this problem (I noticed it recently in Eiyuden Chronicle). It usually requires custom code to either actually snap your positions when moving diagonally, or logic for how you want your game to interpret the intent of your movement.
Ah! I see what you mean now. That looks like your camera is out of sync with your character, updating one frame later. There’s a lot of different things that could cause that, but I haven’t seen it in awhile. Would you be able to share your project or a minimal reproduction? I could tell you exactly the cause and how to fix it, if so.
(unrelated) Set your scale mode to integer, so when you change your screen size the pixels are even.
The camera is attached to your character. Your character’s sprite rendering snaps to the nearest rounded position, but the character still has the float position, so your camera has that float position too.
The easy fix would be to just add a rounding to your camera after you update the movement.
func _physics_process(delta):
if PlayerManagerAutoload.controllable:
player_movement()
camera.global_position = global_position.round()
I think this should be a feature that’s added in though at some point. I’ll see if I can make a PR for 4.4.
@triplefff Thanks! But 2x scale is not my way, I want to leave it 1x, cause I don’t want any half-pixel statements of player etc. @Stefh Not enough, sadly.