Please reimlemt AI pathing to my shooter 2D game in processing. Right now they for some reason pause and dont go to the player, and sometimes they unpause and start moving, sometimes they can go through the tile objects in my game whch shouldnt be possible

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;

enum AnimationState {
    IDLE, WALKING, ATTACKING, DAMAGED, DYING
}

class Enemy {

    float x, y;
    float speed = 1.5;
    int health;
    int maxHealth = 100;
    float respawnTime;
    float respawnTimer = respawnTime;
    List<PVector> path;
    int pathIndex;
    int updatePathInterval = 60; // Update path every 60 frames

    boolean active;

    PImage spriteSheet;
    int spriteWidth = 90;
    int spriteHeight = 64;

    Animation currentAnim;
    HashMap<AnimationState, Animation> animations = new HashMap<>();
    AnimationState currentState = AnimationState.IDLE;
    
    int stateTimer = 0;
    int damagedDuration = 30; // Duration for damaged state in frames
    int dyingDuration = 60; // Duration for dying animation in frames
    int attackingDuration = 55; // Duration for attacking state in frames (11 frames * 5 frame delay)
    boolean hasDealtDamage = false; // Flag to ensure damage is dealt only once per attack


    

    Enemy(float respawnTime) {
        this.respawnTime = respawnTime;
        this.maxHealth = 100;
        this.health = maxHealth;


        this.spriteSheet = random(1) < 0.5 ? enemySpriteSheet1 : enemySpriteSheet2;
        animations.put(AnimationState.ATTACKING, new Animation(0, 11, 5, false));
        animations.put(AnimationState.DYING, new Animation(1, 13, 5, false));
        animations.put(AnimationState.DAMAGED, new Animation(2, 4, 5, false));
        animations.put(AnimationState.IDLE, new Animation(3, 8, 5, true));
        animations.put(AnimationState.WALKING, new Animation(4, 10, 5, true));

        // Set the initial animation
        currentAnim = animations.get(currentState);
        currentAnim.reset();
        respawn(); //this takes care of initital position
    }


void update(Tile[][] map, Player player) {

    if (!active) {//downtime after being killed
        respawnTimer -= 1.0 / frameRate;
        if (respawnTimer <= 0) {
                active = true;
                respawn();
        }
        return;
    }

    if (currentState == AnimationState.DAMAGED || currentState == AnimationState.DYING || currentState == AnimationState.ATTACKING) {
            stateTimer--;
            if (stateTimer <= 0) {
                if (currentState == AnimationState.DYING) {
                    active = false;
                    respawnTimer = respawnTime;
                } else if (currentState == AnimationState.ATTACKING) {
                    setState(AnimationState.IDLE);
                } else {
                    setState(AnimationState.WALKING);
                }
            }
            currentAnim.update();     

              if (currentState == AnimationState.ATTACKING && !hasDealtDamage) {
                checkPlayerDamage(player);
            }
            return;
        }

        if (!isWithinMapBounds(x, y)) {
            PVector safePosition = findSafeSpawnPosition();
            x = safePosition.x;
            y = safePosition.y;
        }

        frameCount++;
        if (frameCount >= updatePathInterval) {
            updatePath(map);
            frameCount = 0;
        }
    float distanceToPlayer = dist(x, y, player.x, player.y);
        if (distanceToPlayer < TILE_SIZE * 1.5) { // Adjust attack range as needed
            attack();
        } else {

        if (path!= null && !path.isEmpty()) {
            PVector target = path.get(pathIndex);
            float dx = target.x - x;
            float dy = target.y - y;
            float distance = sqrt(dx * dx + dy * dy);

            if (distance < speed) {
                pathIndex++;
                if (pathIndex >= path.size()) {
                    path = null;
                    setState(AnimationState.IDLE);
                }

            } else {
                float ratio = speed / distance;
                x += dx * ratio;
                y += dy * ratio;
                setState(AnimationState.WALKING);
            }

        } else {
            setState(AnimationState.IDLE);
        }
        }

        currentAnim.update();   
    }



     void setState(AnimationState newState) {
        if (currentState != newState) {
            currentState = newState;
            currentAnim = animations.get(currentState);
            currentAnim.reset();
            if (newState == AnimationState.DAMAGED) {
                stateTimer = damagedDuration;
            } else if (newState == AnimationState.DYING) {
                stateTimer = dyingDuration;
            } else if (newState == AnimationState.ATTACKING) {
                stateTimer = attackingDuration;
                hasDealtDamage = false; // Reset the damage flag when starting a new attack
            }
        }
    }

    void attack() {
        setState(AnimationState.ATTACKING);
    }

