From ce0628c5ad96e094db12a67d4e98b445fa873ad3 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 14 Feb 2021 16:13:08 -0500 Subject: Added map fadeouts Screen fadeouts and map fadeouts are now handled by the effect system. --- CMakeLists.txt | 1 + res/scripts/common.lua | 29 +++++++++++++++--------- res/scripts/map2.lua | 6 +++++ src/effect_system.cpp | 35 +++++++++++++++++++++++++++++ src/effect_system.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/game.h | 5 ----- src/main.cpp | 2 ++ src/renderer.cpp | 52 +++++++++++++++++++++++++++++++++++++++++-- src/renderer.h | 1 + src/script_system.cpp | 21 +++++++++++++----- src/system.h | 3 ++- 11 files changed, 190 insertions(+), 25 deletions(-) create mode 100644 src/effect_system.cpp create mode 100644 src/effect_system.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e5b3ad..b6d6051 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ add_executable(tanetane src/input_system.cpp src/message_system.cpp src/script_system.cpp + src/effect_system.cpp ) set_property(TARGET tanetane PROPERTY CXX_STANDARD 17) diff --git a/res/scripts/common.lua b/res/scripts/common.lua index 75b86a8..2197417 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua @@ -41,6 +41,7 @@ function StartCutscene() local playerSprite = getSprite(playerId) playerSprite.controllable = false character():halt(playerId) + message():displayCutsceneBars() end function DisplayMessage(msg, name, type) @@ -107,21 +108,27 @@ function StopSound(soundId) end function FadeToBlack(length) - local progress = 0.0 - while progress < length do - progress = progress + coroutine.yield() - setFadeoutProgress(progress / length) - end - setFadeoutProgress(1.0) + effect():fadeScreen(length, 1.0) + repeat + coroutine.yield() + until effect():isScreenFadeComplete() end function RemoveFadeout(length) - local progress = length - while progress > 0 do - progress = progress - coroutine.yield() - setFadeoutProgress(progress / length) + effect():fadeScreen(length, 0.0) + repeat + coroutine.yield() + until effect():isScreenFadeComplete() +end + +function FadeMap(length, amount) + effect():fadeMap(length, amount) +end + +function WaitForMapFade() + while not effect():isMapFadeComplete() do + coroutine.yield() end - setFadeoutProgress(0.0) end function SetPartyDirection(spriteId, direction) diff --git a/res/scripts/map2.lua b/res/scripts/map2.lua index 8058aa2..12a5df0 100644 --- a/res/scripts/map2.lua +++ b/res/scripts/map2.lua @@ -26,6 +26,9 @@ end function map2.mailbox_lightning() StartCutscene() + FadeMap(500, 0.5) + WaitForMapFade() + DisplayMessage("* ...?", "", SpeakerType.NONE) WaitForEndOfMessage() @@ -44,6 +47,9 @@ function map2.mailbox_lightning() SetAnimation("lucas", "lightning_collapse!") WaitForAnimation("lucas") + FadeMap(500, 0.0) + WaitForMapFade() + DisplayMessage("* It was lightning.\n\fAh.", "", SpeakerType.NONE) WaitForEndOfMessage() HideCutsceneBars() diff --git a/src/effect_system.cpp b/src/effect_system.cpp new file mode 100644 index 0000000..3a0afe4 --- /dev/null +++ b/src/effect_system.cpp @@ -0,0 +1,35 @@ +#include "effect_system.h" + +void EffectSystem::tick(double dt) { + if (screenFade_ != screenFadeDest_) { + screenFadeThus_ += dt; + if (screenFadeThus_ >= screenFadeLength_) { + screenFadeThus_ = screenFadeLength_; + } + + screenFade_ = (screenFadeDest_ - screenFadeStart_) / screenFadeLength_ * screenFadeThus_ + screenFadeStart_; + } + + if (mapFade_ != mapFadeDest_) { + mapFadeThus_ += dt; + if (mapFadeThus_ >= mapFadeLength_) { + mapFadeThus_ = mapFadeLength_; + } + + mapFade_ = (mapFadeDest_ - mapFadeStart_) / mapFadeLength_ * mapFadeThus_ + mapFadeStart_; + } +} + +void EffectSystem::fadeScreen(int length, double amount) { + screenFadeStart_ = screenFade_; + screenFadeDest_ = amount; + screenFadeLength_ = length; + screenFadeThus_ = 0; +} + +void EffectSystem::fadeMap(int length, double amount) { + mapFadeStart_ = mapFade_; + mapFadeDest_ = amount; + mapFadeLength_ = length; + mapFadeThus_ = 0; +} diff --git a/src/effect_system.h b/src/effect_system.h new file mode 100644 index 0000000..2cdcb10 --- /dev/null +++ b/src/effect_system.h @@ -0,0 +1,60 @@ +#ifndef EFFECT_SYSTEM_H_0B497B39 +#define EFFECT_SYSTEM_H_0B497B39 + +#include "system.h" + +class Game; + +class EffectSystem : public System { +public: + + static constexpr SystemKey Key = SystemKey::Effect; + + explicit EffectSystem(Game& game) : game_(game) {} + + void tick(double dt) override; + + /* Commands */ + + // Fades the entire screen in or out + // - length is in milliseconds + // - amount is [0,1] + void fadeScreen(int length, double amount); + + // Fades just the map, leaving the sprites, messages, etc unfaded. + // - length is in milliseconds + // - amount is [0,1] + void fadeMap(int length, double amount); + + /* Information */ + + bool isScreenFaded() const { return screenFade_ > 0.0; } + + double getScreenFadeProgress() const { return screenFade_; } + + bool isScreenFadeComplete() const { return screenFade_ == screenFadeDest_; } + + bool isMapFaded() const { return mapFade_ > 0.0; } + + double getMapFadeProgress() const { return mapFade_; } + + bool isMapFadeComplete() const { return mapFade_ == mapFadeDest_; } + +private: + + Game& game_; + + double screenFade_ = 0.0; + double screenFadeDest_ = 0.0; + double screenFadeStart_ = 0.0; + double screenFadeLength_ = 0; + double screenFadeThus_ = 0; + + double mapFade_ = 0.0; + double mapFadeDest_ = 0.0; + double mapFadeStart_ = 0.0; + double mapFadeLength_ = 0.0; + double mapFadeThus_ = 0.0; +}; + +#endif /* end of include guard: EFFECT_SYSTEM_H_0B497B39 */ diff --git a/src/game.h b/src/game.h index c7926bf..736fa7a 100644 --- a/src/game.h +++ b/src/game.h @@ -82,10 +82,6 @@ public: const Font& getFont() const { return font_; } - double getFadeoutProgress() const { return fadeout_; } - - void setFadeoutProgress(double val) { fadeout_ = val; } - private: void clearSprites(); @@ -101,7 +97,6 @@ private: std::map spritesByAlias_; std::unique_ptr map_; Font font_; - double fadeout_ = 0.0; }; #endif /* end of include guard: GAME_H_E6F1396E */ diff --git a/src/main.cpp b/src/main.cpp index 592b3be..79fa306 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ #include "input_system.h" #include "message_system.h" #include "script_system.h" +#include "effect_system.h" void loop(Renderer& renderer) { Game game(renderer); @@ -21,6 +22,7 @@ void loop(Renderer& renderer) { game.emplaceSystem(); game.emplaceSystem(); game.emplaceSystem(); + game.emplaceSystem(); game.loadMap("map2", "debugWarp_mailboxes", Direction::down); game.getSprite(game.getSpriteByAlias("lucas")).controllable = true; diff --git a/src/renderer.cpp b/src/renderer.cpp index 0e5f8f1..c80b0d3 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -6,6 +6,7 @@ #include "transform_system.h" #include "camera_system.h" #include "message_system.h" +#include "effect_system.h" Renderer::Renderer() { win_ = window_ptr( @@ -110,10 +111,22 @@ void Renderer::renderSprite(const Sprite& sprite) { } void Renderer::render(Game& game) { + auto& effects = game.getSystem(); + if (cachedMapName_ != game.getMap().getName()) { cachedMapName_ = game.getMap().getName(); renLay1_ = renderMapLayer(game.getMap(), 0); renLay0_ = renderMapLayer(game.getMap(), 1); + + vec2i mapBounds = game.getMap().getMapSize() * game.getMap().getTileSize(); + mapSwapTex_.reset(SDL_CreateTexture( + ren_.get(), + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_TARGET, + mapBounds.w(), + mapBounds.h())); + + SDL_SetTextureBlendMode(mapSwapTex_.get(), SDL_BLENDMODE_BLEND); } vec2i mapBounds = game.getMap().getMapSize() * game.getMap().getTileSize(); @@ -135,14 +148,48 @@ void Renderer::render(Game& game) { SDL_SetRenderDrawColor(ren_.get(), 255, 255, 255, 255); SDL_RenderClear(ren_.get()); + // Render lower map layer SDL_RenderCopy(ren_.get(), renLay1_.get(), nullptr, nullptr); + if (effects.isMapFaded()) { + SDL_SetRenderTarget(ren_.get(), mapSwapTex_.get()); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); + SDL_RenderClear(ren_.get()); + SDL_RenderCopy(ren_.get(), renLay1_.get(), nullptr, nullptr); + + SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_MOD); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 255); + SDL_RenderFillRect(ren_.get(), nullptr); + + SDL_SetRenderTarget(ren_.get(), canvas.get()); + SDL_SetTextureAlphaMod(mapSwapTex_.get(), effects.getMapFadeProgress() * 255); + SDL_RenderCopy(ren_.get(), mapSwapTex_.get(), nullptr, nullptr); + } + + // Render normal sprite layer for (const Sprite& sprite : game.getSystem().getSpritesByY(SpriteLayer::Normal) | game.spriteView()) { renderSprite(sprite); } + // Render upper map layer SDL_RenderCopy(ren_.get(), renLay0_.get(), nullptr, nullptr); + if (effects.isMapFaded()) { + SDL_SetRenderTarget(ren_.get(), mapSwapTex_.get()); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0); + SDL_RenderClear(ren_.get()); + SDL_RenderCopy(ren_.get(), renLay0_.get(), nullptr, nullptr); + + SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_MOD); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 255); + SDL_RenderFillRect(ren_.get(), nullptr); + + SDL_SetRenderTarget(ren_.get(), canvas.get()); + SDL_SetTextureAlphaMod(mapSwapTex_.get(), effects.getMapFadeProgress() * 255); + SDL_RenderCopy(ren_.get(), mapSwapTex_.get(), nullptr, nullptr); + } + + // Render above sprite layer for (const Sprite& sprite : game.getSystem().getSpritesByY(SpriteLayer::Above) | game.spriteView()) { renderSprite(sprite); } @@ -170,6 +217,7 @@ void Renderer::render(Game& game) { SDL_RenderCopy(ren_.get(), canvas.get(), &cameraField, nullptr); if (game.getSystem().getCutsceneBarsProgress() > 0) { + SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 255); int topBarHeight = 16.0 * game.getSystem().getCutsceneBarsProgress(); @@ -277,9 +325,9 @@ void Renderer::render(Game& game) { } } - if (game.getFadeoutProgress() > 0.0) { + if (effects.isScreenFaded()) { SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, game.getFadeoutProgress() * 255); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, effects.getScreenFadeProgress() * 255); SDL_RenderFillRect(ren_.get(), nullptr); } diff --git a/src/renderer.h b/src/renderer.h index 54dae1c..17dc038 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -145,6 +145,7 @@ private: texture_ptr tilesetTex_; texture_ptr renLay0_; texture_ptr renLay1_; + texture_ptr mapSwapTex_; // Text rendering struct MessageCache { diff --git a/src/script_system.cpp b/src/script_system.cpp index 08d66d4..7109d98 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp @@ -5,6 +5,7 @@ #include "animation_system.h" #include "character_system.h" #include "transform_system.h" +#include "effect_system.h" #include "vector.h" ScriptSystem::ScriptSystem(Game& game) : game_(game) { @@ -31,6 +32,7 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { "message", "displayMessage", &MessageSystem::displayMessage, "showChoice", &MessageSystem::showChoice, + "displayCutsceneBars", &MessageSystem::displayCutsceneBars, "hideCutsceneBars", &MessageSystem::hideCutsceneBars, "isMessageActive", sol::property(&MessageSystem::isMessageActive), "getChoiceSelection", &MessageSystem::getChoiceSelection); @@ -52,6 +54,13 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { transform.initSprite(spriteId, vec2i{x, y}, layer); }); + engine_.new_usertype( + "effect", + "fadeScreen", &EffectSystem::fadeScreen, + "isScreenFadeComplete", &EffectSystem::isScreenFadeComplete, + "fadeMap", &EffectSystem::fadeMap, + "isMapFadeComplete", &EffectSystem::isMapFadeComplete); + engine_.new_usertype( "mixer", "playSound", &Mixer::playSound, @@ -82,6 +91,12 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { return game_.getSystem(); }); + engine_.set_function( + "effect", + [&] () -> EffectSystem& { + return game_.getSystem(); + }); + engine_.set_function( "mixer", [&] () -> Mixer& { @@ -130,12 +145,6 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { game_.loadMap(filename, warpPoint, dir); }); - engine_.set_function( - "setFadeoutProgress", - [&] (double val) { - game_.setFadeoutProgress(val); - }); - engine_.script_file("../res/scripts/common.lua"); } diff --git a/src/system.h b/src/system.h index 3e84537..0cdc205 100644 --- a/src/system.h +++ b/src/system.h @@ -2,13 +2,14 @@ #define SYSTEM_H_6B40E1B9 enum class SystemKey { + Script, Transform, Input, Character, Animation, Camera, Message, - Script + Effect }; class System { -- cgit 1.4.1