Enhances audio effects.Adds TitleScene.
This commit is contained in:
parent
ea6fbd572e
commit
55b64ffa45
@ -155,6 +155,7 @@
|
|||||||
<ClCompile Include="src\PlayScene.cc" />
|
<ClCompile Include="src\PlayScene.cc" />
|
||||||
<ClCompile Include="src\ResultScene.cc" />
|
<ClCompile Include="src\ResultScene.cc" />
|
||||||
<ClCompile Include="src\Texture.cc" />
|
<ClCompile Include="src\Texture.cc" />
|
||||||
|
<ClCompile Include="src\TitleScene.cc" />
|
||||||
<ClCompile Include="src\Win32Console.cc" />
|
<ClCompile Include="src\Win32Console.cc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -183,6 +184,7 @@
|
|||||||
<ClInclude Include="src\OffsetClock.h" />
|
<ClInclude Include="src\OffsetClock.h" />
|
||||||
<ClInclude Include="src\Period.h" />
|
<ClInclude Include="src\Period.h" />
|
||||||
<ClInclude Include="src\PlayScene.h" />
|
<ClInclude Include="src\PlayScene.h" />
|
||||||
|
<ClInclude Include="src\GlitchPosteffect.h" />
|
||||||
<ClInclude Include="src\Rasterbuffer.h" />
|
<ClInclude Include="src\Rasterbuffer.h" />
|
||||||
<ClInclude Include="src\iConsole.h" />
|
<ClInclude Include="src\iConsole.h" />
|
||||||
<ClInclude Include="src\iAllocator.h" />
|
<ClInclude Include="src\iAllocator.h" />
|
||||||
@ -197,6 +199,7 @@
|
|||||||
<ClInclude Include="src\Texture.h" />
|
<ClInclude Include="src\Texture.h" />
|
||||||
<ClInclude Include="src\TextureElement.h" />
|
<ClInclude Include="src\TextureElement.h" />
|
||||||
<ClInclude Include="src\TickingClock.h" />
|
<ClInclude Include="src\TickingClock.h" />
|
||||||
|
<ClInclude Include="src\TitleScene.h" />
|
||||||
<ClInclude Include="thirdparty\lauxlib.h" />
|
<ClInclude Include="thirdparty\lauxlib.h" />
|
||||||
<ClInclude Include="thirdparty\linalg.h" />
|
<ClInclude Include="thirdparty\linalg.h" />
|
||||||
<ClInclude Include="thirdparty\lua.h" />
|
<ClInclude Include="thirdparty\lua.h" />
|
||||||
@ -204,6 +207,7 @@
|
|||||||
<ClInclude Include="thirdparty\luaconf.h" />
|
<ClInclude Include="thirdparty\luaconf.h" />
|
||||||
<ClInclude Include="thirdparty\lualib.h" />
|
<ClInclude Include="thirdparty\lualib.h" />
|
||||||
<ClInclude Include="thirdparty\miniaudio.h" />
|
<ClInclude Include="thirdparty\miniaudio.h" />
|
||||||
|
<ClInclude Include="thirdparty\picojson.h" />
|
||||||
<ClInclude Include="thirdparty\stb_truetype.h" />
|
<ClInclude Include="thirdparty\stb_truetype.h" />
|
||||||
<ClInclude Include="src\Win32Console.h" />
|
<ClInclude Include="src\Win32Console.h" />
|
||||||
<ClInclude Include="thirdparty\utf8.h" />
|
<ClInclude Include="thirdparty\utf8.h" />
|
||||||
|
@ -48,6 +48,9 @@
|
|||||||
<ClCompile Include="src\AudioDevice.cc">
|
<ClCompile Include="src\AudioDevice.cc">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\TitleScene.cc">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\iConsole.h">
|
<ClInclude Include="src\iConsole.h">
|
||||||
@ -197,6 +200,15 @@
|
|||||||
<ClInclude Include="src\MusicElementFactory.h">
|
<ClInclude Include="src\MusicElementFactory.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\TitleScene.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="thirdparty\picojson.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\GlitchPosteffect.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Library Include="thirdparty\lua5.1.lib" />
|
<Library Include="thirdparty\lua5.1.lib" />
|
||||||
|
@ -29,7 +29,7 @@ gj::AudioDevice::~AudioDevice() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gj::AudioDevice::PlayMusic(const std::string& path) {
|
void gj::AudioDevice::PlayMusic(const std::string& path, double offset) {
|
||||||
std::lock_guard _(mtx_);
|
std::lock_guard _(mtx_);
|
||||||
|
|
||||||
if (playing_) {
|
if (playing_) {
|
||||||
@ -39,6 +39,11 @@ void gj::AudioDevice::PlayMusic(const std::string& path) {
|
|||||||
if (ma_decoder_init_file(path.c_str(), &config, &dec_) != MA_SUCCESS) {
|
if (ma_decoder_init_file(path.c_str(), &config, &dec_) != MA_SUCCESS) {
|
||||||
Abort("AudioDevice decoder error: "+path);
|
Abort("AudioDevice decoder error: "+path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint64_t offset_frame = static_cast<uint64_t>(kSampleRate * offset);
|
||||||
|
if (ma_decoder_seek_to_pcm_frame(&dec_, offset_frame) != MA_SUCCESS) {
|
||||||
|
Abort("decoder seek failure");
|
||||||
|
}
|
||||||
playing_ = true;
|
playing_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +59,9 @@ void gj::AudioDevice::Callback_(ma_device* ma, void* out, const void* in, ma_uin
|
|||||||
AudioDevice* dev = reinterpret_cast<AudioDevice*>(ma->pUserData);
|
AudioDevice* dev = reinterpret_cast<AudioDevice*>(ma->pUserData);
|
||||||
std::lock_guard _(dev->mtx_);
|
std::lock_guard _(dev->mtx_);
|
||||||
|
|
||||||
|
const double amp = dev->amp_.load();
|
||||||
|
const double lpf = dev->lpf_coe_.load();
|
||||||
|
|
||||||
float* dst = reinterpret_cast<float*>(out);
|
float* dst = reinterpret_cast<float*>(out);
|
||||||
|
|
||||||
size_t wrote = 0;
|
size_t wrote = 0;
|
||||||
@ -65,5 +73,11 @@ void gj::AudioDevice::Callback_(ma_device* ma, void* out, const void* in, ma_uin
|
|||||||
}
|
}
|
||||||
wrote += n;
|
wrote += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < static_cast<size_t>(framecnt)*kChannel; ++i) {
|
||||||
|
dst[i] = static_cast<float>(dst[i]*amp);
|
||||||
|
dst[i] = static_cast<float>(dev->lpf_prev_*lpf + dst[i]*(1-lpf));
|
||||||
|
dev->lpf_prev_ = dst[i];
|
||||||
|
}
|
||||||
dev->time_.fetch_add(framecnt);
|
dev->time_.fetch_add(framecnt);
|
||||||
}
|
}
|
@ -32,9 +32,16 @@ class AudioDevice : public iAudioDevice, public iClock {
|
|||||||
AudioDevice();
|
AudioDevice();
|
||||||
~AudioDevice();
|
~AudioDevice();
|
||||||
|
|
||||||
void PlayMusic(const std::string& path) override;
|
void PlayMusic(const std::string& path, double offset) override;
|
||||||
void StopMusic() override;
|
void StopMusic() override;
|
||||||
|
|
||||||
|
void SetVolume(double amp) override {
|
||||||
|
amp_.store(amp);
|
||||||
|
}
|
||||||
|
void SetLpfIntensity(double v) override {
|
||||||
|
lpf_coe_.store(v);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t now() const override {
|
uint64_t now() const override {
|
||||||
return time_.load() * 1000 / kSampleRate;
|
return time_.load() * 1000 / kSampleRate;
|
||||||
}
|
}
|
||||||
@ -47,6 +54,11 @@ class AudioDevice : public iAudioDevice, public iClock {
|
|||||||
bool playing_ = false;
|
bool playing_ = false;
|
||||||
ma_decoder dec_{0};
|
ma_decoder dec_{0};
|
||||||
|
|
||||||
|
std::atomic<double> amp_ = 1;
|
||||||
|
|
||||||
|
std::atomic<double> lpf_coe_ = 0;
|
||||||
|
float lpf_prev_ = 0;
|
||||||
|
|
||||||
std::atomic<uint64_t> time_;
|
std::atomic<uint64_t> time_;
|
||||||
|
|
||||||
static void Callback_(ma_device* ma, void* out, const void* in, ma_uint32 framecnt);
|
static void Callback_(ma_device* ma, void* out, const void* in, ma_uint32 framecnt);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "PlayScene.h"
|
|
||||||
|
#include "iScene.h"
|
||||||
|
#include "TitleScene.h"
|
||||||
|
|
||||||
|
|
||||||
gj::Game::Game(gj::Game::Param&& p) :
|
gj::Game::Game(gj::Game::Param&& p) :
|
||||||
@ -8,10 +10,9 @@ gj::Game::Game(gj::Game::Param&& p) :
|
|||||||
logger_(p.h),
|
logger_(p.h),
|
||||||
w_(p.w), h_(p.h),
|
w_(p.w), h_(p.h),
|
||||||
frame_(p.w, p.h, kReserveDrawable, kReserveWritable) {
|
frame_(p.w, p.h, kReserveDrawable, kReserveWritable) {
|
||||||
gj::PlayScene::Param param;
|
gj::iScene::Param param;
|
||||||
param.alloc = alloc_;
|
param.alloc = alloc_;
|
||||||
param.clock = &clock_;
|
param.clock = &clock_;
|
||||||
param.audio = p.audio;
|
param.audio = p.audio;
|
||||||
param.score = "test"; /* TODO test */
|
scene_ = alloc_->MakeUniq<gj::iScene, gj::TitleScene>(param);
|
||||||
scene_ = alloc_->MakeUniq<gj::iScene, gj::PlayScene>(std::move(param));
|
|
||||||
}
|
}
|
48
src/GlitchPosteffect.h
Normal file
48
src/GlitchPosteffect.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "iDrawable.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace gj {
|
||||||
|
|
||||||
|
|
||||||
|
class GlitchPosteffect : public iDrawable {
|
||||||
|
public:
|
||||||
|
GlitchPosteffect(GlitchPosteffect&&) = delete;
|
||||||
|
GlitchPosteffect(const GlitchPosteffect&) = delete;
|
||||||
|
|
||||||
|
GlitchPosteffect& operator=(GlitchPosteffect&&) = delete;
|
||||||
|
GlitchPosteffect& operator=(const GlitchPosteffect&) = delete;
|
||||||
|
|
||||||
|
GlitchPosteffect() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(Colorbuffer& fb) const override {
|
||||||
|
const int32_t w = static_cast<int32_t>(fb.width());
|
||||||
|
const int32_t h = static_cast<int32_t>(fb.height());
|
||||||
|
|
||||||
|
float* ptr = fb.ptr();
|
||||||
|
|
||||||
|
for (int32_t y = 0; y < h; ++y) {
|
||||||
|
const double shift = (XorShift(seed+y)%100/100.*2-1)*maxShift;
|
||||||
|
const int32_t s = static_cast<int32_t>(w*shift);
|
||||||
|
if (std::abs(shift) > 1) continue;
|
||||||
|
|
||||||
|
const size_t offset = static_cast<size_t>(y) * w;
|
||||||
|
float* src = ptr + offset;
|
||||||
|
float* dst = ptr + offset + s;
|
||||||
|
if (src > dst) std::swap(src, dst);
|
||||||
|
|
||||||
|
std::memmove(dst, src, static_cast<size_t>(w) - std::abs(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t seed = 1;
|
||||||
|
double maxShift = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -42,7 +42,7 @@ class GlyphElementFactory : public iElementFactory {
|
|||||||
if (found != fonts_.end()) {
|
if (found != fonts_.end()) {
|
||||||
return *found->second;
|
return *found->second;
|
||||||
}
|
}
|
||||||
auto f = alloc_->MakeUniq<Font>(alloc_, "res/font/"+name);
|
auto f = alloc_->MakeUniq<Font>(alloc_, name);
|
||||||
auto ptr = f.get();
|
auto ptr = f.get();
|
||||||
fonts_[name] = std::move(f);
|
fonts_[name] = std::move(f);
|
||||||
return *ptr;
|
return *ptr;
|
||||||
|
@ -189,10 +189,9 @@ bool gj::HiraganaMatcher::Input_(wchar_t c, bool force_cut) {
|
|||||||
if (itr.size() == newbuf.size()) {
|
if (itr.size() == newbuf.size()) {
|
||||||
comp_match = i;
|
comp_match = i;
|
||||||
if (force_cut) {
|
if (force_cut) {
|
||||||
buffer_ = {c};
|
buffer_ = L"";
|
||||||
state_.match += i;
|
state_.match += i;
|
||||||
UpdateExpects_();
|
return Input_(c, false);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
part_match = i;
|
part_match = i;
|
||||||
@ -248,6 +247,8 @@ void gj::HiraganaMatcher::UpdateExpects_() {
|
|||||||
}
|
}
|
||||||
remain = remain.substr(len);
|
remain = remain.substr(len);
|
||||||
}
|
}
|
||||||
if (prev == remain.size()) Abort("invalid pattern for InputWin");
|
if (prev == remain.size()) {
|
||||||
|
Abort("invalid pattern for InputWin");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#include "Lua.h"
|
#include "Lua.h"
|
||||||
|
|
||||||
|
#include "thirdparty/lualib.h"
|
||||||
|
|
||||||
|
|
||||||
struct LuaPusher {
|
struct LuaPusher {
|
||||||
LuaPusher() = delete;
|
LuaPusher() = delete;
|
||||||
@ -142,6 +144,7 @@ gj::Lua::Lua(iAllocator* alloc, ElementStore* store, const FactoryMap& factory,
|
|||||||
if (L == nullptr) {
|
if (L == nullptr) {
|
||||||
Abort("lua_newstate failure");
|
Abort("lua_newstate failure");
|
||||||
}
|
}
|
||||||
|
luaopen_math(L);
|
||||||
|
|
||||||
for (const auto& f : factory) {
|
for (const auto& f : factory) {
|
||||||
lua_pushstring(L, f.first.c_str());
|
lua_pushstring(L, f.first.c_str());
|
||||||
|
@ -12,6 +12,17 @@ namespace gj {
|
|||||||
|
|
||||||
class MusicElement : public iElement {
|
class MusicElement : public iElement {
|
||||||
public:
|
public:
|
||||||
|
struct Param {
|
||||||
|
iAudioDevice* audio;
|
||||||
|
|
||||||
|
Period period;
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
double offset;
|
||||||
|
|
||||||
|
UniqPtr<iElementDriver> driver;
|
||||||
|
};
|
||||||
|
|
||||||
MusicElement() = delete;
|
MusicElement() = delete;
|
||||||
MusicElement(MusicElement&&) = delete;
|
MusicElement(MusicElement&&) = delete;
|
||||||
MusicElement(const MusicElement&) = delete;
|
MusicElement(const MusicElement&) = delete;
|
||||||
@ -19,13 +30,24 @@ public:
|
|||||||
MusicElement& operator=(MusicElement&&) = delete;
|
MusicElement& operator=(MusicElement&&) = delete;
|
||||||
MusicElement& operator=(const MusicElement&) = delete;
|
MusicElement& operator=(const MusicElement&) = delete;
|
||||||
|
|
||||||
MusicElement(const Period& p, iAudioDevice* audio, const std::string& name) :
|
MusicElement(Param&& p) :
|
||||||
iElement(p), audio_(audio), path_("res/music/"+name) {
|
iElement(p.period), audio_(p.audio), path_(p.path), offset_(p.offset),
|
||||||
|
drv_(std::move(p.driver)) {
|
||||||
|
param_["volume"] = 0.;
|
||||||
|
param_["lpf"] = 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(Frame& frame, double t) override {
|
void Update(Frame& frame, double t) override {
|
||||||
|
drv_->Update(param_, t);
|
||||||
|
|
||||||
|
const double volume = std::get<double>(param_["volume"]);
|
||||||
|
const double lpf = std::get<double>(param_["lpf"]);
|
||||||
|
|
||||||
|
audio_->SetVolume(volume);
|
||||||
|
audio_->SetLpfIntensity(lpf);
|
||||||
|
|
||||||
if (first_) {
|
if (first_) {
|
||||||
audio_->PlayMusic(path_);
|
audio_->PlayMusic(path_, offset_);
|
||||||
first_ = false;
|
first_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,6 +63,11 @@ public:
|
|||||||
std::string path_;
|
std::string path_;
|
||||||
|
|
||||||
bool first_ = true;
|
bool first_ = true;
|
||||||
|
|
||||||
|
double offset_;
|
||||||
|
|
||||||
|
UniqPtr<iElementDriver> drv_;
|
||||||
|
iElementDriver::Param param_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,11 +22,18 @@ class MusicElementFactory : public iElementFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UniqPtr<iElement> Create(Param&& param) override {
|
UniqPtr<iElement> Create(Param&& param) override {
|
||||||
if (param.custom.size() != 1) return nullptr;
|
if (param.custom.size() != 2) return nullptr;
|
||||||
|
|
||||||
const std::string name = std::get<std::string>(param.custom[0]);
|
const std::string path = std::get<std::string>(param.custom[0]);
|
||||||
|
const double offset = std::get<double>(param.custom[1]);
|
||||||
|
|
||||||
return alloc_->MakeUniq<iElement, MusicElement>(param.period, audio_, name);
|
MusicElement::Param p;
|
||||||
|
p.audio = audio_;
|
||||||
|
p.period = param.period;
|
||||||
|
p.path = path;
|
||||||
|
p.offset = offset;
|
||||||
|
p.driver = std::move(param.driver);
|
||||||
|
return alloc_->MakeUniq<iElement, MusicElement>(std::move(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -7,29 +7,28 @@
|
|||||||
#include "ResultScene.h"
|
#include "ResultScene.h"
|
||||||
|
|
||||||
|
|
||||||
gj::PlayScene::PlayScene(Param&& p) :
|
gj::PlayScene::PlayScene(const Param& p, const std::string& title, const std::string& path) :
|
||||||
alloc_(p.alloc), audio_(p.audio),
|
param_(p), clock_(p.clock), store_(&clock_, 256) {
|
||||||
clock_(p.clock), store_(&clock_, 256) {
|
|
||||||
|
|
||||||
GlyphElementFactory glyph(alloc_);
|
GlyphElementFactory glyph(p.alloc);
|
||||||
InputWindowElementFactory inputWin(alloc_, &sb_);
|
InputWindowElementFactory inputWin(p.alloc, &sb_);
|
||||||
MusicElementFactory music(alloc_, audio_);
|
MusicElementFactory music(p.alloc, p.audio);
|
||||||
|
|
||||||
sb_.title = ConvertStrToWstr(p.score);
|
sb_.title = ConvertStrToWstr(title);
|
||||||
|
|
||||||
Lua::FactoryMap map = {
|
Lua::FactoryMap map = {
|
||||||
{ "Glyph", &glyph },
|
{ "Glyph", &glyph },
|
||||||
{ "InputWin", &inputWin },
|
{ "InputWin", &inputWin },
|
||||||
{ "Music", &music },
|
{ "Music", &music },
|
||||||
};
|
};
|
||||||
lua_ = alloc_->MakeUniq<Lua>(
|
lua_ = p.alloc->MakeUniq<Lua>(
|
||||||
alloc_, &store_, map, "res/score/" + p.score + ".lua");
|
p.alloc, &store_, map, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gj::UniqPtr<gj::iScene> gj::PlayScene::Update(Frame& f) {
|
gj::UniqPtr<gj::iScene> gj::PlayScene::Update(Frame& f) {
|
||||||
if (store_.IsEmpty()) {
|
if (store_.IsEmpty()) {
|
||||||
return alloc_->MakeUniq<iScene, ResultScene>(alloc_, clock_.parent(), sb_);
|
return param_.alloc->MakeUniq<iScene, ResultScene>(param_, sb_);
|
||||||
}
|
}
|
||||||
|
|
||||||
store_.Update(f);
|
store_.Update(f);
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "ElementStore.h"
|
#include "ElementStore.h"
|
||||||
#include "Frame.h"
|
|
||||||
#include "iAllocator.h"
|
|
||||||
#include "iAudioDevice.h"
|
|
||||||
#include "iLogger.h"
|
|
||||||
#include "iScene.h"
|
#include "iScene.h"
|
||||||
#include "Lua.h"
|
#include "Lua.h"
|
||||||
#include "OffsetClock.h"
|
#include "OffsetClock.h"
|
||||||
@ -17,14 +13,6 @@ namespace gj {
|
|||||||
|
|
||||||
class PlayScene : public iScene {
|
class PlayScene : public iScene {
|
||||||
public:
|
public:
|
||||||
struct Param {
|
|
||||||
iAllocator* alloc;
|
|
||||||
iAudioDevice* audio;
|
|
||||||
const iClock* clock;
|
|
||||||
|
|
||||||
std::string score;
|
|
||||||
};
|
|
||||||
|
|
||||||
PlayScene() = delete;
|
PlayScene() = delete;
|
||||||
PlayScene(PlayScene&&) = delete;
|
PlayScene(PlayScene&&) = delete;
|
||||||
PlayScene(const PlayScene&) = delete;
|
PlayScene(const PlayScene&) = delete;
|
||||||
@ -32,13 +20,12 @@ class PlayScene : public iScene {
|
|||||||
PlayScene& operator=(PlayScene&&) = delete;
|
PlayScene& operator=(PlayScene&&) = delete;
|
||||||
PlayScene& operator=(const PlayScene&) = delete;
|
PlayScene& operator=(const PlayScene&) = delete;
|
||||||
|
|
||||||
PlayScene(Param&& p);
|
PlayScene(const Param& p, const std::string& title, const std::string& path);
|
||||||
|
|
||||||
UniqPtr<iScene> Update(Frame& f) override;
|
UniqPtr<iScene> Update(Frame& f) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iAllocator* alloc_;
|
Param param_;
|
||||||
iAudioDevice* audio_;
|
|
||||||
|
|
||||||
OffsetClock clock_;
|
OffsetClock clock_;
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include "ResultScene.h"
|
#include "ResultScene.h"
|
||||||
|
|
||||||
|
#include "TitleScene.h"
|
||||||
|
|
||||||
gj::ResultScene::ResultScene(iAllocator* alloc, const iClock* clock, const Scoreboard& sb) :
|
|
||||||
alloc_(alloc), clock_(clock), sb_(sb),
|
gj::ResultScene::ResultScene(const Param& p, const Scoreboard& sb) :
|
||||||
|
param_(p), clock_(p.clock), sb_(sb),
|
||||||
title_(sb.title),
|
title_(sb.title),
|
||||||
correct_label_(L"CORRECT TYPES"),
|
correct_label_(L"CORRECT TYPES"),
|
||||||
correct_num_(std::to_wstring(sb.correct)),
|
correct_num_(std::to_wstring(sb.correct)),
|
||||||
@ -10,7 +12,7 @@ gj::ResultScene::ResultScene(iAllocator* alloc, const iClock* clock, const Score
|
|||||||
line_label_(L"COMPLETE LINES"),
|
line_label_(L"COMPLETE LINES"),
|
||||||
line_num_(std::to_wstring(sb.completeLines)),
|
line_num_(std::to_wstring(sb.completeLines)),
|
||||||
line_den_(std::to_wstring(sb.lines)),
|
line_den_(std::to_wstring(sb.lines)),
|
||||||
guide_(L"~ PRESS ENTER ~") {
|
guide_(L"~ PRESS SPACE ~") {
|
||||||
}
|
}
|
||||||
|
|
||||||
gj::UniqPtr<gj::iScene> gj::ResultScene::Update(Frame& f) {
|
gj::UniqPtr<gj::iScene> gj::ResultScene::Update(Frame& f) {
|
||||||
@ -51,5 +53,9 @@ gj::UniqPtr<gj::iScene> gj::ResultScene::Update(Frame& f) {
|
|||||||
guide_.SetPosition((w-guide_.width())/2, static_cast<int32_t>(h*.8));
|
guide_.SetPosition((w-guide_.width())/2, static_cast<int32_t>(h*.8));
|
||||||
f.Add(&guide_);
|
f.Add(&guide_);
|
||||||
|
|
||||||
|
if (f.input.find(' ') != std::string::npos) {
|
||||||
|
return param_.alloc->MakeUniq<iScene, TitleScene>(param_);
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ElementStore.h"
|
|
||||||
#include "Frame.h"
|
|
||||||
#include "iAllocator.h"
|
|
||||||
#include "iScene.h"
|
#include "iScene.h"
|
||||||
#include "OffsetClock.h"
|
#include "OffsetClock.h"
|
||||||
#include "Scoreboard.h"
|
#include "Scoreboard.h"
|
||||||
@ -21,12 +18,13 @@ class ResultScene : public iScene {
|
|||||||
ResultScene& operator=(ResultScene&&) = delete;
|
ResultScene& operator=(ResultScene&&) = delete;
|
||||||
ResultScene& operator=(const ResultScene&) = delete;
|
ResultScene& operator=(const ResultScene&) = delete;
|
||||||
|
|
||||||
ResultScene(iAllocator* alloc, const iClock* clock, const Scoreboard& sb);
|
ResultScene(const Param& p, const Scoreboard& sb);
|
||||||
|
|
||||||
UniqPtr<iScene> Update(Frame& f) override;
|
UniqPtr<iScene> Update(Frame& f) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iAllocator* alloc_;
|
Param param_;
|
||||||
|
|
||||||
OffsetClock clock_;
|
OffsetClock clock_;
|
||||||
Scoreboard sb_;
|
Scoreboard sb_;
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ void gj::Texture::Draw(Colorbuffer& fb) const {
|
|||||||
if (dstx < 0 || w <= dstx) continue;
|
if (dstx < 0 || w <= dstx) continue;
|
||||||
if (dsty < 0 || h <= dsty) continue;
|
if (dsty < 0 || h <= dsty) continue;
|
||||||
|
|
||||||
dst[dstx + w*dsty] = src[srcx + srcw*srcy] * alpha_;
|
dst[dstx + w*dsty] += src[srcx + srcw*srcy] * alpha_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
129
src/TitleScene.cc
Normal file
129
src/TitleScene.cc
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include "TitleScene.h"
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "thirdparty/picojson.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "Font.h"
|
||||||
|
#include "PlayScene.h"
|
||||||
|
|
||||||
|
|
||||||
|
gj::TitleScene::TitleScene(const Param& p) :
|
||||||
|
param_(p),
|
||||||
|
score_(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)) {
|
||||||
|
/* load score list */
|
||||||
|
std::ifstream ifs(kListPath);
|
||||||
|
if (!ifs) Abort(std::string(kListPath)+" is missing");
|
||||||
|
|
||||||
|
::picojson::value root;
|
||||||
|
const std::string err = ::picojson::parse(root, ifs);
|
||||||
|
ifs.close();
|
||||||
|
|
||||||
|
if (err.size()) Abort(std::string(kListPath)+": "+err);
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
auto& list = root.get<::picojson::array>();
|
||||||
|
for (auto& e : list) {
|
||||||
|
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 = static_cast<uint64_t>(obj["playOffset"].get<double>());
|
||||||
|
|
||||||
|
list_.push_back(s);
|
||||||
|
}
|
||||||
|
if (list_.size() == 0) Abort("no score is registered");
|
||||||
|
|
||||||
|
SelectScore_(0);
|
||||||
|
|
||||||
|
/* render logo */
|
||||||
|
Font font(param_.alloc, "res/font/shippori.ttf");
|
||||||
|
logo_ = Texture(font.RenderGlyphs(L"GlyphsJuke", 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
gj::UniqPtr<gj::iScene> gj::TitleScene::Update(Frame& frame) {
|
||||||
|
for (const auto c : frame.input) {
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
SelectScore_(select_index_? select_index_-1: list_.size()-1);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
SelectScore_((select_index_+1)%list_.size());
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
return param_.alloc->MakeUniq<iScene, PlayScene>(
|
||||||
|
param_, list_[select_index_].displayName, list_[select_index_].score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t now = param_.clock->now();
|
||||||
|
|
||||||
|
const int32_t w = static_cast<int32_t>(frame.w);
|
||||||
|
const int32_t h = static_cast<int32_t>(frame.h);
|
||||||
|
|
||||||
|
const int32_t selector_y = static_cast<int32_t>(h*.75);
|
||||||
|
|
||||||
|
const uint64_t period1 = XorShift(now/1000+1)%1000 + 500;
|
||||||
|
const uint64_t period2 = XorShift(now/1000+5)%1000 + 500;
|
||||||
|
logo_.SetAlpha(static_cast<float>(XorShift(now/period1+1)%100/100.*.4+.4));
|
||||||
|
|
||||||
|
const double shift_x = (XorShift(now/period1+1)%100/100.*2 - 1)*.05;
|
||||||
|
const double shift_y = (XorShift(now/period2+3)%100/100.*2 - 1)*.05;
|
||||||
|
const double scale_x = (XorShift(now/period1+3)%100/100.*2 - 1)*.1;
|
||||||
|
|
||||||
|
const double theta = (XorShift(now/period2+13)%100/100.*2 - 1)*.01*kPi*2;
|
||||||
|
|
||||||
|
const double c = cos(theta), s = sin(theta);
|
||||||
|
auto M = mat3{
|
||||||
|
{1+scale_x, 0, 0},
|
||||||
|
{0, .8, 0},
|
||||||
|
{shift_x, shift_y+.4, 1}
|
||||||
|
};
|
||||||
|
auto Mr = mat3{
|
||||||
|
{c, -s, 0},
|
||||||
|
{s, c, 0},
|
||||||
|
{0, 0, 1},
|
||||||
|
};
|
||||||
|
M = ::linalg::mul(Mr, M);
|
||||||
|
logo_.SetMatrix(M);
|
||||||
|
frame.Add(&logo_);
|
||||||
|
|
||||||
|
next_.SetPosition(static_cast<int32_t>(w*.8-next_.width()), selector_y);
|
||||||
|
frame.Add(&next_);
|
||||||
|
|
||||||
|
prev_.SetPosition(static_cast<int32_t>(w*.2), selector_y);
|
||||||
|
frame.Add(&prev_);
|
||||||
|
|
||||||
|
score_.SetPosition((w-score_.width())/2, selector_y);
|
||||||
|
frame.Add(&score_);
|
||||||
|
|
||||||
|
guide_.SetPosition((w-guide_.width())/2, selector_y+3);
|
||||||
|
frame.Add(&guide_);
|
||||||
|
|
||||||
|
pe_.seed = XorShift(now/period1+10);
|
||||||
|
pe_.maxShift = (XorShift(now/period1+7)%100/100.*2 - 1)*.1;
|
||||||
|
frame.Add(&pe_);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gj::TitleScene::SelectScore_(size_t index) {
|
||||||
|
const auto& s = list_[index];
|
||||||
|
score_ = Text(ConvertStrToWstr(s.displayName));
|
||||||
|
select_index_ = index;
|
||||||
|
|
||||||
|
param_.audio->SetVolume(.2);
|
||||||
|
param_.audio->SetLpfIntensity(.99);
|
||||||
|
param_.audio->PlayMusic(s.music, s.playOffset);
|
||||||
|
}
|
53
src/TitleScene.h
Normal file
53
src/TitleScene.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "GlitchPosteffect.h"
|
||||||
|
#include "iScene.h"
|
||||||
|
#include "Text.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
namespace gj {
|
||||||
|
|
||||||
|
|
||||||
|
class TitleScene : public iScene {
|
||||||
|
public:
|
||||||
|
static constexpr auto kListPath = "res/list.json";
|
||||||
|
|
||||||
|
TitleScene() = delete;
|
||||||
|
TitleScene(TitleScene&&) = delete;
|
||||||
|
TitleScene(const TitleScene&) = delete;
|
||||||
|
|
||||||
|
TitleScene& operator=(TitleScene&&) = delete;
|
||||||
|
TitleScene& operator=(const TitleScene&) = delete;
|
||||||
|
|
||||||
|
TitleScene(const Param& p);
|
||||||
|
|
||||||
|
UniqPtr<iScene> Update(Frame& frame) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Score {
|
||||||
|
std::string displayName;
|
||||||
|
std::string score;
|
||||||
|
std::string music;
|
||||||
|
double playOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
Param param_;
|
||||||
|
|
||||||
|
Text score_;
|
||||||
|
Text next_;
|
||||||
|
Text prev_;
|
||||||
|
Text guide_;
|
||||||
|
|
||||||
|
Texture logo_;
|
||||||
|
|
||||||
|
size_t select_index_;
|
||||||
|
std::vector<Score> list_;
|
||||||
|
|
||||||
|
GlitchPosteffect pe_;
|
||||||
|
|
||||||
|
void SelectScore_(size_t index);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,8 @@ namespace gj {
|
|||||||
using mat3 = ::linalg::mat<double, 3, 3>;
|
using mat3 = ::linalg::mat<double, 3, 3>;
|
||||||
using vec3 = ::linalg::vec<double, 3>;
|
using vec3 = ::linalg::vec<double, 3>;
|
||||||
|
|
||||||
|
constexpr double kPi = 3.14159265358979323846264338327950288;
|
||||||
|
|
||||||
|
|
||||||
static inline std::wstring ConvertStrToWstr(const std::string& str) {
|
static inline std::wstring ConvertStrToWstr(const std::string& str) {
|
||||||
std::wstring ret;
|
std::wstring ret;
|
||||||
@ -38,6 +40,12 @@ static inline size_t CountWstrBytes(const std::wstring& str) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint64_t XorShift(uint64_t x) {
|
||||||
|
x = x ^ (x << 13);
|
||||||
|
x = x ^ (x >> 7);
|
||||||
|
return x ^ (x << 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[[noreturn]]
|
[[noreturn]]
|
||||||
static inline void Abort(const std::string& msg) {
|
static inline void Abort(const std::string& msg) {
|
||||||
|
@ -18,8 +18,11 @@ public:
|
|||||||
|
|
||||||
virtual ~iAudioDevice() = default;
|
virtual ~iAudioDevice() = default;
|
||||||
|
|
||||||
virtual void PlayMusic(const std::string& path) = 0;
|
virtual void PlayMusic(const std::string& path, double offset) = 0;
|
||||||
virtual void StopMusic() = 0;
|
virtual void StopMusic() = 0;
|
||||||
|
|
||||||
|
virtual void SetVolume(double amp) = 0;
|
||||||
|
virtual void SetLpfIntensity(double v) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "Frame.h"
|
#include "Frame.h"
|
||||||
#include "iAllocator.h"
|
#include "iAllocator.h"
|
||||||
|
#include "iAudioDevice.h"
|
||||||
|
#include "iClock.h"
|
||||||
#include "iDrawable.h"
|
#include "iDrawable.h"
|
||||||
#include "iWritable.h"
|
#include "iWritable.h"
|
||||||
|
|
||||||
@ -13,6 +15,12 @@ namespace gj {
|
|||||||
|
|
||||||
class iScene {
|
class iScene {
|
||||||
public:
|
public:
|
||||||
|
struct Param {
|
||||||
|
iAllocator* alloc;
|
||||||
|
iAudioDevice* audio;
|
||||||
|
const iClock* clock;
|
||||||
|
};
|
||||||
|
|
||||||
iScene() = default;
|
iScene() = default;
|
||||||
iScene(iScene&&) = default;
|
iScene(iScene&&) = default;
|
||||||
iScene(const iScene&) = default;
|
iScene(const iScene&) = default;
|
||||||
|
1200
thirdparty/picojson.h
vendored
Normal file
1200
thirdparty/picojson.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user