From 7fa5227f4233cd76dd0b5659214cc238d4bb37a2 Mon Sep 17 00:00:00 2001 From: falsycat <me@falsy.cat> Date: Sat, 28 Aug 2021 13:27:42 +0900 Subject: [PATCH] Adds LoadScene. --- GlyphsJuke.vcxproj | 2 ++ GlyphsJuke.vcxproj.filters | 6 +++++ src/ElementStore.h | 12 +++------ src/GlyphElementFactory.h | 2 +- src/LoadScene.cc | 26 ++++++++++++++++++++ src/LoadScene.h | 50 ++++++++++++++++++++++++++++++++++++++ src/Lua.h | 15 +++++++++--- src/PlayScene.cc | 26 ++++++++++++-------- src/PlayScene.h | 8 +++++- src/TitleScene.cc | 33 ++++++++++++++----------- src/TitleScene.h | 6 ++--- 11 files changed, 146 insertions(+), 40 deletions(-) create mode 100644 src/LoadScene.cc create mode 100644 src/LoadScene.h diff --git a/GlyphsJuke.vcxproj b/GlyphsJuke.vcxproj index f347d0e..c3ed4b3 100644 --- a/GlyphsJuke.vcxproj +++ b/GlyphsJuke.vcxproj @@ -150,6 +150,7 @@ <ClCompile Include="src\Font.cc" /> <ClCompile Include="src\Game.cc" /> <ClCompile Include="src\HiraganaMatcher.cc" /> + <ClCompile Include="src\LoadScene.cc" /> <ClCompile Include="src\Lua.cc" /> <ClCompile Include="src\main.cc" /> <ClCompile Include="src\PlayScene.cc" /> @@ -177,6 +178,7 @@ <ClInclude Include="src\InputWindowElementFactory.h" /> <ClInclude Include="src\iScene.h" /> <ClInclude Include="src\iWritable.h" /> + <ClInclude Include="src\LoadScene.h" /> <ClInclude Include="src\Logger.h" /> <ClInclude Include="src\Lua.h" /> <ClInclude Include="src\Music.h" /> diff --git a/GlyphsJuke.vcxproj.filters b/GlyphsJuke.vcxproj.filters index 4afac60..31ffc11 100644 --- a/GlyphsJuke.vcxproj.filters +++ b/GlyphsJuke.vcxproj.filters @@ -51,6 +51,9 @@ <ClCompile Include="src\TitleScene.cc"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\LoadScene.cc"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="src\iConsole.h"> @@ -215,6 +218,9 @@ <ClInclude Include="src\Music.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="src\LoadScene.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Library Include="thirdparty\lua5.1.lib" /> diff --git a/src/ElementStore.h b/src/ElementStore.h index 70eac24..5996912 100644 --- a/src/ElementStore.h +++ b/src/ElementStore.h @@ -15,13 +15,13 @@ class ElementStore { public: ElementStore() = delete; - ElementStore(ElementStore&&) = delete; + ElementStore(ElementStore&&) = default; ElementStore(const ElementStore&) = delete; - ElementStore& operator=(ElementStore&&) = delete; + ElementStore& operator=(ElementStore&&) = default; ElementStore& operator=(const ElementStore&) = delete; - ElementStore(iClock* clock, size_t reserve) : clock_(clock) { + ElementStore(size_t reserve) { pending_.reserve(reserve); performing_.reserve(reserve); } @@ -35,9 +35,7 @@ class ElementStore { pending_.insert(insert_pos, std::move(e)); } - void Update(Frame& frame) { - const uint64_t now = clock_->now(); - + void Update(Frame& frame, uint64_t now) { auto pending_beg = pending_.begin(); auto pending_end = pending_.end(); auto pending_itr = pending_beg; @@ -83,8 +81,6 @@ class ElementStore { } private: - const iClock* clock_; - std::vector<UniqPtr<iElement>> pending_; std::vector<UniqPtr<iElement>> performing_; }; diff --git a/src/GlyphElementFactory.h b/src/GlyphElementFactory.h index 1b07633..4abf8f3 100644 --- a/src/GlyphElementFactory.h +++ b/src/GlyphElementFactory.h @@ -27,7 +27,7 @@ class GlyphElementFactory : public iElementFactory { const std::string text = std::get<std::string>(param.custom[0]); const std::string name = std::get<std::string>(param.custom[1]); - const intmax_t size = std::get<double>(param.custom[2]); + const uint32_t size = static_cast<uint32_t>(std::get<double>(param.custom[2])); auto& font = FindOrCreateFont(name); auto tex = std::move(font.RenderGlyphs(ConvertStrToWstr(text), size)); /* TODO */ diff --git a/src/LoadScene.cc b/src/LoadScene.cc new file mode 100644 index 0000000..d9b9be1 --- /dev/null +++ b/src/LoadScene.cc @@ -0,0 +1,26 @@ +#include "LoadScene.h" + +#include "common.h" + + +gj::LoadScene::LoadScene(Param&& p) : + alloc_(p.super.alloc), clock_(p.super.clock), loading_(L"Loading...") { + prod_ = p.super.alloc->MakeUniq<PlayScene>(p.super, p.title, p.path); + orphan_ = std::move(p.orphan); +} + +gj::UniqPtr<gj::iScene> gj::LoadScene::Update(Frame& frame) { + if (prod_->HasPrepared() && !(orphan_ && orphan_->IsBusy())) { + prod_->Start(); + return UniqPtr<iScene>(prod_.release(), iAllocator::Deleter<iScene>(alloc_)); + } + + const uint64_t now = clock_->now(); + + if (XorShift(now+1)%10) { + loading_.SetPosition((frame.w - loading_.width())/2, frame.h/2); + frame.Add(&loading_); + } + + return nullptr; +} \ No newline at end of file diff --git a/src/LoadScene.h b/src/LoadScene.h new file mode 100644 index 0000000..c8b1d70 --- /dev/null +++ b/src/LoadScene.h @@ -0,0 +1,50 @@ +#pragma once + +#include <string> + +#include "iAllocator.h" +#include "iClock.h" +#include "iScene.h" +#include "Music.h" +#include "PlayScene.h" +#include "Text.h" + +namespace gj { + + +class LoadScene : public iScene { + public: + struct Param { + iScene::Param super; + + std::string title; + std::string path; + + /* 'orphan' is an instance of Music that couldn't be deleted + * at previous scene because it was busy. */ + UniqPtr<Music> orphan; + }; + + LoadScene() = delete; + LoadScene(LoadScene&&) = delete; + LoadScene(const LoadScene&) = delete; + + LoadScene& operator=(LoadScene&&) = delete; + LoadScene& operator=(const LoadScene&) = delete; + + LoadScene(Param&& p); + + UniqPtr<iScene> Update(Frame& frame) override; + + private: + iAllocator* alloc_; + const iClock* clock_; + + UniqPtr<PlayScene> prod_; + UniqPtr<Music> orphan_; + + Text loading_; +}; + + +} \ No newline at end of file diff --git a/src/Lua.h b/src/Lua.h index db2af2e..d0f9259 100644 --- a/src/Lua.h +++ b/src/Lua.h @@ -19,16 +19,25 @@ class Lua { using FactoryMap = std::map<std::string, iElementFactory*>; Lua() = delete; - Lua(Lua&&) = delete; Lua(const Lua&) = delete; - Lua& operator=(Lua&&) = delete; Lua& operator=(const Lua&) = delete; + + Lua(Lua&& src) noexcept : L(src.L) { + src.L = nullptr; + } + Lua& operator=(Lua&& src) noexcept { + if (&src != this) { + L = src.L; + src.L = nullptr; + } + return *this; + } Lua(iAllocator* alloc, ElementStore* store, const FactoryMap& factory, const std::string& path); ~Lua() { - lua_close(L); + if (L) lua_close(L); } private: diff --git a/src/PlayScene.cc b/src/PlayScene.cc index dd927aa..ddd04c0 100644 --- a/src/PlayScene.cc +++ b/src/PlayScene.cc @@ -7,8 +7,17 @@ #include "ResultScene.h" +gj::UniqPtr<gj::iScene> gj::PlayScene::Update(Frame& f) { + if (store_.IsEmpty()) { + return param_.alloc->MakeUniq<iScene, ResultScene>(param_, sb_); + } + + store_.Update(f, clock_.now()); + return nullptr; +} + gj::PlayScene::PlayScene(const Param& p, const std::string& title, const std::string& path) : - param_(p), clock_(p.clock), store_(&clock_, 256) { + param_(p), clock_(p.clock), store_(256) { GlyphElementFactory glyph(p.alloc); InputWindowElementFactory inputWin(p.alloc, &sb_); @@ -21,16 +30,13 @@ gj::PlayScene::PlayScene(const Param& p, const std::string& title, const std::st { "InputWin", &inputWin }, { "Music", &music }, }; - lua_ = p.alloc->MakeUniq<Lua>( - p.alloc, &store_, map, path); + lua_ = p.alloc->MakeUniq<Lua>(p.alloc, &store_, map, path); } +void gj::PlayScene::Start() { + clock_ = OffsetClock(param_.clock); +} -gj::UniqPtr<gj::iScene> gj::PlayScene::Update(Frame& f) { - if (store_.IsEmpty()) { - return param_.alloc->MakeUniq<iScene, ResultScene>(param_, sb_); - } - - store_.Update(f); - return nullptr; +bool gj::PlayScene::HasPrepared() const { + return store_.CountPreparings() == 0; } \ No newline at end of file diff --git a/src/PlayScene.h b/src/PlayScene.h index 9332a9f..e31c956 100644 --- a/src/PlayScene.h +++ b/src/PlayScene.h @@ -1,5 +1,6 @@ #pragma once +#include <string> #include "ElementStore.h" #include "iScene.h" @@ -13,6 +14,8 @@ namespace gj { class PlayScene : public iScene { public: + friend class LoadScene; + PlayScene() = delete; PlayScene(PlayScene&&) = delete; PlayScene(const PlayScene&) = delete; @@ -21,10 +24,13 @@ class PlayScene : public iScene { PlayScene& operator=(const PlayScene&) = delete; PlayScene(const Param& p, const std::string& title, const std::string& path); - + UniqPtr<iScene> Update(Frame& f) override; private: + void Start(); + bool HasPrepared() const; + Param param_; OffsetClock clock_; diff --git a/src/TitleScene.cc b/src/TitleScene.cc index 45a6f4b..4727f86 100644 --- a/src/TitleScene.cc +++ b/src/TitleScene.cc @@ -10,12 +10,12 @@ #include "common.h" #include "Font.h" -#include "PlayScene.h" +#include "LoadScene.h" gj::TitleScene::TitleScene(const Param& p) : param_(p), - score_(L"penguin: you didn't see anything..."), + title_(L"penguin: you didn't see anything..."), next_(L"> L"), prev_(L"H <"), guide_(L"H:PREV / SPACE:PLAY / L:NEXT"), logo_(Colorbuffer(p.alloc, 1, 1)) { @@ -35,11 +35,10 @@ gj::TitleScene::TitleScene(const Param& p) : auto& obj = e.get<::picojson::object>(); Score s; - - s.displayName = obj["displayName"].get<std::string>(); - s.music = obj["music"].get<std::string>(); - s.score = obj["score"].get<std::string>(); - s.playOffset = obj["playOffset"].get<double>(); + s.title = obj["title"].get<std::string>(); + s.music = obj["music"].get<std::string>(); + s.path = obj["path"].get<std::string>(); + s.playOffset = obj["playOffset"].get<double>(); list_.push_back(s); } @@ -56,16 +55,22 @@ gj::UniqPtr<gj::iScene> gj::TitleScene::Update(Frame& frame) { /* input handling */ for (const auto c : frame.input) { switch (c) { + case ' ': { + if (music_) param_.audio->RemoveEffect(music_.get()); + const auto& s = list_[select_index_]; + LoadScene::Param param; + param.super = param_; + param.path = s.path; + param.title = s.title; + param.orphan = std::move(music_); + return param_.alloc->MakeUniq<iScene, LoadScene>(std::move(param)); + } case 'h': SelectScore_(select_index_? select_index_-1: list_.size()-1); break; case 'l': SelectScore_((select_index_+1)%list_.size()); break; - case ' ': - if (music_) param_.audio->RemoveEffect(music_.get()); - return param_.alloc->MakeUniq<iScene, PlayScene>( - param_, list_[select_index_].displayName, list_[select_index_].score); } } @@ -126,8 +131,8 @@ gj::UniqPtr<gj::iScene> gj::TitleScene::Update(Frame& frame) { prev_.SetPosition(static_cast<int32_t>(w*.2), selector_y); frame.Add(&prev_); - score_.SetPosition((w-score_.width())/2, selector_y); - frame.Add(&score_); + title_.SetPosition((w-title_.width())/2, selector_y); + frame.Add(&title_); guide_.SetPosition((w-guide_.width())/2, selector_y+3); frame.Add(&guide_); @@ -141,7 +146,7 @@ gj::UniqPtr<gj::iScene> gj::TitleScene::Update(Frame& frame) { void gj::TitleScene::SelectScore_(size_t index) { const auto& s = list_[index]; - score_ = Text(ConvertStrToWstr(s.displayName)); + title_ = Text(ConvertStrToWstr(s.title)); select_index_ = index; trying_play_ = true; diff --git a/src/TitleScene.h b/src/TitleScene.h index 9a2d0b6..acf695a 100644 --- a/src/TitleScene.h +++ b/src/TitleScene.h @@ -27,15 +27,15 @@ class TitleScene : public iScene { private: struct Score { - std::string displayName; - std::string score; + std::string title; + std::string path; std::string music; double playOffset = 0; }; Param param_; - Text score_; + Text title_; Text next_; Text prev_; Text guide_;