+4 votes

I've tried to use the set_flip_h in my script, but it says it's nonexistent, so I guess I need to call the function somewhere, or create it? I'm also guessing in order to use that I need to grab the sprite node that's a child of the Rigidbody2D?

I've also tried to just set the scale to -1 when going left, but it makes the character erratic and scale back and forth. Does anyone have a good way of flipping the character on the horizontal axis? Would creating a custom function to scale the character be the best way and then call it when I need it?

Any suggestions would rock from you guys. Thanks!

in Engine by (32 points)
edited by

7 Answers

+7 votes
Best answer

In a recente project i created the function:

var Direction = "Left"

func ChangeDirection():
    if Direction == "Left":
        get_node( "Sprite" ).set_flip_h( false )
        Direction = "Right"
    elif Direction == "Right":
        get_node( "Sprite" ).set_flip_h( true )
        Direction = "Left"

so, in any part of the program, call ChangeDirection, change the sprite of the object. You can improve this to have arguments and other parameters if you wish

by (429 points)
selected by

This is my movement function:

func Movement():
    var leftButton = Input.is_action_pressed("leftButton")
    var rightButton = Input.is_action_pressed("rightButton")

    if rightButton:
        set_axis_velocity(Vector2(moveSpeed, 0))
    elif leftButton:
        set_axis_velocity(Vector2(-moveSpeed, 0))
    else:
        set_axis_velocity(Vector2(0, 0))

Where would I call the ChangeDirection function? I can't seem to get it to flip no matter what I do. Should I rewrite my movement code?

ok, add the line:

if rightButton:
    get_node( "Sprite" ).set_flip_h( false ) #this line
    ...

remember to change the path for the sprite and if the direction is wrong change false to true.

than tell me if works

That worked! I was trying to add an "&" operator for some silly reason. My final movement code looked like this:

# Player Movement Control (left and right)---------------------|
func Movement():
    var leftButton = Input.is_action_pressed("leftButton")
    var rightButton = Input.is_action_pressed("rightButton")

    if rightButton:
        set_axis_velocity(Vector2(moveSpeed, 0))
        get_node( "playerSprite" ).set_flip_h( false )
    elif leftButton:
        set_axis_velocity(Vector2(-moveSpeed, 0))
        get_node( "playerSprite" ).set_flip_h( true)
    else:
        set_axis_velocity(Vector2(0, 0))

Thanks a lot for your help. I had the right idea but was doing it completely wrong. :)

No problem :D

+7 votes

There may be a better way, but I currently have my script attached to my KinematicBody2D with the sprite as a child, and when left:

set_scale(Vector2(-1,1))

when right:

set_scale(Vector2(1,1))

This flips all of the children, including my CollisionShape2D that is slightly off center.

by (33 points)

I tried this but my player acts funky when I try to move it. The code to move my character is this:

if rightButton:
    set_axis_velocity(Vector2(moveSpeed, 0))
elif leftButton:
    set_axis_velocity(Vector2(-moveSpeed, 0))
else:
    set_axis_velocity(Vector2(0, 0))

Should I use an & operator in this code or would I need to write the code differently to move my character and flip it?

0 votes

Aside using set_scale, you can set the transform (which does exactly the same thing):

set_transform(Vector2(-1,0),Vector2(0,1),get_pos())
by (703 points)
+8 votes

I want to provide an answer for Godot 3 users who are stumbling upon this page in 2018, like I did:

You can accomplish flipping an entire Node2d and all its children through use of apply_scale.

Here is how I have horizontal flipping set up for my platform game:

const DIRECTION_RIGHT = 1
const DIRECTION_LEFT = -1
var direction = Vector2(DIRECTION_RIGHT, 1)

func set_direction(hor_direction):
    if hor_direction == 0:
        hor_direction = DIRECTION_RIGHT # default to right if param is 0
    var hor_dir_mod = hor_direction / abs(hor_direction) # get unit direction
    apply_scale(Vector2(hor_dir_mod * direction.x, 1)) # flip
    direction = Vector2(hor_dir_mod, direction.y) # update direction

Then, when needed, just call:

set_direction(DIRECTION_LEFT)

or:

set_direction(DIRECTION_RIGHT)

The Node2d will then flip if it is facing the opposite direction of the parameter.

The nice thing about this implementation is that the var direction can be applied to dependent scenes, such as when determining the direction of a projectile:

func create_projectile():
    var projectile = PROJECTILE_SCENE.instance()
    projectile.direction = direction
    get_parent().add_child(projectile)

Note the above function does not define PROJECTILE_SCENE or cover translating it to the correct coordinates - it is only to show the use of direction.

by (30 points)
edited by
+2 votes

Finding this question years later when wondering the same thing myself, I found the following useful macros under part of Transform2D:

FLIP_X = Transform2D( -1, 0, 0, 1, 0, 0 )
Transform2D with mirroring applied parallel to the X axis.

FLIP_Y = Transform2D( 1, 0, 0, -1, 0, 0 )
Transform2D with mirroring applied parallel to the Y axis.

These can be use to flip an object and all its children in a way similar to the one Rob describes in his answer, but in the following single line:

transform *= Transform2D.FLIP_X
by (85 points)

and the funny thing about @Rob Blob is that the only code working is :

apply_scale(Vector2(-1, 1))

and all the other stuff are excessive!

A disclaimer: be careful when trying to change your character's rotation after modifying its transform. The rotation value is adjusted based on the transform at each processing step.

+2 votes

Sometimes simple is best, just stick to set_flip_h(), I've been using scale.x * -1 in order to reflect the sprite but this approach modifies de value of rotation_degrees and makes everything more complicated.

by (24 points)

I found this out the hard way... My rotation was all screwy and had no idea why and after hours of debugging it hit me. Yes just use setfliph(). Less headache down the line.

+2 votes

This works for me:

if(_velocity.x > 0):
    scale.x = scale.y * -1
elif(_velocity.x < 0):
    scale.x = scale.y * 1
by (58 points)

Thank you very much!

Only this worked for me, and i have no idea why... if someone could explain, i will appreciate!!

THIS WORKS!!!! Thank you so much, i'm crying rn

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.