# Enemy Spritesheet Animation not working

**URL:** <https://discourse.libsdl.org/t/enemy-spritesheet-animation-not-working/58890>\
**Category:** Game Development\
**Created:** [March 31, 2025, 1:18am UTC](https://discourse.libsdl.org/t/enemy-spritesheet-animation-not-working/58890 "2025-03-31T01:18:08Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![JOJOlovesGaming](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/j/b38774/32.png) [@JOJOlovesGaming](https://discourse.libsdl.org/u/JOJOlovesGaming)\
**Post date:** [March 31, 2025, 1:18am UTC](https://discourse.libsdl.org/t/enemy-spritesheet-animation-not-working/58890/1 "2025-03-31T01:18:08Z")

</div>

Hi I have an Animating Main Character but my Enemy Sprite does Animate but it renders and just freezes in one frame.

```auto
#ifndef ENEMY_H
#define ENEMY_H

#include <string>
#include <SDL.h>

// Forward declaration
class Sprite;

class Enemy {
public:
    Enemy(int health, const std::string& spritePath);
    virtual ~Enemy();

    virtual int calculateDamage(int turn) = 0;

    int getHealth() const { return health; }
    void takeDamage(int damage) { health -= damage; }

    void initSprite(SDL_Renderer* renderer);
    void updateAnimation(float deltaTime);
    void render(int x, int y, int width, int height);

    // Animation control methods
    void setFrameRate(float rate);
    void setupDefaultAnimation();

    Sprite* getSprite() { return sprite; }

protected:
    int health;
    std::string spritePath;
    Sprite* sprite;

    // Animation parameters
    int frameWidth;
    int frameHeight;
    int numFrames;
    float frameRate;
    float frameTimer;
    int currentFrame;
};

class EnemyA : public Enemy {
public:
    EnemyA();
    int calculateDamage(int turn) override;
};

class EnemyB : public Enemy {
public:
    EnemyB();
    int calculateDamage(int turn) override;
};

class EnemyC : public Enemy {
public:
    EnemyC();
    int calculateDamage(int turn) override;
};

#endif // ENEMY_H

```

```auto
#include "Enemy.h"
#include "Sprite.h"
#include <stdio.h>
#include <cstdlib>

// Animation frame definitions
#define TZ_H (512 / 4) // Width of a single frame (128px)
#define TZ_V (252 / 2) // Height of a single frame (126px)

Enemy::Enemy(int health, const std::string& spritePath)
    : health(health), spritePath(spritePath), sprite(nullptr),
    frameWidth(0), frameHeight(0), numFrames(0),
    frameRate(0.1f), frameTimer(0.0f), currentFrame(0) {
}

Enemy::~Enemy() {
    if (sprite) {
        delete sprite;
    }
}

void Enemy::setupDefaultAnimation() {
    frameWidth = TZ_H;
    frameHeight = TZ_V;
    numFrames = 8; // Assuming 4 columns x 2 rows
    frameRate = 0.1f; // Default frame rate (10 FPS)
}

void Enemy::setFrameRate(float rate) {
    frameRate = rate;
}

void Enemy::initSprite(SDL_Renderer* renderer) {
    sprite = new Sprite(renderer, spritePath.c_str());
    if (!sprite->loadTexture()) {
        fprintf(stderr, "Failed to load enemy sprite: %s\n", spritePath.c_str());
        delete sprite;
        sprite = nullptr;
        return;
    }
    setupDefaultAnimation();
    if (sprite) {
        sprite->setAnimationParameters(frameWidth, frameHeight, numFrames, frameRate);
    }
}

void Enemy::updateAnimation(float deltaTime) {
    frameTimer += deltaTime;
    while (frameTimer >= frameRate) {
        currentFrame = (currentFrame + 1) % numFrames;
        frameTimer -= frameRate;
    }

    if (sprite) {
        sprite->updateAnimation(deltaTime);
    }
}

void Enemy::render(int x, int y, int width, int height) {
    if (sprite) {
        sprite->render(x, y, width, height);
    }
}

// EnemyA implementation
EnemyA::EnemyA() : Enemy(30, "assets/Sprites/Enemies/enemy1.png") {}

int EnemyA::calculateDamage(int turn) {
    return rand() % 6 + 1;
}

// EnemyB implementation
EnemyB::EnemyB() : Enemy(25, "assets/Sprites/Enemies/enemy2.png") {}

int EnemyB::calculateDamage(int turn) {
    return turn * 2;
}

// EnemyC implementation
EnemyC::EnemyC() : Enemy(25, "assets/Sprites/Enemies/enemy3.png") {}

int EnemyC::calculateDamage(int turn) {
    return (rand() % 6 + 1);
}

```

```auto
//In Combat.cpp
    // Create appropriate enemy type
    switch (level) {
    case 1: currentEnemy = new EnemyA(); break;
    case 2: currentEnemy = new EnemyB(); break;
    case 3: currentEnemy = new EnemyC(); break;
    default: currentEnemy = new EnemyA(); break;
    }

    // Initialize enemy sprite if renderer is available
    if (currentEnemy && renderer) {
        currentEnemy->initSprite(renderer);
    }
}

// Render the combat UI
extern "C" void renderCombat(CombatContext* context) {
    if (currentEnemy == nullptr) {
        SDL_Log("Error: currentEnemy is nullptr");
        return;
    }

    //DestroyTexture code
    // Render enemy sprite aligned with Knight at Y = 400
    if (currentEnemy && currentEnemy->getSprite()) {
        const int knightYBase = 400; // Knight's Y position
        int enemyX, enemyY, enemyWidth, enemyHeight;

        switch (currentLevel) {
        case 1:
            enemyX = 1500;
            enemyWidth = 200;
            enemyHeight = 300;
            enemyY = SCREEN_HEIGHT - 300;
            break;
        case 2:
            enemyX = 1500;
            enemyWidth = 250;
            enemyHeight = 350;
            enemyY = SCREEN_HEIGHT - 300;
            break;
        case 3:
            enemyX = 1500;
            enemyWidth = 300;
            enemyHeight = 400;
            enemyY = SCREEN_HEIGHT - 300;
            break;
        default:
            enemyX = 1500;
            enemyWidth = 200;
            enemyHeight = 300;
            enemyY = SCREEN_HEIGHT - 300;
        }

        currentEnemy->getSprite()->render(enemyX, enemyY, enemyWidth, enemyHeight);
    }

    //other code

```

---

<div class="post-metadata">

**Author:** ![JOJOlovesGaming](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/j/b38774/32.png) [@JOJOlovesGaming](https://discourse.libsdl.org/u/JOJOlovesGaming)\
**Post date:** [March 31, 2025, 1:25am UTC](https://discourse.libsdl.org/t/enemy-spritesheet-animation-not-working/58890/2 "2025-03-31T01:25:18Z")

</div>

[Game Download](https://we.tl/t-Y3L5sXNsbi)

```auto
#ifndef SPRITE_H
#define SPRITE_H

#include <SDL.h>
#include <string>

// Animation frame definitions
#define TZ_H (512 / 4) // Width of a single frame (128px)
#define TZ_V (252 / 2) // Height of a single frame (126px)

class Sprite {
public:
    Sprite(SDL_Renderer* renderer, const std::string& filePath);
    ~Sprite();

    bool loadTexture();
    void render(int x, int y);
    void updateAnimation(float 
    );
    void setSize(int width, int height);
    int getWidth() const;
    int getHeight() const;

    SDL_Texture* getTexture() const;
    void destroyTexture();
    void render(int x, int y, int renderWidth = -1, int renderHeight = -1);

    // Method to set the frame rate dynamically
    void setFrameRate(float rate);

    // Method to set animation parameters
    void setAnimationParameters(int frameW, int frameH, int frames, float rate);

    // Quick setup for standard animations
    void setupDefaultAnimation();

private:
    SDL_Renderer* renderer;
    SDL_Texture* texture;
    std::string filePath;
    int width;
    int height;
    int frameWidth;
    int frameHeight;
    int numFrames;
    float frameTimer;
    float frameRate;
    int currentFrame;
};

#endif // SPRITE_H

```

```auto
#include "Sprite.h"
#include <SDL_image.h>
#include <stdio.h>

Sprite::Sprite(SDL_Renderer* renderer, const std::string& filePath)
    : renderer(renderer), texture(nullptr), filePath(filePath),
    width(0), height(0), frameWidth(0), frameHeight(0),
    numFrames(0), frameTimer(0.0f), frameRate(0.1f), currentFrame(0) {
}

Sprite::~Sprite() {
    if (texture) {
        SDL_DestroyTexture(texture);
    }
}

bool Sprite::loadTexture() {
    SDL_Surface* surface = IMG_Load(filePath.c_str());
    if (!surface) {
        fprintf(stderr, "Failed to load image %s: %s\n", filePath.c_str(), IMG_GetError());
        return false;
    }

    texture = SDL_CreateTextureFromSurface(renderer, surface);
    SDL_FreeSurface(surface);

    if (!texture) {
        fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError());
        return false;
    }

    SDL_QueryTexture(texture, nullptr, nullptr, &width, &height);
    return true;
}

void Sprite::setAnimationParameters(int frameW, int frameH, int frames, float rate) {
    frameWidth = frameW;
    frameHeight = frameH;
    numFrames = frames;
    frameRate = rate;
}

void Sprite::render(int x, int y, int renderWidth, int renderHeight) {
    if (!texture) {
        fprintf(stderr, "Texture not loaded for sprite: %s\n", filePath.c_str());
        return;
    }

    // Calculate source rectangle based on current frame
    SDL_Rect srcRect = {
        (currentFrame % (width / frameWidth)) * frameWidth,
        (currentFrame / (width / frameWidth)) * frameHeight,
        frameWidth,
        frameHeight
   

```

---

<div class="post-metadata">

**Author:** ![Daniel1985](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/d/a5b964/32.png) [@Daniel1985](https://discourse.libsdl.org/u/Daniel1985)\
**Post date:** [March 31, 2025, 7:44am UTC](https://discourse.libsdl.org/t/enemy-spritesheet-animation-not-working/58890/3 "2025-03-31T07:44:10Z")

</div>

Have you debugged your code and checked that the `frameTimer` variable is actually updated properly?  
Print out the variable to the console amd check its value.

You might want to check- and print out the `srcRect` variable to the console too, to make sure it’s set properly.

You really need to start debugging your code whenever there’s some problem with it.
