/* =========================================================================== * Saland Adventures Copyright (C) 2014-2018 Poul Sander This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ Source information and contacts persons can be found at https://github.com/sago007/saland =========================================================================== */ #include #include #include #include "sago/SagoDataHolder.hpp" #include "sago/SagoSpriteHolder.hpp" #include "sago/GameStateInterface.hpp" #include "sago/SagoTextField.hpp" #include #include #include #include #include #include #include #include #include #include "saland/globals.hpp" #include "saland/Game.hpp" #include "sago/SagoMisc.hpp" #include "sago/platform_folders.h" #include "sagotmx/tmx_struct.h" #include "sago/SagoTextBox.hpp" #include "MenuSystem.h" #include "common.h" #include "os.hpp" #include "version.h" GlobalData globalData; class TitleScreen : public sago::GameStateInterface { public: TitleScreen() { textField.SetHolder(globalData.dataHolder); textField.SetFontSize(30); textBox.SetHolder(globalData.dataHolder); textBox.SetFontSize(16); testBox.SetHolder(globalData.dataHolder); testBox.SetFontSize(16); } virtual bool IsActive() override { return isActive; } virtual void Draw(SDL_Renderer* target) override { textField.SetText("Saland Adventures - The game that has a very long subtitle to test the outline"); textField.SetOutline(3, SDL_Color{255,165,0,255}); textField.Draw(target, 10, 10); textBox.SetText("This is an attempt to create 2d rpg with a modifiable world.\nLet's see how it goes!"); textBox.SetOutline(1, SDL_Color{255,0,0,255}); textBox.SetMaxWidth(800); textBox.Draw(target, 300,300); testBox.SetText("a\xe6\x97\xa5\xd1\x88\xc3\x86"); testBox.SetMaxWidth(1); testBox.Draw(target, 300,500); circleRGBA(target, 150, 150, 75, 0, 0, 255, 255); const sago::SagoSprite& s = globalData.spriteHolder->GetSprite("male_walkcycle_E"); s.Draw(globalData.screen, SDL_GetTicks(), 100, 100); const sago::SagoSprite& sc = globalData.spriteHolder->GetSprite("female_spellcast_E"); sc.Draw(globalData.screen, SDL_GetTicks(), 200, 100); const sago::SagoSprite& bee = globalData.spriteHolder->GetSprite("bee_E"); bee.Draw(globalData.screen, SDL_GetTicks(), 100, 200); const sago::SagoSprite& bat = globalData.spriteHolder->GetSprite("bat_W"); bat.Draw(globalData.screen, SDL_GetTicks(), 200, 200); } virtual void ProcessInput(const SDL_Event& event, bool &processed) override { if ( event.type == SDL_KEYDOWN ) { if (event.key.keysym.sym == SDLK_RETURN) { isActive = false; processed = true; } } } virtual void Update() override { } private: bool isActive = true; sago::SagoTextField textField; sago::SagoTextBox textBox; sago::SagoTextBox testBox; }; /** * This function reads the mouse coordinates from a relevant event. * Unlike SDL_GetMouseState this works even if SDL_RenderSetLogicalSize is used * @param event * @param mousex * @param mousey */ void UpdateMouseCoordinates(const SDL_Event& event, int& mousex, int& mousey) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: mousex = event.button.x; mousey = event.button.y; break; case SDL_MOUSEMOTION: mousex = event.motion.x; mousey = event.motion.y; break; default: break; } } void ResetFullscreen(); void RunGameState(sago::GameStateInterface& state ) { bool done = false; //We are done! while (!done && !globalData.isShuttingDown) { if (globalData.resetVideo) { ResetFullscreen(); globalData.resetVideo = false; } SDL_SetRenderDrawColor(globalData.screen, 0, 0, 0, 0); SDL_RenderClear(globalData.screen); state.Draw(globalData.screen); SDL_Delay(1); SDL_Event event; while ( SDL_PollEvent(&event) ) { if ( event.type == SDL_QUIT ) { globalData.isShuttingDown = true; done = true; } if (event.type == SDL_WINDOWEVENT_RESIZED) { std::cout << event.window.data1 << ", " << event.window.data2 << "\n"; SDL_GetRendererOutputSize(globalData.screen, &globalData.xsize, &globalData.ysize); } if (event.type == SDL_KEYDOWN) { if (!globalData.resetVideo && event.key.keysym.sym == SDLK_RETURN && event.key.keysym.mod & KMOD_LALT) { globalData.fullscreen = !globalData.fullscreen; globalData.resetVideo = true; } } bool processed = false; state.ProcessInput(event, processed); } state.Update(); SDL_RenderPresent(globalData.screen); if (!state.IsActive()) { done = true; } } } void startWorld() { Game g; RunGameState(g); } static SDL_Window* win = nullptr; void ResetFullscreen() { sago::SagoDataHolder& dataHolder = *globalData.dataHolder; Mix_HaltMusic(); //We need to reload all data in case the screen type changes. Music must be stopped before unload. if (globalData.fullscreen) { SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); } else { SDL_SetWindowFullscreen(win, 0); } dataHolder.invalidateAll(globalData.screen); globalData.spriteHolder.reset(new sago::SagoSpriteHolder( dataHolder ) ); SDL_ShowCursor(SDL_ENABLE); SDL_GetRendererOutputSize(globalData.screen, &globalData.xsize, &globalData.ysize); } void toggleFullscreen() { globalData.fullscreen = !globalData.fullscreen; ResetFullscreen(); } void runMenuOptions() { Menu m(globalData.screen, true); Button bFullscreen; bFullscreen.setLabel("Fullscreen"); bFullscreen.setAction(toggleFullscreen); m.addButton(&bFullscreen); RunGameState(m); } void runGame() { int posX = 100, posY = 100, width = 1280, height = 800; SDL_Init(SDL_INIT_VIDEO); IMG_Init(IMG_INIT_PNG); TTF_Init(); Mix_Init(MIX_INIT_OGG); globalData.fullscreen = Config::getInstance()->getInt("fullscreen"); win = SDL_CreateWindow("Saland Adventures", posX, posY, width, height, 0); globalData.screen = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); //SDL_RenderSetLogicalSize(globalData.screen, 1024, 768); sago::SagoDataHolder holder(globalData.screen); globalData.spriteHolder.reset(new sago::SagoSpriteHolder(holder)); globalData.dataHolder = &holder; ResetFullscreen(); TitleScreen ts; RunGameState(ts); standardButton.setSurfaces(); Menu m(globalData.screen, false); Button bStart; bStart.setLabel("Start"); bStart.setAction(startWorld); m.addButton(&bStart); Button bOptions; bOptions.setLabel("Options"); bOptions.setAction(runMenuOptions); m.addButton(&bOptions); while (!globalData.isShuttingDown) { RunGameState(m); } SDL_DestroyRenderer(globalData.screen); SDL_DestroyWindow(win); SDL_Quit(); } int main(int argc, char* argv[]) { PHYSFS_init(argv[0]); PHYSFS_addToSearchPath((std::string(PHYSFS_getBaseDir())+"/data").c_str(), 1); std::string savepath = getPathToSaveFiles(); OsCreateSaveFolder(); PHYSFS_addToSearchPath(savepath.c_str(), 1); PHYSFS_setWriteDir(savepath.c_str()); boost::program_options::options_description desc("Options"); desc.add_options() ("version", "Print version information and quit") ("help,h", "Print basic usage information to stdout and quit") ("fullscreen", "Run in fullscreen") ("no-fullscreen", "Run in window") ; boost::program_options::variables_map vm; boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); boost::program_options::notify(vm); if (vm.count("help")) { std::cout << desc << "\n"; return 0; } if (vm.count("version")) { std::cout << "saland " << VERSION_NUMBER << "\n"; return 0; } if (vm.count("fullscreen")) { Config::getInstance()->setInt("fullscreen", 1); } if (vm.count("no-fullscreen")) { Config::getInstance()->setInt("fullscreen", 0); } runGame(); Config::getInstance()->save(); return 0; }