Character sprite jitters while scrolling

Godot Version

4.4.1.stable

Question

Hi, total noob here. I just started yesterday and I cannot have smoothed scrolling without the character jittering around. I've tried numerous solutions but none of them have worked, and I'm at my wits' end. Please, is there something I'm missing?

Character code:

extends CharacterBody2D

var char_direction: Vector2
const grid_size = 16
var is_moving = false
var next_destination: Vector2 = position

#movement
func _physics_process(delta: float) -> void:
	#func fix_jitter():
		#if not $PlayerStateMachine.is_moving():
			#position = position.round()
	position = next_destination
	char_direction.x = Input.get_axis("move_left", "move_right")
	char_direction.y = Input.get_axis("move_up", "move_down")
	move()
	
	if char_direction:
		velocity = char_direction * delta
		if char_direction.x > 0:
			%player_sprite.flip_h = false
			%player_sprite.animation = "walking_side"
		elif char_direction.x < 0:
			%player_sprite.flip_h = true
			%player_sprite.animation = "walking_side"
		elif char_direction.y > 0:
			%player_sprite.flip_h = false
			%player_sprite.animation = "walking_down"
		elif char_direction.y < 0:
			%player_sprite.flip_h = false
			%player_sprite.animation = "walking_up"
	else:
		velocity = velocity.move_toward(Vector2.ZERO, 0)
		if %player_sprite.animation == "walking_side": %player_sprite.animation = "idle_side"
		elif %player_sprite.animation == "walking_up": %player_sprite.animation = "idle_up"
		elif %player_sprite.animation == "walking_down": %player_sprite.animation = "idle_down"
	
	
	move_and_slide()

#snap to grid
func move():
	if char_direction:
		if is_moving == false:
			is_moving = true
			var tween = create_tween()
			tween.set_process_mode(0)
			tween.tween_property(self, "next_destination", position + char_direction*grid_size, 0.1)
			tween.tween_callback(move_false)
			
func move_false():
	is_moving = false

Camera code:

extends Camera2D

@export_category("Follow Player")
@export var player: CharacterBody2D

@export_category("Camera Smoothing")
#@export var cam_smooth: bool
@export_range(1, 10) var smooth_amount: int = 8

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
	if player != null:
		var cam_pos: Vector2
		#if cam_smooth:
		var weight: float = float(21 - smooth_amount) / 100
		cam_pos = lerp(global_position, player.global_position, weight)
		#else:
			#cam_pos = player.global_position
			
		global_position = cam_pos.round()

I have:

  • Set camera process to physics
  • Enabled physics interpolation
  • Set physics to 60fps
  • As the code shows, set the player and camera to both run on physics, and rounded the coordinates
  • Anything else that people have said to do (as long as I could understand what they were talking about)

Please help :melting_face:

Since you haven’t mentioned this one, try to go to Project Settings, Rendering, 2D, and in there, enable these two options, and see if that helps:

No, sorry. I think it slightly reduced the jitter, but it’s still there

What display settings in project settings are you using?

If you don’t move the camera at all, does the player’s position appear to jitter? That is, have you isolated whether the jitter is the player movement or the camera movement (or both)?

It’s a 640x360 viewport locked at integer scaling

It’s the camera, and only when smoothing is turned on. For now, I’ve disabled camera smoothing so the character doesn’t jitter, but it would be nice to have the smoothing

If it’s the camera, you should see the environment jittering as well.

I do wonder if you’re seeing some instability between the lerp() and the .round(); if you’re hovering on the edge of a pixel boundary, that could bounce back and forth over the line.

The way viewport scaling works is that first renders to the smallest 640x360 size, then upscales it. So it can’t accurately show subpixel positioning. Does it look better if you use canvasitems instead of viewport?

Are you making the camera follow the characterbody2d with a remote transform?

And also if your not against add-ons Phantom Camera add-on is great for widened camera controls

I’m sorry, but I don’t know how I would fix that if it were the issue

Nope, still jitters

No, the camera is a child of the player

You might consider making it a sibling of the player rather than a child; if the camera is a child of the player, the camera position is an offset from the player’s, and that could be feeding in to this.