    void checkPlayerDamage(Player player) {
        if (dist(player.x, player.y, x, y) < TILE_SIZE && player.canTakeDamage() && isAlive() && !hasDealtDamage) {
            player.takeDamage();
            hasDealtDamage = true;
            hitFlash();
            // Note: You might want to trigger screen shake and red flash from here,
            // or implement a method in the main class that the Enemy can call.
        }
    }

    void updatePath(Tile[][] map) {
        int startX = floor(x / TILE_SIZE);
        int startY = floor(y / TILE_SIZE);
        int endX = floor(player.x / TILE_SIZE);
        int endY = floor(player.y / TILE_SIZE);

        path = aStar(map,startX, startY, endX, endY);
        pathIndex = 0;
    }

    List<PVector> aStar(Tile[][] map, int startX, int startY, int goalX, int goalY) {
        PriorityQueue<Node> openSet = new PriorityQueue<>();
        boolean[][] closedSet = new boolean[map.length][map[0].length];
        Node[][] nodeMap = new Node[map.length][map[0].length];

        for (int i = 0; i < map.length; i++) {

            for (int j = 0;j < map[0].length;j++) {

                nodeMap[i][j] = new Node(i, j);
            }
        }

        Node start = nodeMap[startX][startY];
        Node goal = nodeMap[goalX][goalY];
        start.g = 0;
        start.f = heuristic(start, goal);

        openSet.add(start);

        while(!openSet.isEmpty()) {
            Node current = openSet.poll();

            if (current == goal) {
                return reconstructPath(current);
            }

            closedSet[current.x][current.y] = true;

             for (int[] dir : new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}) {

                int neighborX = current.x + dir[0];
                int neighborY = current.y + dir[1];

                if (neighborX < 0 || neighborX >= map.length || neighborY < 0 || neighborY >= map[0].length) {
                    continue;
                }

                if (closedSet[neighborX][neighborY] || map[neighborX][neighborY].type != TileType.EMPTY) {
                    continue;
                }

                Node neighbor = nodeMap[neighborX][neighborY];
                float tentativeG = current.g + 1;

                if (!openSet.contains(neighbor) || tentativeG < neighbor.g) {
                    neighbor.parent = current;
                    neighbor.g = tentativeG;
                    neighbor.f = neighbor.g + heuristic(neighbor, goal);

                    if (!openSet.contains(neighbor)) {
                        openSet.add(neighbor);
                    }
                }
            }
        }
        return null; //no path found
    }


    float heuristic(Node a, Node b) {
        return abs(a.x - b.x) + abs(a.y - b.y);
    }


    List<PVector> reconstructPath(Node goal) {
        List<PVector> path = new ArrayList<>();
        Node current = goal;

        while(current != null) {
            path.add(new PVector(current.x * TILE_SIZE + TILE_SIZE / 2, current.y * TILE_SIZE + TILE_SIZE / 2));
            current = current.parent;
            }
        Collections.reverse(path);
        return path;
        }

    

     void takeDamage(int damage) {
        health -= damage;
        if (!isAlive()) {
            setState(AnimationState.DYING);
        } else {
            setState(AnimationState.DAMAGED);
        }
    }

    void respawn() {
        setState(AnimationState.IDLE);
        active = true;
        health = maxHealth;
        PVector safePosition = findSafeSpawnPosition();
        x = safePosition.x;
        y = safePosition.y;
    }

    boolean isAlive() {
        return health > 0;
    }

     void display() {
        if (!active) return;
        int rowIndex = currentAnim.row;
        int currentFrame = currentAnim.getCurrentFrame();

        int spriteX = currentFrame * spriteWidth;
        int spriteY = rowIndex * spriteHeight;
        pushMatrix();
        translate(x, y);

        boolean flip = false;
        if ((currentState == AnimationState.WALKING || currentState == AnimationState.ATTACKING) 
            && path != null && !path.isEmpty() && path.get(pathIndex).x < x) {
            flip = true;
            scale(-1, 1); 
        }      
       // float drawX = flip ? spriteWidth / 2f : -spriteWidsth / 2f;
         float drawX = -spriteWidth / 2;
         image(spriteSheet, drawX, -spriteHeight+spriteHeight/4, spriteWidth, spriteHeight, 
          spriteX, spriteY, 
          spriteX + spriteWidth, spriteY + spriteHeight); // Source position and size

        popMatrix();

        if (health < maxHealth && currentState != AnimationState.DYING) {
            drawHealthBar();
        }
    }


    void drawHealthBar() {
        float barWidth = TILE_SIZE;
        float healthRatio = (float)health / maxHealth;
        float barHeight = 5;
        fill(255, 0, 0);
        rect(x - barWidth / 2, y - TILE_SIZE / 2 - 10,barWidth * healthRatio, barHeight);
        noFill();
        }
    }

class Node implements Comparable<Node> {
    int x, y;
    float g, f;
    Node parent;

    Node(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override public int compareTo(Node other) {
        return Float.compare(this.f, other.f);
    }
}