From a645524d19bb9183d4eece72bf8945bba4bed3a0 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 16 Feb 2021 22:03:10 -0500 Subject: Added scriptable camera panning --- res/scripts/common.lua | 23 ++++++++++++++++++ res/scripts/map2.lua | 19 ++++++++++++++- src/camera_system.cpp | 63 +++++++++++++++++++++++++++++++++++++++----------- src/camera_system.h | 16 +++++++++++++ src/script_system.cpp | 14 +++++++++++ 5 files changed, 120 insertions(+), 15 deletions(-) diff --git a/res/scripts/common.lua b/res/scripts/common.lua index caab86a..f88c4c1 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua @@ -141,6 +141,29 @@ function StopShakingCamera() effect():stopShakingCamera() end +function PanToSprite(spriteName, length) + local spriteId = getSpriteByAlias(spriteName) + camera():panToSprite(spriteId, length) +end + +function WaitForPan() + while camera():isPanning() do + coroutine.yield() + end +end + +function ReturnCamera(length) + local playerId = getPlayerSprite() + camera():panToSprite(playerId, length) + + while camera():isPanning() do + coroutine.yield() + end + + camera():setFollowingSprite(playerId) + camera():unlockCamera() +end + function SetPartyDirection(spriteId, direction) animation():setSpriteDirection(spriteId, direction) diff --git a/res/scripts/map2.lua b/res/scripts/map2.lua index 92c1747..c929e8d 100644 --- a/res/scripts/map2.lua +++ b/res/scripts/map2.lua @@ -74,9 +74,26 @@ function map2.approach_doria() gamestate.approached_doria = true StartCutscene() + PanToSprite("doria", 2000) + WaitForPan() + SetDirection("doria", Direction.DOWN_RIGHT) SetAnimation("doria", "talk") - DisplayMessage("* Oh my!\n* Is that our little Kumatora I spy? `\n* Such style! Such swagger!\nWhy, just as if she were Magifolk herself! `\n* When Ionia showed us the human she was looking after, I hardly knew what to think.", "Doria", SpeakerType.MAN) + DisplayMessage("* Oh my!\n\f* Is that our little Kumatora I spy? `", "Doria", SpeakerType.MAN) + WaitForEndOfMessage() + + SetAnimation("doria", "still") + ReturnCamera(2000) + Delay(1000) + SetAnimation("kuma", "talk") + DisplayMessage("* Doria...?\n\f* What the hell... You're still alive?", "Kumatora", SpeakerType.WOMAN) + WaitForEndOfMessage() + + SetAnimation("kuma", "still") + Delay(1000) + + SetAnimation("doria", "talk") + DisplayMessage("* It is! It is her!\n\f* Such style! Such swagger!\nWhy, just as if she were Magifolk herself! `\n* When Ionia showed us the human she was looking after, I hardly knew what to think.", "Doria", SpeakerType.MAN) WaitForEndOfMessage() SetDirection("doria", Direction.DOWN) diff --git a/src/camera_system.cpp b/src/camera_system.cpp index b7627b1..2d7be61 100644 --- a/src/camera_system.cpp +++ b/src/camera_system.cpp @@ -6,26 +6,39 @@ void CameraSystem::tick(double dt) { if (!locked_ && followingSprite_ != -1) { const Sprite& follow = game_.getSprite(followingSprite_); - const Map& map = game_.getMap(); - vec2i mapBounds = map.getMapSize() * map.getTileSize(); - pos_ = follow.loc - vec2i{0, 16} - (fov_ / 2); + pos_ = calculatePosWithCenter(follow.loc - vec2i{0, 16}); + } - if (pos_.x() < 0) { - pos_.x() = 0; - } - if (pos_.y() < 0) { - pos_.y() = 0; - } - if (pos_.x() + fov_.w() >= mapBounds.w()) { - pos_.x() = mapBounds.w() - fov_.w() - 1; - } - if (pos_.y() + fov_.h() >= mapBounds.h()) { - pos_.y() = mapBounds.h() - fov_.h() - 1; + if (panning_) { + panThus_ += dt; + + if (panThus_ >= panLength_) { + panning_ = false; + pos_ = panEnd_; + } else { + pos_.x() = static_cast((panEnd_ - panStart_).x()) / panLength_ * panThus_ + panStart_.x(); + pos_.y() = static_cast((panEnd_ - panStart_).y()) / panLength_ * panThus_ + panStart_.y(); } } } +void CameraSystem::panToSprite(int targetId, int length) { + locked_ = true; + + const Sprite& target = game_.getSprite(targetId); + + if (length > 0) { + panning_ = true; + panStart_ = pos_; + panEnd_ = calculatePosWithCenter(target.loc - vec2i{0, 16}); + panLength_ = length; + panThus_ = 0.0; + } else { + pos_ = calculatePosWithCenter(target.loc - vec2i{0, 16}); + } +} + void CameraSystem::destroySprite(int spriteId) { if (followingSprite_ == spriteId) { followingSprite_ = -1; @@ -35,3 +48,25 @@ void CameraSystem::destroySprite(int spriteId) { void CameraSystem::clearSpriteCache() { followingSprite_ = -1; } + +vec2i CameraSystem::calculatePosWithCenter(vec2i center) const { + const Map& map = game_.getMap(); + vec2i mapBounds = map.getMapSize() * map.getTileSize(); + + vec2i result = center - (fov_ / 2); + + if (result.x() < 0) { + result.x() = 0; + } + if (result.y() < 0) { + result.y() = 0; + } + if (result.x() + fov_.w() >= mapBounds.w()) { + result.x() = mapBounds.w() - fov_.w() - 1; + } + if (result.y() + fov_.h() >= mapBounds.h()) { + result.y() = mapBounds.h() - fov_.h() - 1; + } + + return result; +} diff --git a/src/camera_system.h b/src/camera_system.h index 37ff8b4..a2dee93 100644 --- a/src/camera_system.h +++ b/src/camera_system.h @@ -24,6 +24,13 @@ public: void unlockCamera() { locked_ = false; } + // Pans over to the provided sprite over the provided amount of time. + // - length is in milliseconds + // Automatically locks the camera. + void panToSprite(int targetId, int length); + + bool isPanning() const { return panning_; } + void tick(double dt) override; void destroySprite(int spriteId) override; @@ -31,12 +38,21 @@ public: void clearSpriteCache() override; private: + + vec2i calculatePosWithCenter(vec2i center) const; + Game& game_; vec2i pos_; vec2i fov_ { CANVAS_WIDTH, CANVAS_HEIGHT }; int followingSprite_ = -1; bool locked_ = true; + + bool panning_ = false; + vec2i panStart_; + vec2i panEnd_; + double panLength_ = 0.0; + double panThus_ = 0.0; }; #endif /* end of include guard: CAMERA_SYSTEM_H_D52ADAD3 */ diff --git a/src/script_system.cpp b/src/script_system.cpp index cbbd473..3ac04ac 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp @@ -6,6 +6,7 @@ #include "character_system.h" #include "transform_system.h" #include "effect_system.h" +#include "camera_system.h" #include "vector.h" ScriptSystem::ScriptSystem(Game& game) : game_(game) { @@ -63,6 +64,13 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { "shakeCamera", &EffectSystem::shakeCamera, "stopShakingCamera", &EffectSystem::stopShakingCamera); + engine_.new_usertype( + "camera", + "panToSprite", &CameraSystem::panToSprite, + "isPanning", &CameraSystem::isPanning, + "unlockCamera", &CameraSystem::unlockCamera, + "setFollowingSprite", &CameraSystem::setFollowingSprite); + engine_.new_usertype( "mixer", "playSound", &Mixer::playSound, @@ -99,6 +107,12 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { return game_.getSystem(); }); + engine_.set_function( + "camera", + [&] () -> CameraSystem& { + return game_.getSystem(); + }); + engine_.set_function( "mixer", [&] () -> Mixer& { -- cgit 1.4.1