Why your scale.x = -1.0 (or negative scale.x) is freaking out!

There are several Topics in the Help section asking about this exact problem (or a slight variant), and I couldn’t see that any of them had a “great” solution… :eyes:

But there is a great solution!.. and it’s not traversing all the children of your node to set flip_h on each Sprite2D. Nor is it to “accept defeat” and set scale.y = -1 along with rotation = PI. Whilst this does work, you might be wondering… why?!. Why can’t i set a negative scale.x without the engine “freaking out” and constantly flipping my objects?

The short answer

The way Godot works under the hood is that it uses something called a Transform matrix. The individual components are more “helper” functions that try their best to convert back to a matrix.

So to speak Godot’s “native language”, the way to set a flipped x axis is something like this:

if velocity.x > 0:
    transform.x = Vector2(1.0, 0.0)
elif velocity.x < 0:
    transform.x = Vector2(-1.0, 0.0)

And voila!, this node (along with all its children), should flip in a stable manner :tada:

:drum:…Longer answer (with links) about Transform

Why does Godot (and probably every other game engine? :eyes:) use Transform Matrices? You probably already guessed it, but it is (as always) in the name of performance, we can pack multiple components into a few numbers, this way you can also perform multiple transformations at once and it’s the same as doing each individual transformation in sequence.

However you do lose something, you can’t easily go back from a Transform matrix to the individual components skew, rotation, scale (also referred to as “decomposing” in the docs), as there are multiple ways to arrive at the same result. (eg. flipping the Y axis and rotating by 180 degrees is the same as flipping the X axis)

There’s already a wonderful docs page on Transformations using 2d as an example with great example images, I had to read it to write this guide! so you should too!

To understand transform.x and transform.y better, here’s a picture from the docs:

You can set the x and y components of the Transformation matrix with the following code:

transform.x = Vector2(1.0, 0.0) # normal
transform.x = Vector2(-1.0, 0.0) # flip x direction

or for the y component:

transform.y = Vector2(0.0, 1.0) # normal
transform.y = Vector2(0.0, -1.0) # flip y direction
4 Likes

@sixrobin Maybe this is why the boolean flip_h trick I posted works?

2 Likes

Well, seems related indeed!

2 Likes