#include "animation_system.h" #include #include #include #include "game.h" #include "vector.h" #include "util.h" void AnimationSystem::initSprite(int spriteId, std::string_view filename) { std::ifstream datafile(filename.data()); if (!datafile.is_open()) { throw std::invalid_argument(std::string("Could not find sprite datafile: ") + std::string(filename)); } Sprite& sprite = game_.getSprite(spriteId); sprite.isAnimated = true; char ch; std::string line; datafile >> sprite.spritesheet; std::string framefilename; datafile >> framefilename; std::ifstream framefile(framefilename); if (!framefile.is_open()) { throw std::invalid_argument("Could not find frame datafile: " + framefilename); } vec2i cellSize; framefile >> cellSize.w(); framefile >> ch; //, framefile >> cellSize.h(); std::getline(framefile, line); // cell size int framesPerRow; framefile >> framesPerRow; std::getline(framefile, line); // frames per row int numFrames; framefile >> numFrames; std::getline(framefile, line); // frames std::getline(framefile, line); // blank for (int i=0; i> f.size.w(); framefile >> ch; //, framefile >> f.size.h(); framefile >> ch; //, framefile >> f.center.x(); framefile >> ch; //, framefile >> f.center.y(); std::getline(framefile, line); // blank f.srcRect.x = (i % framesPerRow) * cellSize.w(); f.srcRect.y = (i / framesPerRow) * cellSize.h(); f.srcRect.w = f.size.w(); f.srcRect.h = f.size.h(); sprite.frames.push_back(std::move(f)); } std::string animLine; std::getline(datafile, animLine); // blank while (std::getline(datafile, animLine)) { std::regex re(R"(([a-z!_]+)\[([a-z_]+)\]: ([0-9,]+))"); std::smatch m; std::regex_match(animLine, m, re); std::string animName = m[1]; Animation anim; auto framestrs = splitStr>(m[3], ","); for (const std::string& f : framestrs) { anim.frameIndices.push_back(std::stoi(f)); } if (animName.back() == '!') { anim.looping = false; } int animId = sprite.animations.size(); sprite.animations.push_back(std::move(anim)); Direction dir = directionFromString(std::string(m[2])); sprite.nameDirToAnim[animName][dir] = animId; } updateAnimation(spriteId); } void AnimationSystem::tick(double dt) { animTimer_.accumulate(dt); while (animTimer_.step()) { for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { if (sprite.isAnimated && !sprite.animFinished) { sprite.animationFrame++; if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) { if (sprite.animations[sprite.animationId].looping) { sprite.animationFrame = 0; } else { sprite.animFinished = true; sprite.animationFrame = sprite.animations[sprite.animationId].frameIndices.size() - 1; } } } } } } void AnimationSystem::setSpriteDirection(int spriteId, Direction dir) { Sprite& sprite = game_.getSprite(spriteId); if (sprite.dir != dir) { sprite.dir = dir; updateAnimation(spriteId); } } void AnimationSystem::setSpriteAnimation(int spriteId, std::string_view name) { Sprite& sprite = game_.getSprite(spriteId); if (sprite.animationName != name) { sprite.animationName = name; updateAnimation(spriteId); } } void AnimationSystem::updateAnimation(int spriteId) { Sprite& sprite = game_.getSprite(spriteId); sprite.animationId = sprite.nameDirToAnim[sprite.animationName][sprite.dir]; sprite.animationFrame = 0; sprite.animFinished = false; }