0 votes

Currently, I am trying to get the entire player (sprite, collision2d, position2d, and sprite within that position2d) to flip when the cursor is in front or behind the y axis of the position2d, to no avail. I set up the position2d as an onready var and attempted to return its value, and I couldn't get that to work either. Is there any specific way to get this working?

Thanks.

Godot version Godot Engine v3.2.3.stable.official
in Engine by (30 points)

1 Answer

+1 vote
Best answer

flip_h = global_position.x - get_global_mouse_position().x < 0 change the < to > if it's the opposite of what you want.

by (2,832 points)
selected by

When I attempt that, I get the error message 'The Identifier "flip_h" isn't declared in the current scope.'

It would need to be in the _physics_process() or _process() functions of your Sprite scripts.

The issue is, I would also like to flip it so the position 2d is also flipped to the opposite side of the player, as well whatever additional nodes I add to it. I am currently using the position2d as an arm pivot for a shooting game, that will have an additional node at the tip of the gun to spawn bullets from, so I don't think just flipping the sprites themselves will work.

Ah. A shortcut I found when playing with it was changing the x scale of the parent node to -1, but that may have unintended consequences.

The proper way to do it would be to have (relative) positions set up for all of your child nodes for when your character is facing right and another set for those facing left. Then in your parent node's _process() or_physics_process():

if global_position.x - get_global_mouse_position().x < 0:
    flip_children_right()
else:
    flip_children_left()

If your character is centered on the x axis you shouldn't need to adjust the parent node's position in those functions at all.

I'll clean it up later, but currently I have it like this:

if global_position.x - get_global_mouse_position().x > 0:
    $BodySprite.scale.x = -1
    $Arm.scale.x = -1
else:
    $BodySprite.scale.x = 1
    $Arm.scale.x = 1

For the most part, it works except for two things that I need help with. First is that the sprite now faces away from the mouse, and second is that I would like the postion2d of the arm to move to the opposite side of the body, which I am unsure of how to accomplish.

I've tried something else out, which is almost there, but whenever it tries to move the arm, I get a "Invalid get index 'position' (on base: 'null instance')." Everything else seems to work, as just before it crashes when moving the cursor to the left of the player, the arm sprite inverts. Here's the code:

extends Position2D

onready var arm = $Arm

var move_arm = true

func _physics_process(delta):
    look_at(get_global_mouse_position())
    if global_position.x - get_global_mouse_position().x > 0:
        if move_arm == true:
            arm.position.x += 5
            move_arm = false
        $ArmSprite.scale.y = -1
    else:
        if move_arm == false:
            arm.position.x -= 5
            move_arm = true
        $ArmSprite.scale.y = 1

I am unsure of where the problem is, so any assistance on this final issue would be appreciated.

If your node structure is:

Player
>Sprite
>Collision2D
>Position2D
>>Sprite

Changing the x scale of Player should cause all of the children to flip their horizontal positions. Again this is pretty hacky any may have unintended consequences. This is the more proper way:

if global_position.x - get_global_mouse_position().x < 0:
    flip_children_right()
else:
    flip_children_left()

func flip_children_right():
    $Sprite.position = Vector2(16,16)
    # (probably)
    $Sprite.flip_h = true
    $Position2D.position = Vector2(16,16)
    $Position2D/Sprite.position = Vector2(16,16)
    # (probably)
    $Position2D/Sprite.flip_h = true

func flip_children_right():
    $Sprite.position = Vector2(-16,16)
    # (probably)
    $Sprite.flip_h = false
    $Position2D.position = Vector2(-16,16)
    $Position2D/Sprite.position = Vector2(-16,16)
    # (probably)
    $Position2D/Sprite.flip_h = false

Instead of Vector2(16,16) and Vector2(-16,16) you should go through the editor to see what positions look good for your nodes in a left facing direction, and a right facing direction. You should already have one of those directions so half the job is done. If you make the x values negative they should probably give you something close to facing the other way.

If your sprites are facing opposite the mouse chance the < 0 to > 0 or vise versa.

When I use $Position2D.$Sprite.position (or my renamed equivalent), I get "Expected identifier as member."

My bad $Position2D/Sprite. I always store them in onready vars:
onready var position_sprite = $Position2D/Sprite then just access them via the variable, in this case position_sprite. That way if you ever change the names of the nodes in your editor you only have to change them in one place in code.

Works perfectly! Thank you so much!

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 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 webmaster@godotengine.org with your username.