godot: Rotation plus motion causes jitter in pixel-perfect mode
Godot version
3.4.2.stable.official
System information
Win10, NVIDIA GeForce GTX 960
Issue description
I am working in pixel-perfect mode (viewport). When I rotate a sprite it follows the pixel grid perfectly, just as I want. Motion is also as expected, even if I use float velocities, the character is always fixed to the pixel grid, which is exactly what I would expect.
Now this:
If I move my rotated character with integer speed, this works fine (here: 1 px per frame):

But if I move my character with float speeds (here: 1.01 px per frame), the rotation is not stable and I get jittery pixel shifts all across the sprite:

This effect seems to stem from the interaction between the float position and the float angle.
This is a version with float speed (1.01 px per frame) and int (90°) rotation, which is fine:

It seems like Godot maps the float position and angle to the pixel grid in one go, which accumulates rounding errors between the two parameters into a single step. This could lead to the fractional part of the position influencing the outcome of the rotation, which should be independent from it.
If that is the case, a solution might lie in the direction of first rounding the position before applying the rotation.
EDIT
The same seems to be happing for scaling. I was able to see a problem with the combination of float scale and float position. But I was also able to see the problem with int position (px/frame) and a very specific scale (1.5 or 2.5), other float scalings seem to work with int positions.
Steps to reproduce
This is the minimal example code I used (also see Godot project below). It’s pretty standard. Default settings except these two:
- Display -> Window -> Size -> 320x180
- Display -> Window -> Stretch -> viewport
Change the values in the code as the comment states to get the different behaviors:
func _physics_process(delta):
var SPEED_INT = 1.0
var SPEED_FLOAT = 1.01
var ANGLE_90 = PI/2
var ANGLE_float = 1
# change these to reproduce:
# SPEED_INT / ANGLE_float --> ok
# SPEED_INT / ANGLE_90 --> ok
# SPEED_FLOAT / ANGLE_90 --> ok
# SPEED_FLOAT / ANGLE_float --> not ok
var speed = SPEED_INT
var angle = ANGLE_float
if Input.is_key_pressed(KEY_A):
self.position.x -= speed
if Input.is_key_pressed(KEY_D):
self.position.x += speed
if Input.is_key_pressed(KEY_W):
self.position.y -= speed
if Input.is_key_pressed(KEY_S):
self.position.y += speed
if Input.is_key_pressed(KEY_E):
self.rotate(angle)
if Input.is_key_pressed(KEY_Q):
self.rotate(-angle)
if Input.is_key_pressed(KEY_SPACE):
self.rotation = 0
Minimal reproduction project
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 19 (19 by maintainers)
Thanks for the discussion everyone! As a final closing note, we are very eager to improve the experience of making pixel art games in Godot 4. So please feel free to open a new issue if you stumble onto new problems
@Calinou Thanks, that was it.
It seems like I haven’t fully grasped the new settings.
So the global setting is CanvasTexture (I love that this can now be globally set!) Then each node along the tree can deviate from the global setting or just Inherit (which is the default).
So setting the CanvasTexture to Nearest and leaving everything else, works like a charm, thank you!
So, after all this journey I still have the feeling that we should try and make it easier for pixel art games to get to the setting in a more convenient way. I read that Godot allows providing configs as cfg files, which is nice. I’m thinking whether it might be a good idea to curate a set of commonly used configs for different tasks (2d pixel perfect, 2d mixed resolution, 2d hi resolution, etc) and to offer them as presets to the user in a convenient (but optional) way when they start a new project.
Do you know whether something like this already exists?
If not, I’ll try to think a little more about some presets that may make sense and if something comes out of it I’ll start a discussion about them. I think that’s probably a way better solution than to have a fixed set of project settings because that is too limiting.
It can be closed for the time being. It was a Godot 3 issue and I think that it does not occur in Godot 4 anymore. I think there is a number of issues related to pixel perfect games in 4, but they are better discussed elsewhere. The discussion is archived here so it’s fine by me to close it.