New Problem with Enemy AI

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ThreeSpark

Yesterday, I asked a question asking for help with getting my enemy to follow my player, however, now I am faced with a new problem - I added animations and the animations get very glitchy, constantly witching between the up, down, and right/left (depending on the direction), when the slime follows the player on the x axis. Please note that the enemy is smaller than the player. If this is the reason it is glitchy, then how do I fix it without changing the size of the enemy or player? Here is my code, if needed:

extends KinematicBody2D

onready var player = get_node("../Player")
var velocity = Vector2()
var speed = 5000
enum {RIGHT, LEFT, UP, DOWN, IDLE_RIGHT, IDLE_LEFT, IDLE_UP, IDLE_DOWN}
var anim
var new_anim
var state

func change_state(new_state):
	state = new_state
	match state:
		RIGHT:
			new_anim = 'right'
		LEFT:
			new_anim = 'left'
		UP:
			new_anim = 'up'
		DOWN:
			new_anim = 'down'
		IDLE_RIGHT:
			new_anim = 'idle_right'
		IDLE_LEFT:
			new_anim = 'idle_left'
		IDLE_UP:
			new_anim = 'idle_up'
		IDLE_DOWN:
			new_anim = 'idle_down'

func _ready():
	change_state(IDLE_RIGHT)

func _process(delta):
	if player.position.x > position.x:
		velocity.x += speed
		change_state(RIGHT)
	if player.position.x < position.x:
		velocity.x -= speed
		change_state(LEFT)
	if player.position.y > position.y:
		velocity.y += speed
		change_state(DOWN)
	if player.position.y < position.y:
		velocity.y -= speed
		change_state(UP)
	if new_anim != anim:
		anim = new_anim
		$AnimationPlayer.play(anim)

func _physics_process(delta):
	velocity = move_and_slide(velocity * delta)

Some tips if you’re interested. You shouldn’t multiply delta in move_and_slide, since move_and_slide does that on its own. However if you change it, you’ll have a host of other problems. And if you’d like some smoother movement, you could do:

velocity = (player.position - position).normalized() * speed

which will move directly towards the player. Then use if statements to check which direction you’re moving to set your state.

rk3Omega | 2018-08-01 19:29

:bust_in_silhouette: Reply From: rk3Omega

It flips because every time it moves it switches back and forth between being greater than and less than the player’s position (of that axis). A way to get around this is to prevent the movement and state change if the speed of the movement is greater than the distance intended. One way to fix this would be:

func _process(delta):
    var min_distance = 4
    if player.position.x > position.x && abs(player.position.x - position.x) > min_distance:
        velocity.x += speed
        change_state(RIGHT)
    if player.position.x < position.x && abs(player.position.x - position.x) > min_distance:
        velocity.x -= speed
        change_state(LEFT)
    if player.position.y > position.y && abs(player.position.y - position.y) > min_distance:
        velocity.y += speed
        change_state(DOWN)
    if player.position.y < position.y && abs(player.position.y - position.y) > min_distance:
        velocity.y -= speed
        change_state(UP)
    if new_anim != anim:
        anim = new_anim
        $AnimationPlayer.play(anim)