diff --git a/assets/characters/bf/character.lua b/assets/characters/bf/character.lua index 9d74e07..91f34aa 100644 --- a/assets/characters/bf/character.lua +++ b/assets/characters/bf/character.lua @@ -1,4 +1,6 @@ function onCreateCharacter(character) + character.flipX = not character.flipX + character.animation:addByPrefix("idle" ,"BF idle dance", 24, false, {}) character.animation:addOffset("idle", -5, 0) @@ -8,13 +10,16 @@ function onCreateCharacter(character) character.animation:addByPrefix("singUP" ,"BF NOTE UP0", 24, false, {}) character.animation:addOffset("singUP", -46, 27) - character.animation:addByPrefix("singRIGHT" ,"BF NOTE RIGHT0", 24, false, {}) - character.animation:addOffset("singRIGHT", -48, -7) + local right = flipX and "singLEFT" or "singRIGHT" + character.animation:addByPrefix(right ,"BF NOTE RIGHT0", 24, false, {}) + character.animation:addOffset(right, -48, -7) - character.animation:addByPrefix("singLEFT" ,"BF NOTE LEFT0", 24, false, {}) - character.animation:addOffset("singLEFT", 5, -6) + local left = flipX and "singRIGHT" or "singLEFT" + character.animation:addByPrefix(left ,"BF NOTE LEFT0", 24, false, {}) + character.animation:addOffset(left, 5, -6) character.animation:play("idle", true) + character.barColor = Color.new(49, 176, 209, 255) end \ No newline at end of file diff --git a/assets/images/bad.png b/assets/images/bad.png index e75c869..5e90d5f 100644 Binary files a/assets/images/bad.png and b/assets/images/bad.png differ diff --git a/assets/images/combo.png b/assets/images/combo.png index 810d34a..ace118a 100644 Binary files a/assets/images/combo.png and b/assets/images/combo.png differ diff --git a/assets/images/good.png b/assets/images/good.png index 08f59ac..c3f0cd3 100644 Binary files a/assets/images/good.png and b/assets/images/good.png differ diff --git a/assets/images/num0.png b/assets/images/num0.png index 0b091fc..cd8d8a4 100644 Binary files a/assets/images/num0.png and b/assets/images/num0.png differ diff --git a/assets/images/num1.png b/assets/images/num1.png index fb814aa..af38bf9 100644 Binary files a/assets/images/num1.png and b/assets/images/num1.png differ diff --git a/assets/images/num2.png b/assets/images/num2.png index 0247033..a832748 100644 Binary files a/assets/images/num2.png and b/assets/images/num2.png differ diff --git a/assets/images/num3.png b/assets/images/num3.png index aa12857..7e8409f 100644 Binary files a/assets/images/num3.png and b/assets/images/num3.png differ diff --git a/assets/images/num4.png b/assets/images/num4.png index 820b1a8..00d6e80 100644 Binary files a/assets/images/num4.png and b/assets/images/num4.png differ diff --git a/assets/images/num5.png b/assets/images/num5.png index 8237a08..29f2362 100644 Binary files a/assets/images/num5.png and b/assets/images/num5.png differ diff --git a/assets/images/num6.png b/assets/images/num6.png index c6b6096..7540fd8 100644 Binary files a/assets/images/num6.png and b/assets/images/num6.png differ diff --git a/assets/images/num7.png b/assets/images/num7.png index 751bb65..5293238 100644 Binary files a/assets/images/num7.png and b/assets/images/num7.png differ diff --git a/assets/images/num8.png b/assets/images/num8.png index ccf4f40..8350186 100644 Binary files a/assets/images/num8.png and b/assets/images/num8.png differ diff --git a/assets/images/num9.png b/assets/images/num9.png index 5738414..0509f6c 100644 Binary files a/assets/images/num9.png and b/assets/images/num9.png differ diff --git a/assets/images/shit.png b/assets/images/shit.png index 50f84ed..8f57021 100644 Binary files a/assets/images/shit.png and b/assets/images/shit.png differ diff --git a/assets/images/sick.png b/assets/images/sick.png index ef451a9..59d7991 100644 Binary files a/assets/images/sick.png and b/assets/images/sick.png differ diff --git a/assets/images/slungus.png b/assets/images/slungus.png index 1deef6b..3ff9e62 100644 Binary files a/assets/images/slungus.png and b/assets/images/slungus.png differ diff --git a/assets/sounds/cancelMenu.ogg b/assets/sounds/cancelMenu.ogg new file mode 100644 index 0000000..d56d11d Binary files /dev/null and b/assets/sounds/cancelMenu.ogg differ diff --git a/assets/sounds/confirmMenu.ogg b/assets/sounds/confirmMenu.ogg new file mode 100644 index 0000000..f60010e Binary files /dev/null and b/assets/sounds/confirmMenu.ogg differ diff --git a/assets/stages/mainStage/stage.lua b/assets/stages/mainStage/stage.lua index d9c9d0d..d98a5f7 100644 --- a/assets/stages/mainStage/stage.lua +++ b/assets/stages/mainStage/stage.lua @@ -17,11 +17,12 @@ function onCreateStage(stage) boyfriend.position.x = 700 - boyfriend.position.y = 100 + + boyfriend.position.y = (boyfriend.characterName=="bf") and 400 or 100 stage:add(boyfriend) dad.position.x = 100 - dad.position.y = 100 + dad.position.y = (boyfriend.characterName=="bf") and 350 or 100 stage:add(dad) local stagecurtains = Sprite.new(-500, -300) diff --git a/external/json b/external/json index 1876493..35705d7 160000 --- a/external/json +++ b/external/json @@ -1 +1 @@ -Subproject commit 1876493f8789b0e50991c90a426fbb65e701887e +Subproject commit 35705d79d878db5ca1a282ec0f8243a80010d24e diff --git a/external/raylib b/external/raylib index caba629..9f3cadf 160000 --- a/external/raylib +++ b/external/raylib @@ -1 +1 @@ -Subproject commit caba629ca1ed8a31a4466599cd387c750e57e97a +Subproject commit 9f3cadf1e618f125bd9b282c7759f8cb26ce17fc diff --git a/src/funkin/Camera.cpp b/src/funkin/Camera.cpp index a538954..020041b 100644 --- a/src/funkin/Camera.cpp +++ b/src/funkin/Camera.cpp @@ -22,6 +22,8 @@ namespace funkin { flashColor = col; flashDuration = duration; flashAlpha = 1.0f; + + flashIn=true; } Vector2 Camera::getScreenToWorld(const Vector2 pos) const { return GetScreenToWorld2D(pos, camera); } @@ -47,7 +49,13 @@ namespace funkin { position, Vector2{.x = static_cast(GetScreenWidth()) / 2.0f, .y = static_cast(GetScreenHeight()) / 2.0f}); camera.zoom = zoom; camera.rotation = angle; - if (flashAlpha > 0.0) { + if(flashIn){ + flashAlpha += delta / flashDuration; + if(flashAlpha >= 1.0){ + flashIn=false; + flashAlpha=1; + } + }else if (flashAlpha > 0.0) { flashAlpha -= delta / flashDuration; } } diff --git a/src/funkin/Camera.hpp b/src/funkin/Camera.hpp index 9062718..2ebd2a2 100644 --- a/src/funkin/Camera.hpp +++ b/src/funkin/Camera.hpp @@ -18,6 +18,9 @@ namespace funkin { float angle = 0.0f; float zoom = 1.0f; + float flashAlpha = 0.0f; + float flashDuration = 0.0f; + Color flashColor = BLANK; Vector2 target = Vector2Zero(); Vector2 position = Vector2Zero(); @@ -44,9 +47,7 @@ namespace funkin { void update(float delta); graphics::Shader premultiplyShader; private: - float flashAlpha = 0.0f; - float flashDuration = 0.0f; - Color flashColor = BLANK; + bool flashIn = false; Camera2D camera{}; RenderTexture canvas{}; }; diff --git a/src/funkin/Game.cpp b/src/funkin/Game.cpp index 4ba5ef1..4aee9c3 100644 --- a/src/funkin/Game.cpp +++ b/src/funkin/Game.cpp @@ -46,6 +46,8 @@ namespace funkin { scene = std::move(newScene); scene->create(); + + defaultCamera->flash(BLACK, 0.5f); switching = false; nextScene = nullptr; } diff --git a/src/funkin/Group.hpp b/src/funkin/Group.hpp index c0577f9..b44893d 100644 --- a/src/funkin/Group.hpp +++ b/src/funkin/Group.hpp @@ -47,9 +47,9 @@ \ template \ void name::remove(std::shared_ptr object) { \ - if (std::ranges::find(members, object) != members.end()) { \ - members.erase(std::ranges::find(members, object)); \ - } \ + if (auto ranges = std::ranges::find(members, object); ranges != members.end()) { \ + members.erase(ranges); \ + } \ } \ \ template \ diff --git a/src/funkin/data/Song.cpp b/src/funkin/data/Song.cpp index 2d266c7..c4486f4 100644 --- a/src/funkin/data/Song.cpp +++ b/src/funkin/data/Song.cpp @@ -12,14 +12,24 @@ using json = nlohmann::json; namespace funkin::data { SongData Song::parseSong(const std::string &songName, const std::string &difficulty) { const std::string songPath = "assets/songs/" + songName + "/"; + if (FileExists((songPath + difficulty).c_str())) { + return parseLegacy(songPath + difficulty); + } if (FileExists((songPath + songName + "-metadata.json").c_str())) { - return parseVSlice(songName, difficulty); + return parseVSlice(songPath + songName, difficulty); } - return parseLegacy(songName, difficulty); + return parseLegacy(songPath + songName + "-" + difficulty + ".json"); } - - SongData Song::parseLegacy(const std::string &songName, const std::string &difficulty) { - const std::string path = "assets/songs/" + songName + "/" + songName + "-" + difficulty + ".json"; + SongData Song::parseSongFromPath(const std::string &path, const std::string &difficulty) { + if (FileExists((path + "-metadata.json").c_str())) { + return parseVSlice(path, difficulty); + } + if (FileExists((path + ".json").c_str())) { + return parseLegacy(path+".json"); + } + return parseLegacy(path); + } + SongData Song::parseLegacy(const std::string &path) { auto chart = std::ifstream(path); auto parsedChart = json::parse(chart); chart.close(); @@ -27,7 +37,6 @@ namespace funkin::data { std::vector playerNotes = {}; std::vector opponentNotes = {}; - std::vector events = {}; nlohmann::json_abi_v3_12_0::json song; @@ -97,8 +106,8 @@ namespace funkin::data { } // load events from json - if (FileExists(("assets/songs/" + songName + "/events.json").c_str())) { - auto eventStream = std::ifstream("assets/songs/" + songName + "/events.json"); + if (FileExists((path + "/events.json").c_str())) { + auto eventStream = std::ifstream(path + "/events.json"); auto parsedEvents = json::parse(eventStream); eventStream.close(); @@ -151,9 +160,7 @@ namespace funkin::data { .spectator = spectator}; } - SongData Song::parseVSlice(const std::string &songName, const std::string &difficulty) { - const std::string path = "assets/songs/" + songName + "/" + songName; - + SongData Song::parseVSlice(const std::string &path, const std::string &difficulty) { auto chart = std::ifstream(path + "-chart.json"); auto meta = std::ifstream(path + "-metadata.json"); @@ -171,7 +178,7 @@ namespace funkin::data { for (auto note: parsedChart["notes"][difficulty]) { bool player = note["d"] < 4; - auto noteData = NoteData{.player = player, + NoteData noteData = NoteData{.player = player, .lane = static_cast(static_cast(note["d"]) % 4), .time = note["t"], .length = note.contains("l") ? static_cast(note["l"]) : 0.0f}; diff --git a/src/funkin/data/Song.hpp b/src/funkin/data/Song.hpp index a68a638..01a3261 100644 --- a/src/funkin/data/Song.hpp +++ b/src/funkin/data/Song.hpp @@ -29,13 +29,15 @@ namespace funkin::data { std::string player; std::string opponent; std::string spectator; + std::string path; } SongData; class Song { public: static SongData parseSong(const std::string &songName, const std::string &difficulty); + static SongData parseSongFromPath(const std::string &path, const std::string &difficulty); static SongData parseVSlice(const std::string &songName, const std::string &difficulty); - static SongData parseLegacy(const std::string &songName, const std::string &difficulty); + static SongData parseLegacy(const std::string &path); }; } // namespace funkin::data diff --git a/src/funkin/modding/LuaScript.cpp b/src/funkin/modding/LuaScript.cpp index 85ab25f..d557745 100644 --- a/src/funkin/modding/LuaScript.cpp +++ b/src/funkin/modding/LuaScript.cpp @@ -274,6 +274,7 @@ namespace funkin::modding { lua_Character.set("type", &objects::Character::type); lua_Character.set("barColor", &objects::Character::barColor); lua_Character.set("cameraOffset", &objects::Character::cameraOffset); + lua_Character.set("characterName", &objects::Character::characterName); auto lua_Stage = state.new_usertype("Stage"); lua_Stage.set("stageName", &objects::Stage::stageName); diff --git a/src/funkin/objects/Character.cpp b/src/funkin/objects/Character.cpp index 06cb15f..97de5fc 100644 --- a/src/funkin/objects/Character.cpp +++ b/src/funkin/objects/Character.cpp @@ -6,8 +6,12 @@ namespace funkin::objects { Character::Character(const float x, const float y, const std::string &characterName, const CharacterType type) : Sprite(x, y) { this->characterName = characterName; this->type = type; - - const std::string basePath = "assets/characters/" + characterName; + std::string basePath = "assets/characters/" + characterName; + if(!FileExists(basePath.c_str())){ + TraceLog(5,("Unable to load character '"+this->characterName+"'. Fallbacking to bf").c_str()); + this->characterName="bf"; + basePath = "assets/characters/bf"; + } loadTexture(basePath + "/spritesheet.png"); if (FileExists((basePath + "/spritesheet.txt").c_str())) { @@ -17,7 +21,8 @@ namespace funkin::objects { } if (type == CharacterType::BOYFRIEND) { - barColor = LIME; + barColor = LIME; + flipX = true; } script = std::make_shared(basePath + "/character.lua"); @@ -28,21 +33,13 @@ namespace funkin::objects { bool Character::canDance(const float stepCrochet) const { const auto animationName = getCurrentAnimation()->name; - return (holdTimer > stepCrochet * 0.0011f * singDuration && animationName.starts_with("sing") && !animationName.ends_with("miss") || - holdTimer == 0.0f); + return (holdTimer == 0.0f || + holdTimer > singDuration && animationName.starts_with("sing") && !animationName.ends_with("miss")); } void Character::dance(const bool force) { - if (dancesLeftAndRight) { - if (danced) { - animation.play("danceRight", force); - } else { - animation.play("danceLeft", force); - } - danced = !danced; - } else { - animation.play("idle", force); - } + animation.play(dancesLeftAndRight ? ((danced=!danced) ? "danceLeft" : "danceRight") : "idle", force); + holdTimer = 0.0f; } diff --git a/src/funkin/objects/Character.hpp b/src/funkin/objects/Character.hpp index 58e7f76..d398cb7 100644 --- a/src/funkin/objects/Character.hpp +++ b/src/funkin/objects/Character.hpp @@ -18,7 +18,7 @@ namespace funkin::objects { bool dancesLeftAndRight = false; std::uint8_t danceEvery = 2; float holdTimer = 0.0f; - float singDuration = 4.0f; + float singDuration = 1.0f; CharacterType type = CharacterType::DAD; Color barColor = RED; Vector2 cameraOffset = Vector2Zero(); diff --git a/src/funkin/objects/Stage.cpp b/src/funkin/objects/Stage.cpp index fbe5afc..db4cc56 100644 --- a/src/funkin/objects/Stage.cpp +++ b/src/funkin/objects/Stage.cpp @@ -1,12 +1,20 @@ #include "Stage.hpp" +#include +#include + #include "funkin/modding/LuaScript.hpp" namespace funkin::objects { Stage::Stage(const std::string &stageName, const std::shared_ptr &boyfriend, const std::shared_ptr &dad, const std::shared_ptr &girlfriend) { + this->stageName = stageName; - script = std::make_shared("assets/stages/" + stageName + "/stage.lua"); + if(!FileExists(("assets/stages/" + stageName + "/stage.lua").c_str())){ + TraceLog(5,("Unable to load stage '"+stageName+"'. Fallbacking to mainStage").c_str()); + this->stageName="mainStage"; + } + script = std::make_shared("assets/stages/" + this->stageName + "/stage.lua"); script->set("boyfriend", boyfriend); script->set("dad", dad); script->set("girlfriend", girlfriend); diff --git a/src/funkin/scenes/FreeplayScene.cpp b/src/funkin/scenes/FreeplayScene.cpp index 75690d9..674bceb 100644 --- a/src/funkin/scenes/FreeplayScene.cpp +++ b/src/funkin/scenes/FreeplayScene.cpp @@ -1,63 +1,112 @@ #include "FreeplayScene.hpp" +#include +#include + #include "PlayScene.hpp" +#include "MainMenuScene.hpp" #include "funkin/Game.hpp" #include "funkin/sound/SoundManager.hpp" +#include "funkin/ui/AlphabetList.hpp" +#include "funkin/Text.hpp" +#include "nlohmann/json.hpp" +#include "raylib.h" + +using json = nlohmann::json; namespace funkin::scenes { FreeplayScene::FreeplayScene() = default; - FreeplayScene::~FreeplayScene() { UnloadSound(scrollMenu); }; + FreeplayScene::~FreeplayScene() { }; void FreeplayScene::create() { FunkinScene::create(); - std::vector songList = {"blissful erect", "bonedoggle", "darnell bf mix", "b2llistic", - "spine crusher", "thearchy", "expurgation", "bushwhack"}; + // std::array songList = {"blissful erect", "bonedoggle", "darnell bf mix", "b2llistic", "spine crusher", "thearchy"}; + - scrollMenu = LoadSound("assets/sounds/scrollMenu.ogg"); menuBG = std::make_shared(); menuBG->loadTexture("assets/images/menuDesat.png"); menuBG->screenCenter(); add(menuBG); - songTexts = std::make_shared>(); + songTexts = std::make_shared(); add(songTexts); - - for (auto i = 0; i < songList.size(); i++) { - const auto song = std::make_shared(90, 320, songList[i]); - song->isMenuItem = true; - song->targetY = i; - song->ID = i; + for (const auto &file: std::filesystem::directory_iterator("assets/songs/")) { + auto fileString = file.path().filename(); + const auto song = std::make_shared(90, 320, fileString); songTexts->add(song); + difficulties.push_back({}); } - changeSelection(0); + difficultyText = std::make_shared(0,0,""); + difficultyText->borderSize=2; + add(difficultyText); + + + songTexts->changeSelection(0); + changeDifficulty(0); } void FreeplayScene::update(const float delta) { FunkinScene::update(delta); - if (IsKeyPressed(KEY_DOWN)) { - changeSelection(1); - } else if (IsKeyPressed(KEY_UP)) { - changeSelection(-1); - } else if (GetMouseWheelMove() != 0) { - changeSelection(-static_cast(GetMouseWheelMove())); - } else if (IsKeyPressed(KEY_ENTER)) { - Game::switchScene(std::make_unique(songTexts->members[curSelected]->getText())); + if(songTexts->checkInput()){ + curDifficulty=0; + changeDifficulty(0); + }else if (IsKeyPressed(KEY_LEFT)) { + changeDifficulty(-1); + }else if (IsKeyPressed(KEY_RIGHT)) { + changeDifficulty(1); + }else if (IsKeyPressed(KEY_ENTER)) { + Game::switchScene(std::make_unique(songTexts->getSelected()->getText(),difficulties[songTexts->currentSelected][curDifficulty])); + }else if (IsKeyPressed(KEY_BACKSPACE)) { + Game::switchScene(std::make_unique()); } } - void FreeplayScene::changeSelection(const int change) { - curSelected = static_cast(Wrap(static_cast(curSelected + change), 0, static_cast(songTexts->size()))); - - for (auto i = 0; i < songTexts->size(); i++) { - songTexts->members[i]->targetY = i - curSelected; - } - if (change != 0) { - sound::SoundManager::playSound("assets/sounds/scrollMenu.ogg"); + void FreeplayScene::changeDifficulty(const int change) { + const std::string songName = songTexts->getSelected()->getText(); + std::vector &difficulty_list = difficulties.at(songTexts->currentSelected); + if(difficulty_list.size()==0){ + const std::string path = "assets/songs/"+songName+"/"; + const std::string metadata_path = (path + songName+"-metadata.json"); + if(FileExists(metadata_path.c_str())){ + try{ + auto meta = std::ifstream(metadata_path); + auto parsedMeta = json::parse(meta); + meta.close(); + auto chart_difficulties = parsedMeta["playData"]["difficulties"]; + if(chart_difficulties.size() == 0){throw "Chart has invalid size!";} + for (const std::string &difficulty: chart_difficulties ) { + difficulty_list.push_back(difficulty); + } + }catch(...){ + difficulty_list.clear(); + TraceLog(5,"Unable to load metadata."); + } + }else{ + for (const auto &file: std::filesystem::directory_iterator(path)) { + std::string filename = file.path().filename(); + if(!filename.ends_with(".json") || filename == "events.json") continue; + difficulty_list.push_back(filename); + } + } + if(difficulty_list.size() == 0){ + TraceLog(5,"Unable to get difficulties, using fallback!"); + difficulty_list.push_back("easy"); + difficulty_list.push_back("normal"); + difficulty_list.push_back("hard"); + } + difficulty_list = difficulties.at(songTexts->currentSelected); } + + curDifficulty = static_cast(Wrap(static_cast(curDifficulty + change), 0, static_cast(difficulty_list.size()))); + + if (change != 0) sound::SoundManager::playSound("assets/sounds/scrollMenu.ogg"); + difficultyText->setText(difficulty_list.at(curDifficulty)); + difficultyText->screenCenter(math::Axes::X); + } } // namespace funkin::scenes diff --git a/src/funkin/scenes/FreeplayScene.hpp b/src/funkin/scenes/FreeplayScene.hpp index 332a901..a0ad925 100644 --- a/src/funkin/scenes/FreeplayScene.hpp +++ b/src/funkin/scenes/FreeplayScene.hpp @@ -2,21 +2,27 @@ #include "FunkinScene.hpp" #include "funkin/objects/Alphabet.hpp" +#include "funkin/ui/AlphabetList.hpp" +#include "funkin/Text.hpp" +#include "funkin/utilities/CoolUtil.hpp" +#include "nlohmann/json.hpp" +#include "raylib.h" namespace funkin::scenes { class FreeplayScene : public FunkinScene { public: FreeplayScene(); ~FreeplayScene() override; + int curDifficulty = 0; + std::vector> difficulties = {}; + std::shared_ptr songTexts = std::make_shared(); - int curSelected = 0; std::shared_ptr menuBG = nullptr; - std::shared_ptr> songTexts = nullptr; + std::shared_ptr difficultyText = nullptr; - Sound scrollMenu{}; - void changeSelection(int change); + void changeDifficulty(int change); void update(float delta) override; protected: diff --git a/src/funkin/scenes/FunkinScene.cpp b/src/funkin/scenes/FunkinScene.cpp index cbf966a..043f581 100644 --- a/src/funkin/scenes/FunkinScene.cpp +++ b/src/funkin/scenes/FunkinScene.cpp @@ -1,9 +1,9 @@ #include "FunkinScene.hpp" #include "eventpp/callbacklist.h" +#include "funkin/sound/SoundManager.hpp" namespace funkin::scenes { std::shared_ptr FunkinScene::conductor = std::make_shared(); - FunkinScene::FunkinScene() = default; FunkinScene::~FunkinScene() { conductor->onBeatHit = eventpp::CallbackList(); diff --git a/src/funkin/scenes/MainMenuScene.cpp b/src/funkin/scenes/MainMenuScene.cpp index 0c2e6f7..d4210fb 100644 --- a/src/funkin/scenes/MainMenuScene.cpp +++ b/src/funkin/scenes/MainMenuScene.cpp @@ -4,6 +4,7 @@ #include "PlayScene.hpp" #include "funkin/Game.hpp" #include "funkin/objects/Alphabet.hpp" +#include "funkin/sound/SoundManager.hpp" namespace funkin::scenes { MainMenuScene::MainMenuScene() = default; @@ -65,5 +66,8 @@ namespace funkin::scenes { menuButton->updateHitbox(); menuButton->screenCenter(math::Axes::X); } + if (change != 0) { + sound::SoundManager::playSound("assets/sounds/scrollMenu.ogg"); + } } } // namespace funkin::scenes diff --git a/src/funkin/scenes/PauseSubScene.cpp b/src/funkin/scenes/PauseSubScene.cpp new file mode 100644 index 0000000..d206c8d --- /dev/null +++ b/src/funkin/scenes/PauseSubScene.cpp @@ -0,0 +1,66 @@ +#include "PauseSubScene.hpp" + +#include "PlayScene.hpp" +#include "FunkinScene.hpp" +#include "funkin/Scene.hpp" +#include "MainMenuScene.hpp" +#include "FreeplayScene.hpp" +#include "funkin/ui/AlphabetList.hpp" +#include "funkin/game/Conductor.hpp" +#include "funkin/Game.hpp" +#include "funkin/Group.hpp" +#include "raylib.h" +using Conductor = funkin::game::Conductor; + +namespace funkin::scenes { + PauseSubScene::PauseSubScene(std::string _songName,std::string _difficulty) { + this->songName = _songName; + this->difficulty = _difficulty; + for (size_t i = 0; i < menuOptions.size(); i++) { + menuAlphabets->add(std::make_shared(90, 250, menuOptions[i])); + } + add(menuAlphabets); + menuAlphabets->changeSelection(0); + } + PauseSubScene::~PauseSubScene() {} + void PauseSubScene::close() { + pending_close=true; + Game::defaultCamera->flashAlpha=0.5; + Game::defaultCamera->flashColor=BLACK; + Game::defaultCamera->flashDuration=0.1; + // parentScene->remove(this); + } + void PauseSubScene::restart() { + Game::switchScene(std::make_unique(songName,difficulty)); + } + void PauseSubScene::exit() { + Game::switchScene(std::make_unique()); + } + void PauseSubScene::draw(const float x, const float y, const std::shared_ptr &cam) { + DrawRectangle(0, 0, GetRenderWidth(), GetRenderHeight(), ColorAlpha(BLACK, 0.5)); + Scene::draw(x,y,cam); + } + void PauseSubScene::update(const float delta) { + Scene::update(delta); + menuAlphabets->checkInput(); + if (IsKeyPressed(KEY_ENTER)) { + switch(menuAlphabets->currentSelected){ + case 0:{ + close(); + return; + } + case 1:{ + restart(); + return; + } + case 2:{ + exit(); + return; + } + } + // Game::switchScene(std::make_unique(songTexts->members[curSelected]->getText(),difficulties[curSelected][curDifficulty])); + }else if (IsKeyPressed(KEY_BACKSPACE)) { + exit(); + } + } +} // namespace funkin::scenes diff --git a/src/funkin/scenes/PauseSubScene.hpp b/src/funkin/scenes/PauseSubScene.hpp new file mode 100644 index 0000000..bb04efb --- /dev/null +++ b/src/funkin/scenes/PauseSubScene.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "funkin/Scene.hpp" +#include "funkin/ui/AlphabetList.hpp" +#include "funkin/objects/Alphabet.hpp" +#include "funkin/utilities/CoolUtil.hpp" +#include "funkin/game/Conductor.hpp" +#include "raylib.h" + +using Conductor = funkin::game::Conductor; + +namespace funkin::scenes { + class PauseSubScene : public Scene { + public: + explicit PauseSubScene(std::string _songName,std::string _difficulty); + ~PauseSubScene() override; + + std::string songName; + std::string difficulty; + bool pending_close = false; + std::shared_ptr menuAlphabets = std::make_shared(); + + std::array menuOptions = {"Resume", "Restart", "Main Menu"}; + + void open(); + void close(); + void exit(); + void restart(); + + void update(float delta) override; + void draw(const float x, const float y, const std::shared_ptr &cam) override; + }; +} // namespace funkin::scenes diff --git a/src/funkin/scenes/PlayScene.cpp b/src/funkin/scenes/PlayScene.cpp index d9ef6da..e3e5104 100644 --- a/src/funkin/scenes/PlayScene.cpp +++ b/src/funkin/scenes/PlayScene.cpp @@ -13,7 +13,8 @@ #include "raytween.h" namespace funkin::scenes { - PlayScene::PlayScene(const std::string &songName) { this->songName = songName; }; + + PlayScene::PlayScene(const std::string &songName, const std::string &difficulty) { this->songName = songName; this->difficulty = difficulty; }; PlayScene::~PlayScene() { scripts.clear(); @@ -23,6 +24,8 @@ namespace funkin::scenes { void PlayScene::create() { Scene::create(); + songData = data::Song::parseSong(songName, difficulty); + for (const auto &file: std::filesystem::directory_iterator("assets/songs/" + songName)) { auto fileString = file.path().string(); if (fileString.ends_with(".lua")) { @@ -35,7 +38,6 @@ namespace funkin::scenes { setOnScripts("camHUD", camHUD); - songData = data::Song::parseSong(songName, "hard"); events = songData.events; inst = LoadMusicStream(("assets/songs/" + songName + "/Inst.ogg").c_str()); @@ -238,20 +240,32 @@ namespace funkin::scenes { } void PlayScene::update(const float delta) { + if(pauseSubScene != nullptr){ + if(!pauseSubScene->pending_close){ + callOnScripts("onPausedUpdate", delta); + pauseSubScene->update(delta); + return; + } + conductor->resume(); + remove(pauseSubScene); + } callOnScripts("onUpdate", delta); + + Scene::update(delta); conductor->update(delta); - - if (IsKeyPressed(KEY_SPACE)) { - if (conductor->playing) { - conductor->pause(); - } else { - conductor->resume(); - } - } else if (IsKeyPressed(KEY_ENTER)) { - Game::switchScene(std::make_unique()); + if(!conductor->playing){ + return; + } + if (IsKeyPressed(KEY_ENTER)) { + conductor->pause(); + pauseSubScene = std::make_unique(songName, difficulty); + pauseSubScene->camera = camHUD; + callOnScripts("onPause"); + add(pauseSubScene); + return; } constexpr float decayRate = 0.95f; diff --git a/src/funkin/scenes/PlayScene.hpp b/src/funkin/scenes/PlayScene.hpp index 9ffd133..0a7209f 100644 --- a/src/funkin/scenes/PlayScene.hpp +++ b/src/funkin/scenes/PlayScene.hpp @@ -8,25 +8,29 @@ #include "funkin/objects/HealthBar.hpp" #include "funkin/objects/Stage.hpp" #include "funkin/objects/notes/PlayField.hpp" +#include "PauseSubScene.hpp" namespace funkin::scenes { using namespace game; class PlayScene : public Scene { + friend class funkin::scenes::PauseSubScene; public: - explicit PlayScene(const std::string &songName); + explicit PlayScene(const std::string &songName,const std::string &difficulty); ~PlayScene() override; std::shared_ptr conductor = nullptr; std::vector tracks = {}; data::SongData songData = {}; std::vector events = {}; + std::string difficulty; std::string songName; Music inst = {}; Music voices = {}; Music voicesPlayer = {}; + std::shared_ptr pauseSubScene = nullptr; std::shared_ptr healthBar = nullptr; std::shared_ptr scoreText = nullptr; std::shared_ptr> comboGroup = nullptr; diff --git a/src/funkin/scenes/TitleScene.cpp b/src/funkin/scenes/TitleScene.cpp index 5115854..0b26b4f 100644 --- a/src/funkin/scenes/TitleScene.cpp +++ b/src/funkin/scenes/TitleScene.cpp @@ -3,6 +3,7 @@ #include "MainMenuScene.hpp" #include "funkin/Game.hpp" #include "funkin/utilities/CoolUtil.hpp" +#include "funkin/sound/SoundManager.hpp" namespace funkin::scenes { bool TitleScene::initialized = false; @@ -125,7 +126,6 @@ namespace funkin::scenes { conductor->tracks.push_back(LoadMusicStream("assets/music/freakyMenu.ogg")); conductor->bpm = 102; conductor->start(); - initialized = true; } @@ -136,7 +136,7 @@ namespace funkin::scenes { skippedIntro = true; remove(newgroundsLogo); remove(textGroup); - Game::defaultCamera->flash(WHITE, initialized ? 1.0f : 4.0f); + Game::defaultCamera->flash(WHITE, 1.0f); add(gfDance); add(logoBumpin); add(pressEnterText); @@ -161,7 +161,11 @@ namespace funkin::scenes { } if(IsKeyPressed(KEY_ENTER)){ if (skippedIntro) { + finishedFadeIn = true; + SetMusicVolume(conductor->tracks[0],1); + sound::SoundManager::playSoundWithoutCaching("assets/sounds/confirmMenu.ogg"); Game::switchScene(std::make_unique()); + }else if (initialized) { skipIntro(); } diff --git a/src/funkin/sound/SoundManager.cpp b/src/funkin/sound/SoundManager.cpp index dd1e166..ea943c3 100644 --- a/src/funkin/sound/SoundManager.cpp +++ b/src/funkin/sound/SoundManager.cpp @@ -16,6 +16,10 @@ namespace funkin::sound { soundAliases.push_back(LoadSoundAlias(soundCache[path])); PlaySound(soundAliases.back()); } + void SoundManager::playSoundWithoutCaching(const std::string &path) { + cacheSound(path); + PlaySound(LoadSound(path.c_str())); + } void SoundManager::cacheSound(const std::string &path) { if (!soundCache.contains(path)) { @@ -31,6 +35,7 @@ namespace funkin::sound { soundAliases.clear(); for (const auto &val: soundCache | std::views::values) { + UnloadSound(val); } soundCache.clear(); diff --git a/src/funkin/sound/SoundManager.hpp b/src/funkin/sound/SoundManager.hpp index 8b78f89..5556497 100644 --- a/src/funkin/sound/SoundManager.hpp +++ b/src/funkin/sound/SoundManager.hpp @@ -13,6 +13,7 @@ namespace funkin::sound { static float checkEvery; static void playSound(const std::string &path); + static void playSoundWithoutCaching(const std::string &path); static void cacheSound(const std::string &path); static void clearCache(); diff --git a/src/funkin/ui/AlphabetList.cpp b/src/funkin/ui/AlphabetList.cpp new file mode 100644 index 0000000..b2b9bc1 --- /dev/null +++ b/src/funkin/ui/AlphabetList.cpp @@ -0,0 +1,63 @@ +#include "AlphabetList.hpp" +#include "funkin/Group.hpp" +#include "funkin/sound/SoundManager.hpp" + +using Alphabet = funkin::objects::Alphabet; + +namespace funkin { + AlphabetList::AlphabetList(const float x,const float y) : Group(x, y) {} + AlphabetList::AlphabetList() : Group(0, 0) {} + + AlphabetList::~AlphabetList() = default; + + void AlphabetList::update(float delta) { + Group::update(delta); + } + void AlphabetList::add(std::shared_ptr object) { + members.push_back(object); + alphabetMembers.push_back(object); + object->isMenuItem=true; + object->targetY = object->ID = members.size(); + } + + std::shared_ptr AlphabetList::getSelected() const { + return alphabetMembers[currentSelected]; + } + void AlphabetList::remove(std::shared_ptr object) { + if (auto ranges = std::ranges::find(members, object); ranges != members.end()) { + members.erase(ranges); + } + if (auto ranges = std::ranges::find(alphabetMembers, object); ranges != alphabetMembers.end()) { + alphabetMembers.erase(ranges); + } + changeSelection(0); + } + bool AlphabetList::checkInput() { + if (IsKeyPressed(KEY_DOWN)) { + changeSelection(1); + return true; + }else if (IsKeyPressed(KEY_UP)) { + changeSelection(-1); + return true; + }else if (GetMouseWheelMove() != 0){ + changeSelection(-static_cast(GetMouseWheelMove())); + return true; + } + return false; + } + void AlphabetList::changeSelection(const int change) { + currentSelected = static_cast(Wrap(static_cast(currentSelected + change), 0, static_cast(alphabetMembers.size()))); + if(change != 0) sound::SoundManager::playSound("assets/sounds/scrollMenu.ogg"); + + int i = 0; + for (auto member: alphabetMembers) { + if (member != nullptr) { + member->targetY=i-this->currentSelected; + member->visible=member->targetY > -10 && member->targetY < 10; + member->alpha=(member->targetY == 0 ? 1.0 : 0.8); + i++; + } + } + + } +} // namespace funkin diff --git a/src/funkin/ui/AlphabetList.hpp b/src/funkin/ui/AlphabetList.hpp new file mode 100644 index 0000000..e32c85c --- /dev/null +++ b/src/funkin/ui/AlphabetList.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "funkin/Group.hpp" +#include "funkin/objects/Alphabet.hpp" + +using Alphabet = funkin::objects::Alphabet; + +namespace funkin { + class AlphabetList : public Group<> { + public: + AlphabetList(const float x,const float y); + explicit AlphabetList(); + ~AlphabetList() override; + + void update(float delta) override; + + + void add(const std::shared_ptr object); + void remove(const std::shared_ptr object); + void changeSelection(const int change); + bool checkInput(); + std::shared_ptr getSelected() const; + + + int currentSelected = 0; + /* TODO: This should be implemented better*/ + std::vector> alphabetMembers = {}; + + // protected: + // virtual void create(); + }; +} // namespace funkin