should the display method by dividng by 11 when calculating the row index when going through each sprite frame in the enemy sprite sheet? because at the end of each animation cycle, I see a brief 'flash' where the enemy disappears alsmot as if there is no frame. The largest row is 11 columns, but other rows are smaller

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

    int frameCount = 0;
    boolean active;

    PImage spriteSheet;
    int spriteWidth = 90;
    int spriteHeight = 90;
    int currentFrame = 0;
    int frameDelay = 5;
    int frameCounter = 0;


   int stateTimer = 0;
    int damagedDuration = 30; // Duration for damaged state in frames
    int dyingDuration = 60; // Duration for dying animation in frames
    

    AnimationState currentState = AnimationState.IDLE;
    HashMap<AnimationState, int[]> animations = new HashMap<AnimationState, int[]>();

    

    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 int[]{0, 11});
        animations.put(AnimationState.DYING, new int[]{11, 13});
        animations.put(AnimationState.DAMAGED, new int[]{24, 4});
        animations.put(AnimationState.IDLE, new int[]{28, 8});
        animations.put(AnimationState.WALKING, new int[]{36, 10});

        respawn(); //this takes care of initital position
    }


void update(Tile[][] map) {

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

    if (currentState == AnimationState.DAMAGED || currentState == AnimationState.DYING) {
            stateTimer--;
            if (stateTimer <= 0) {
                if (currentState == AnimationState.DYING) {
                    active = false;
                    respawnTimer = respawnTime;
                } else {
                    setState(AnimationState.WALKING);
                }
            }
            // Don't update position or path while in DAMAGED or DYING state
            updateAnimation();
        return;
        }
  
        if (!isWithinMapBounds(x, y)) {
            PVector safePosition = findSafeSpawnPosition();
            x = safePosition.x;
            y = safePosition.y;
        }

        frameCount++;
        if (frameCount >= updatePathInterval) {
            updatePath(map);
            frameCount = 0;
        }

        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);
        }
        frameCounter++;
        updateAnimation();
    }

     void updateAnimation() {
        frameCounter++;
        if (frameCounter >= frameDelay) {
            frameCounter = 0;
            currentFrame++;
            if (currentFrame >= animations.get(currentState)[1]) {
                currentFrame = 0;
            }
        }
    }

    void setState(AnimationState newState) {
        if (currentState != newState) {
            //print("setting state from: " + currentState + " to " + newState);
            currentState = newState;
            currentFrame = 0;
            if (newState == AnimationState.DAMAGED) {
                stateTimer = damagedDuration;
            } else if (newState == AnimationState.DYING) {
                stateTimer = dyingDuration;
            }
        }
    }


    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() {
        active = true;
        health = maxHealth;
        PVector safePosition = findSafeSpawnPosition();
        x = safePosition.x;
        y = safePosition.y;
    }

    boolean isAlive() {
        return health > 0;
    }

     void display() {
        if (!active) return;

        int[] animationInfo = animations.get(currentState);
        int rowIndex = animationInfo[0] / 11;  // 11 frames per row
        int colIndex = (animationInfo[0] + currentFrame) % 11;

        pushMatrix();
        translate(x, y);

        // Flip the sprite horizontally if moving left
        if (currentState == AnimationState.WALKING && path != null && !path.isEmpty() && path.get(pathIndex).x < x) {
            scale(-1, 1);
        }

        image(spriteSheet, 
              -spriteWidth/2, -spriteHeight/2, spriteWidth, spriteHeight, 
              colIndex * spriteWidth, rowIndex * spriteHeight, 
              (colIndex + 1) * spriteWidth, (rowIndex + 1) * spriteHeight);

        popMatrix();

        // Draw health bar
        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);
    }
}