From 7e3b59b09399bf8da243fb4122caa2c9c10d2624 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Fri, 5 Mar 2021 09:39:31 -0500 Subject: Implemented circle transition effect (for exit area) --- src/effect_system.cpp | 16 +++++++++++++++ src/effect_system.h | 17 ++++++++++++++++ src/renderer.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/script_system.cpp | 4 +++- 4 files changed, 90 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/effect_system.cpp b/src/effect_system.cpp index aeccebb..4dff13c 100644 --- a/src/effect_system.cpp +++ b/src/effect_system.cpp @@ -37,6 +37,15 @@ void EffectSystem::tick(double dt) { cameraShakeOffset_.y() = 0; } } + + if (circleEffect_ != circleEffectDest_) { + circleEffectThus_ += dt; + if (circleEffectThus_ >= circleEffectLength_) { + circleEffectThus_ = circleEffectLength_; + } + + circleEffect_ = (circleEffectDest_ - circleEffectStart_) / circleEffectLength_ * circleEffectThus_ + circleEffectStart_; + } } void EffectSystem::fadeScreen(int length, double amount) { @@ -64,3 +73,10 @@ void EffectSystem::stopShakingCamera() { cameraShaking_ = false; cameraShakeOffset_ = { 0, 0 }; } + +void EffectSystem::circleTransition(int length, double amount) { + circleEffectStart_ = circleEffect_; + circleEffectDest_ = amount; + circleEffectLength_ = length; + circleEffectThus_ = 0; +} diff --git a/src/effect_system.h b/src/effect_system.h index 12ec7ca..904e6cb 100644 --- a/src/effect_system.h +++ b/src/effect_system.h @@ -34,6 +34,11 @@ public: void stopShakingCamera(); + // Hides or reveals the screen using a circle transition. + // - length is the time in milliseconds + // - amount is [0,1], where 0 is fully revealed and 1 is fully hidden + void circleTransition(int length, double amount); + /* Information */ bool isScreenFaded() const { return screenFade_ > 0.0; } @@ -52,6 +57,12 @@ public: bool isCameraShaking() const { return cameraShaking_; } + bool isCircleTransitionActive() const { return circleEffect_ > 0.0; } + + double getCircleTransitionProgress() const { return circleEffect_; } + + bool isCircleTransitionComplete() const { return circleEffect_ == circleEffectDest_; } + private: Game& game_; @@ -72,6 +83,12 @@ private: vec2i cameraShakeOffset_ { 0, 0 }; bool cameraShakeOn_ = false; Timer cameraShakeTimer_ { 0 }; + + double circleEffect_ = 0.0; + double circleEffectDest_ = 0.0; + double circleEffectStart_ = 0.0; + double circleEffectLength_ = 0.0; + double circleEffectThus_ = 0.0; }; #endif /* end of include guard: EFFECT_SYSTEM_H_0B497B39 */ diff --git a/src/renderer.cpp b/src/renderer.cpp index 3007378..5ab623a 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -353,6 +353,60 @@ void Renderer::render(Game& game) { SDL_RenderFillRect(ren_.get(), nullptr); } + if (effects.isCircleTransitionActive()) { + if (effects.getCircleTransitionProgress() == 1.0) { + SDL_SetRenderTarget(ren_.get(), cameraTex.get()); + SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 255); + SDL_RenderClear(ren_.get()); + } else { + texture_ptr circleEffectTex( + SDL_CreateTexture( + ren_.get(), + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_TARGET, + CANVAS_WIDTH, + CANVAS_HEIGHT)); + + if (!circleEffectTex) { + throw sdl_error(); + } + + SDL_SetRenderTarget(ren_.get(), circleEffectTex.get()); + SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 255); + SDL_RenderClear(ren_.get()); + + int circleDiameter = 290 * (1.0 - effects.getCircleTransitionProgress()); + SDL_Rect circleSize { + CANVAS_WIDTH / 2 - circleDiameter / 2, + CANVAS_HEIGHT / 2 - circleDiameter / 2, + circleDiameter, + circleDiameter + }; + + SDL_Rect copyFromCamera = circleSize; + if (circleDiameter > CANVAS_WIDTH) { + copyFromCamera.x = 0; + copyFromCamera.w = CANVAS_WIDTH; + } + if (circleDiameter > CANVAS_HEIGHT) { + copyFromCamera.y = 0; + copyFromCamera.h = CANVAS_HEIGHT; + } + + SDL_RenderCopy(ren_.get(), cameraTex.get(), ©FromCamera, ©FromCamera); + + int pinholeTexId = loadImageFromFile("../res/pinhole.png"); + SDL_SetTextureBlendMode(textures_[pinholeTexId].get(), SDL_BLENDMODE_MOD); + SDL_RenderCopy(ren_.get(), textures_[pinholeTexId].get(), nullptr, &circleSize); + + SDL_SetRenderTarget(ren_.get(), cameraTex.get()); + SDL_SetTextureBlendMode(circleEffectTex.get(), SDL_BLENDMODE_NONE); + SDL_RenderCopy(ren_.get(), circleEffectTex.get(), nullptr, nullptr); + } + } + if (game.getSystem().isDebugConsoleOpen()) { // Not sure why I'm supposed to copy the cached texture to the screen // BEFORE rendering it, but we get flickering if we don't, so. diff --git a/src/script_system.cpp b/src/script_system.cpp index a3686b4..3325b79 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp @@ -89,7 +89,9 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { "fadeMap", &EffectSystem::fadeMap, "isMapFadeComplete", &EffectSystem::isMapFadeComplete, "shakeCamera", &EffectSystem::shakeCamera, - "stopShakingCamera", &EffectSystem::stopShakingCamera); + "stopShakingCamera", &EffectSystem::stopShakingCamera, + "circleTransition", &EffectSystem::circleTransition, + "isCircleTransitionComplete", &EffectSystem::isCircleTransitionComplete); engine_.new_usertype( "camera", -- cgit 1.4.1