#2D Look at without rotating object

13 messages · Page 1 of 1 (latest)

tribal inlet
#

Hello again, I've got an enemy sprite that I want to flip horizontally and have it look at the player as it's chasing them.

I'm using a CharacterBody2D for the enemy and a lerp to change position.
The enemy ends up turning upside down when looking at the player (see image).
So I have 2 problems here:

  1. how do I stop the enemy from turning upside down and just flip horizontally when chasing the player
  2. is there a way to make the enemy move so I can detect its velocity? (see below for more info on this)

Code for moving and looking at player, I'm using:

func chase():
    await get_tree().create_timer(2).timeout
    var lerpSpeed = 0.01
    
    if player and position.distance_to(player.position) > 20:
        look_at(player.position)
        self.position = lerp(self.position, player.position, lerpSpeed)

PS: One way I solved the issue was that instead of using look_at() I used this:

func lookAt():
    if player and player.position < position:
        $Icon.flip_h = true
    else:
        $Icon.flip_h = false

But would still like to know if there's a better way to do it 🙂

Problem number 2:
I tried to use move_and_collide() but that doesn't affect the enemy's velocity either.
This is just so that I can set the correct animation when it's moving with:

if velocity == Vector2.ZERO:
        animationTree["parameters/conditions/idle"] = true
    else:
        animationTree["parameters/conditions/idle"] = false
            animationTree["parameters/conditions/isMoving"] = true
small comet
#

One way to solve your second issue is instead of lerping your character toward the player and directly adjusting the position, give it a velocity towards the player and use move_and_collide every physics step

#

Like setting the velocity to (player.position - self.position).normalize() * speed

obsidian jungle
#

This is exactly what look_at is supposed to do, it rotates the node so .forward looks at the specified target.

The whole lerp approach is probably going to give you a headache either way. You will not get a constant speed with this, but rather the closer the enemy is, the slower it gets. Might not be what you're intending to do. Using a Characterbody with move_and_slide could be the better option.

Either way, you can look at either the rotation, if you do it the way you do it, or the velocity otherwise, and flip the sprite based on that information, to make it look upright again.

tribal inlet
tribal inlet
obsidian jungle
tribal inlet
#

🤔 alright. I'll give that a try, cheers. I'm currently fighting my player character not staying flipped when moving left...

obsidian jungle
#

If you look_at/lerp him as well, that's bound to happen.

small comet
#

Also, in my suggestion above, I mentioned the key step of setting the velocity and gave example code for that to use instead of lerping. The move_and_collide function doesn't do anything unless you set velocity. The function then moves the character according to the velocity you set. It also handles collisions with obstacles automatically, which you won't get with lerping.

#

If you want to keep the effect of the enemy moving faster when they're a larger distance away, you could make the speed proportional to the magnitude of the displacement (difference between position vectors) rather than a constant

tribal inlet
# small comet Also, in my suggestion above, I mentioned the key step of setting the velocity a...

Hey thanks, so I'm trying this now (was sorting out animations for the past 2 days). I've got this:

velocity = (player.position - self.position).normalized() * speed * delta
move_and_collide(velocity)

That's called in func _physics_process(delta: float) -> void:

That works, but I was wondering how to increase the speed when the enemy is farther away. You mentioned the difference between the position vectors, but isn't that what this line does?
(player.position - self.position).normalized()