From ed933607765a6e010689aaaf85184053ff6e8a2b Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sat, 13 Feb 2021 12:14:58 -0500 Subject: Added non-looping animations Lucas can get electrocuted now. --- res/maps/map2.tmx | 8 +++++++- res/scripts/common.lua | 13 +++++++++++++ res/scripts/map2.lua | 14 ++++++++++++++ res/sprites/lucas_anim.txt | 3 ++- src/animation_system.cpp | 29 +++++++++++++++++++++-------- src/renderer.cpp | 2 +- src/script_system.cpp | 3 ++- src/sprite.h | 8 +++++++- 8 files changed, 67 insertions(+), 13 deletions(-) diff --git a/res/maps/map2.tmx b/res/maps/map2.tmx index ee9931c..6316ef5 100644 --- a/res/maps/map2.tmx +++ b/res/maps/map2.tmx @@ -1,5 +1,5 @@ - + @@ -651,6 +651,12 @@ + + + + + + diff --git a/res/scripts/common.lua b/res/scripts/common.lua index 3c412c6..3db1b26 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua @@ -59,11 +59,24 @@ function HideCutsceneBars() playerSprite.controllable = true end +function SetDirection(spriteName, dir) + local spriteId = getSpriteByAlias(spriteName) + animation():setSpriteDirection(spriteId, dir) +end + function SetAnimation(spriteName, animName) local spriteId = getSpriteByAlias(spriteName) animation():setSpriteAnimation(spriteId, animName) end +function WaitForAnimation(spriteName) + local spriteId = getSpriteByAlias(spriteName) + local sprite = getSprite(spriteId) + repeat + coroutine.yield() + until sprite.animFinished +end + function PlaySound(filename) mixer():playSound("../res/sfx/" .. filename) end diff --git a/res/scripts/map2.lua b/res/scripts/map2.lua index 1b55072..3bc9eff 100644 --- a/res/scripts/map2.lua +++ b/res/scripts/map2.lua @@ -23,3 +23,17 @@ function map2.mailbox1() HideCutsceneBars() end + +function map2.mailbox_lightning() + StartCutscene() + DisplayMessage("* ...?", "", SpeakerType.NONE) + WaitForEndOfMessage() + + SetDirection("lucas", Direction.DOWN) + SetAnimation("lucas", "electrocute!") + WaitForAnimation("lucas") + + DisplayMessage("* It was lightning.\n\fAh.", "", SpeakerType.NONE) + WaitForEndOfMessage() + HideCutsceneBars() +end diff --git a/res/sprites/lucas_anim.txt b/res/sprites/lucas_anim.txt index 455c321..12a373e 100644 --- a/res/sprites/lucas_anim.txt +++ b/res/sprites/lucas_anim.txt @@ -31,4 +31,5 @@ run[up_left]: 70,78,86,94 run[up]: 71,79,87,95 run[up_right]: 72,80,88,96 run[right]: 73,81,89,97 -run[down_right]: 74,82,90,98 \ No newline at end of file +run[down_right]: 74,82,90,98 +electrocute![down]: 116,117,118,116,117,118,116,117,118,119,120,121,122 \ No newline at end of file diff --git a/src/animation_system.cpp b/src/animation_system.cpp index 997b7f7..3f3f22a 100644 --- a/src/animation_system.cpp +++ b/src/animation_system.cpp @@ -65,21 +65,26 @@ void AnimationSystem::initSprite(int spriteId, std::string_view filename) { std::string animLine; std::getline(datafile, animLine); // blank while (std::getline(datafile, animLine)) { - std::regex re(R"(([a-z]+)\[([a-z_]+)\]: ([0-9,]+))"); + std::regex re(R"(([a-z!]+)\[([a-z_]+)\]: ([0-9,]+))"); std::smatch m; std::regex_match(animLine, m, re); - std::vector frames; + std::string animName = m[1]; + Animation anim; auto framestrs = splitStr>(m[3], ","); for (const std::string& f : framestrs) { - frames.push_back(std::stoi(f)); + anim.frameIndices.push_back(std::stoi(f)); + } + + if (animName.back() == '!') { + anim.looping = false; } int animId = sprite.animations.size(); - sprite.animations.push_back(std::move(frames)); + sprite.animations.push_back(std::move(anim)); Direction dir = directionFromString(std::string(m[2])); - sprite.nameDirToAnim[m[1]][dir] = animId; + sprite.nameDirToAnim[animName][dir] = animId; } updateAnimation(spriteId); @@ -89,10 +94,17 @@ void AnimationSystem::tick(double dt) { animTimer_.accumulate(dt); while (animTimer_.step()) { for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { - if (sprite.isAnimated) { + if (sprite.isAnimated && !sprite.animFinished) { sprite.animationFrame++; - if (sprite.animationFrame >= sprite.animations[sprite.animationId].size()) { - sprite.animationFrame = 0; + if (sprite.animations[sprite.animationId].looping) { + if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) { + sprite.animationFrame = 0; + } + } else { + if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size() - 1) { + sprite.animationFrame = sprite.animations[sprite.animationId].frameIndices.size() - 1; + sprite.animFinished = true; + } } } } @@ -119,4 +131,5 @@ void AnimationSystem::updateAnimation(int spriteId) { Sprite& sprite = game_.getSprite(spriteId); sprite.animationId = sprite.nameDirToAnim[sprite.animationName][sprite.dir]; sprite.animationFrame = 0; + sprite.animFinished = false; } diff --git a/src/renderer.cpp b/src/renderer.cpp index f07931b..a7169e9 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -130,7 +130,7 @@ void Renderer::render(Game& game) { SDL_RenderCopy(ren_.get(), textures_.at(shadowTexId).get(), nullptr, &shadowDest); } - const SpriteFrame& frame = sprite.frames.at(sprite.animations.at(sprite.animationId).at(sprite.animationFrame)); + const SpriteFrame& frame = sprite.frames.at(sprite.animations.at(sprite.animationId).frameIndices.at(sprite.animationFrame)); const SDL_Rect& src = frame.srcRect; SDL_Rect dest { sprite.loc.x() - frame.center.x(), sprite.loc.y() - frame.center.y(), frame.size.w(), frame.size.h() }; SDL_RenderCopy(ren_.get(), textures_.at(loadImageFromFile(sprite.spritesheet)).get(), &src, &dest); diff --git a/src/script_system.cpp b/src/script_system.cpp index 5b9b987..3f89290 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp @@ -16,7 +16,8 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { "dir", &Sprite::dir, "followers", &Sprite::followers, "characterState", &Sprite::characterState, - "controllable", &Sprite::controllable); + "controllable", &Sprite::controllable, + "animFinished", &Sprite::animFinished); engine_.new_usertype( "message", diff --git a/src/sprite.h b/src/sprite.h index 84a7b03..fcf7e1d 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -16,6 +16,11 @@ struct SpriteFrame { vec2i size; }; +struct Animation { + bool looping = true; + std::vector frameIndices; +}; + enum class CharacterState { Still, Walking, @@ -48,8 +53,9 @@ public: int animationId = 0; int animationFrame = 0; std::vector frames; - std::vector> animations; + std::vector animations; std::map> nameDirToAnim; + bool animFinished = false; bool hasShadow = false; // Character -- cgit 1.4.1