diff options
author | Clyne Sullivan <tullivan99@gmail.com> | 2016-10-20 08:44:58 -0400 |
---|---|---|
committer | Clyne Sullivan <tullivan99@gmail.com> | 2016-10-20 08:44:58 -0400 |
commit | cb408a63a0f03ccb0b0ce7c338527a3b4964aff9 (patch) | |
tree | c373f7f74d0c1b5c834dccf47b7f3b343a0b870b | |
parent | 4f838cdf582f0ace6d7de8cb376dfce7100fbea3 (diff) |
removed all old entity stuff
-rw-r--r-- | include/entities.hpp.bak (renamed from include/entities.hpp) | 0 | ||||
-rw-r--r-- | include/inventory.hpp.bak (renamed from include/inventory.hpp) | 0 | ||||
-rw-r--r-- | include/mob.hpp.bak (renamed from include/mob.hpp) | 0 | ||||
-rw-r--r-- | include/quest.hpp.bak (renamed from include/quest.hpp) | 0 | ||||
-rw-r--r-- | include/ui.hpp | 8 | ||||
-rw-r--r-- | include/ui_action.hpp.bak (renamed from include/ui_action.hpp) | 0 | ||||
-rw-r--r-- | include/ui_quest.hpp | 4 | ||||
-rw-r--r-- | include/world.hpp | 390 | ||||
-rw-r--r-- | main.cpp | 121 | ||||
-rw-r--r-- | src/engine.cpp | 11 | ||||
-rw-r--r-- | src/entities.cpp.bak (renamed from src/entities.cpp) | 0 | ||||
-rw-r--r-- | src/inventory.cpp.bak (renamed from src/inventory.cpp) | 1 | ||||
-rw-r--r-- | src/items.cpp.bak (renamed from src/items.cpp) | 0 | ||||
-rw-r--r-- | src/mob.cpp.bak (renamed from src/mob.cpp) | 0 | ||||
-rw-r--r-- | src/quest.cpp.bak (renamed from src/quest.cpp) | 17 | ||||
-rw-r--r-- | src/ui.cpp | 303 | ||||
-rw-r--r-- | src/ui_action.cpp.bak (renamed from src/ui_action.cpp) | 0 | ||||
-rw-r--r-- | src/ui_menu.cpp | 1 | ||||
-rw-r--r-- | src/world.cpp | 1244 | ||||
-rw-r--r-- | xml/!town.xml | 10 | ||||
-rw-r--r-- | xml/bobshouse.xml | 4 |
21 files changed, 330 insertions, 1784 deletions
diff --git a/include/entities.hpp b/include/entities.hpp.bak index 945e8c8..945e8c8 100644 --- a/include/entities.hpp +++ b/include/entities.hpp.bak diff --git a/include/inventory.hpp b/include/inventory.hpp.bak index 533318c..533318c 100644 --- a/include/inventory.hpp +++ b/include/inventory.hpp.bak diff --git a/include/mob.hpp b/include/mob.hpp.bak index 24b8ed9..24b8ed9 100644 --- a/include/mob.hpp +++ b/include/mob.hpp.bak diff --git a/include/quest.hpp b/include/quest.hpp.bak index 2db65a2..2db65a2 100644 --- a/include/quest.hpp +++ b/include/quest.hpp.bak diff --git a/include/ui.hpp b/include/ui.hpp index 8671393..c7a69b6 100644 --- a/include/ui.hpp +++ b/include/ui.hpp @@ -21,10 +21,9 @@ // local game headers #include <common.hpp> #include <config.hpp> -#include <entities.hpp> -#include <inventory.hpp> +//#include <inventory.hpp> #include <ui_menu.hpp> -#include <ui_action.hpp> +//#include <ui_action.hpp> // local library headers #include <SDL2/SDL_opengl.h> @@ -71,7 +70,6 @@ namespace ui { extern bool posFlag; extern unsigned char dialogOptChosen; - extern unsigned char merchOptChosen; extern bool dialogBoxExists; extern bool dialogImportant; extern bool dialogPassive; @@ -123,8 +121,6 @@ namespace ui { void drawBox(vec2 c1, vec2 c2); void drawNiceBox(vec2 c1, vec2 c2, float z); void dialogBox(std::string name, std::string opt, bool passive, std::string text, ...); - void merchantBox(const char *name,Trade trade,const char *opt,bool passive,const char *text,...); - void merchantBox(); void closeBox(); void waitForDialog(void); diff --git a/include/ui_action.hpp b/include/ui_action.hpp.bak index a275ab3..a275ab3 100644 --- a/include/ui_action.hpp +++ b/include/ui_action.hpp.bak diff --git a/include/ui_quest.hpp b/include/ui_quest.hpp index 24a5e1b..8582b67 100644 --- a/include/ui_quest.hpp +++ b/include/ui_quest.hpp @@ -27,14 +27,14 @@ namespace ui { ui::putStringCentered(offset.x, top_y - 40, "Current Quests:"); - auto y = top_y - 100; + /*auto y = top_y - 100; const auto x = offset.x - 180; for (const auto &q : player->qh.current) { ui::putText(x, y, q.title.c_str()); y -= 20; ui::putText(x + 40, y, q.desc.c_str()); y -= 40; - } + }*/ std::swap(textWrap, ui::textWrapLimit); } diff --git a/include/world.hpp b/include/world.hpp index dc07267..36ccdfa 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -8,9 +8,13 @@ // local game includes #include <common.hpp> -#include <entities.hpp> #include <coolarray.hpp> +#include <events.hpp> +#include <texture.hpp> +#include <tinyxml2.h> +using namespace tinyxml2; + /** * The background type enum. * This enum contains all different possibilities for world backgrounds; used @@ -44,13 +48,6 @@ typedef struct { } WorldData; /** - * Contains info necessary for switching worlds. - * This pair contains a pointer to the new world, and the new set of - * coordinates the player should be at in that world. - */ -using WorldSwitchInfo = std::pair<World *, vec2>; - -/** * Alters how bright world elements are drawn. * This value is based off of the current time of day (tick count), set in * main.cpp. @@ -95,41 +92,6 @@ constexpr const unsigned int INDOOR_FLOOR_HEIGHTT = 400; */ constexpr const unsigned int INDOOR_FLOOR_HEIGHT = (INDOOR_FLOOR_HEIGHTT + INDOOR_FLOOR_THICKNESS); -/** - * The village class. - * This class defines an area in a world that is considered to be a village, - * and provides a welcome message when the player enters the area. - */ -class Village { -public: - /** - * The name of the village. - */ - std::string name; - - /** - * The start and end coordinates of the village. - */ - vec2 start, end; - - /** - * A "player in village" flag. - * This flag is used to trigger displaying the welcome message. - */ - bool in; - - /** - * Constructs a village with the given name, inside the given world. - */ - Village(std::string meme, World *w); - - /** - * Destructs the village. - */ - ~Village(void){} -}; - - #include <entityx/entityx.h> constexpr const char* WorldWeatherString[3] = { @@ -138,20 +100,45 @@ constexpr const char* WorldWeatherString[3] = { "Snowy" }; +struct WorldData2 { + // data + std::vector<WorldData> data; + float startX; + + // indoor + bool indoor; + float indoorWidth; + GLuint indoorTex; + + // links + std::string toLeft, toRight; + + // style + WorldBGType style; + std::string styleFolder; + std::vector<std::string> sTexLoc; + + // music + std::string bgm; + + // village + float villageStart, villageEnd; +}; + class WorldSystem : public entityx::System<WorldSystem>, public entityx::Receiver<WorldSystem> { private: - World *world; - World *outside; + WorldData2 world; WorldWeather weather; Mix_Music *bgmObj; - std::string bgmObjFile; std::vector<std::string> bgFiles; TextureIterator bgTex; + XMLDocument xmlDoc; + public: explicit WorldSystem(void); ~WorldSystem(void); @@ -160,13 +147,14 @@ public: ev.subscribe<BGMToggleEvent>(*this); } + inline float getWidth(void) const + { return world.startX * -2.0f; } + void receive(const BGMToggleEvent &bte); void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override; void render(void); - void setWorld(World *w); - inline const std::string getWeatherStr(void) const { return WorldWeatherString[static_cast<int>(weather)]; } @@ -175,299 +163,20 @@ public: void setWeather(const std::string &s); - void singleDetect(Entity *e, entityx::TimeDelta dt); void detect(entityx::TimeDelta dt); - void detect2(entityx::TimeDelta dt); - - void enterWorld(World *w); - void leaveWorld(void); -}; - - -/** - * The world class. - * This class handles entity creation, management, and deletion. Most - * world-related operations have to be done through this class, such as - * drawing. - */ -class World { -private: - bool m_Indoor; - -public: - - float HouseWidth; - GLuint houseTex; - - inline bool isIndoor(void) const - { return m_Indoor; } - - WorldBGType bgType; - - std::string styleFolder; + void goWorldLeft(void) {} + void goWorldRight(void) {} - /** - * An array of all the world's ground data, populated through - * World::generate(). - * @see generate() - */ - std::vector<WorldData> worldData; - - /** - * Contains the size of the 'worldData' array. - */ - unsigned int lineCount; - - /** - * The starting x-coordinate of the world. - */ - float worldStart; - - /** - * The path to the XML file of the world to the left. - * - * @see setToLeft() - */ - std::string toLeft; - - /** - * The path to the XML file of the world to the right. - * - * @see setToRight() - */ - std::string toRight; - - /** - * A vector of paths for the structure textures. - * The appearance of structures depends on the world's theme. - * - * @see setStyle() - */ - std::vector<std::string> sTexLoc; - - /** - * Contains randomly generated coordinates for stars. - */ - std::vector<vec2> star; - - /** - * A vector of all light elements in the world. - * - * @see addLight() - * @see getLastLight() - */ - std::vector<Light> light; - - /** - * A vector of all villages in the world. - * - * @see addVillage() - */ - std::vector<Village> village; - - std::vector<Entity *> entityPending; - - /** - * Destroys entities and clears vectors that contain them. - * This function is only called in the world destructor. - */ - void deleteEntities(void); - - /** - * The filename of the world's BGM file. - * - * @see setBGM() - */ - std::string bgm; - - CoolArray<Particles> particles; - - /** - * A vector of pointers to all entities from the other vectors. - * This is used to mass-manage entities, or operate on entities - * outside of what the world does. - * - * @see getNearInteractable() - */ - std::vector<Entity *> entity; - - /** - * Constructs the world, resets variables. - */ - World(bool indoor = false); - - /** - * Destructs the world, frees memory. - */ - virtual ~World(void); - - /** - * Generates a world of the specified width. - * This will populate the 'worldData' array and create star coordinates. - * It's necessary to call this function to actually use the world. - */ - void generate(int width); - - /** - * Draws everything the world handles to the screen (and the player). - * Drawing is based off of the player so that off-screen elements are not - * drawn. - */ - virtual void draw(Player *p); - - /** - * Gets the width of the world, presumably in pixels. - * TODO - */ - int getTheWidth(void) const; - - /** - * Gets the starting x-coordinate of the world. - * - * @see worldStart - */ - float getWorldStart(void) const; - - inline unsigned int getEntityCount(void) const { - return entity.size(); - } + // worlddata2 stuff + WorldData2 worldData; - /** - * Gets a pointer to the most recently created light. - * This is used to update properties of the light outside of the - * world class. - */ - Light& getLastLight(void); + void generate(unsigned int width = 0); + void addHole(const unsigned int& start, const unsigned int& end); + void addHill(const ivec2& peak, const unsigned int& width); - /** - * Gets a pointer ot the most recently created mob. - * This is used to update properties of the mob outside of the - * world class. - */ - Mob* getLastMob(void); - - /** - * Finds the entity nearest to the provided one. - */ - Entity* getNearInteractable(Entity &e); - - /** - * Finds the mob nearest to the given entity. - */ - Mob* getNearMob(Entity &e); - - /** - * Gets the coordinates of the `index`th structure. - */ - vec2 getStructurePos(int index); - - /** - * Gets the texture path of the `index`th structure - */ - std::string getSTextureLocation(unsigned int index) const; - - // saves the world's data to an XML file, either the one provided or the current path - void save(const std::string& s=""); - - // sets the world's background theme - void setBackground(WorldBGType bgt); - - // sets the folder to collect entity textures from - void setStyle(std::string pre); - - // gets the string that represents the current weather - std::string getWeatherStr(void) const; - const WorldWeather& getWeatherId(void) const; - - // sets the weatherrrr - void setWeather(const std::string& w); - - // sets / gets pathnames of XML files for worlds to the left and right - std::string setToLeft(std::string file); - std::string setToRight(std::string file); - std::string getToLeft(void) const; - std::string getToRight(void) const; - - // attempts to enter the left/right adjacent world, returning either that world or this - WorldSwitchInfo goWorldLeft(Player *p); - WorldSwitchInfo goWorldRight(Player *p); - - /** - * Attempts to move an NPC to the left adjacent world, returning true on success. - */ - bool goWorldLeft(NPC *e); - - /** - * Attempts to move an NPC to the world to the right, returning true on success. - */ - bool goWorldRight(NPC *e); - - // attempts to enter a structure that the player would be standing in front of - WorldSwitchInfo goInsideStructure(Player *p); - - /** - * Adopts an NPC from another world, taking its ownership. - */ - void adoptNPC(NPC *e); - - /** - * Adopts a mob from another world, taking its ownership. - */ - void adoptMob(Mob *e); - - // adds a hole at the specified start and end x-coordinates - void addHole(unsigned int start,unsigned int end); - - // adds a hill that peaks at the given coordinate and is `width` HLINEs wide - void addHill(ivec2 peak, unsigned int width); - - // functions to add entities to the world - void addLight(vec2 xy, float radius, Color color); - - void addMerchant(float x, float y, bool housed); - - void addMob(Mob *m, vec2 coord); - - void addNPC(NPC *n); - - void addObject(std::string in, std::string pickupDialog, float x, float y); - - void addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int dur); - void addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int dur, unsigned char flags); - - void addStructure(Structures *s); - - Village *addVillage(std::string name, World *world); -}; - -/** - * The arena class - creates an arena. - * - * This world, when created, expects a pointer to a Mob. This mob will be - * transported to a temporary world with the player, and the Mob will be - * killed upon exiting the arena. - */ - -class Arena : public World { -private: - - // the mob that the player is fighting - Mob *mmob; - -public: - - // creates the arena with the world being left for it - Arena(void); - - // frees memory - ~Arena(void); - - // starts a new fight?? - void fight(World *leave, const Player *p, Mob *m); - - // attempts to exit the arena, returning what world the player should be in - WorldSwitchInfo exitArena(Player *p); + bool save(const std::string& file); + void load(const std::string& file); }; /** @@ -495,13 +204,4 @@ World *loadWorldFromXMLNoTakeover(std::string path); */ World *loadWorldFromPtr(World *ptr); -/** - * Casts a normal world to an indoor world, to access IndoorWorld-exclusive - * elements. - */ -constexpr IndoorWorld *Indoorp(World *w) -{ - return (IndoorWorld *)w; -} - #endif // WORLD_H @@ -21,7 +21,7 @@ using namespace tinyxml2; // local game includes #include <common.hpp> #include <config.hpp> -#include <entities.hpp> +//#include <entities.hpp> #include <world.hpp> #include <ui.hpp> #include <gametime.hpp> @@ -33,23 +33,12 @@ using namespace tinyxml2; ** Variables section ** --------------------------------------------------------------------------*/ -// world objects for the current world and the two that are adjacent -World *currentWorld = NULL, - *currentWorldToLeft = NULL, - *currentWorldToRight = NULL; - -// an arena for fightin' -Arena *arena = nullptr; - // the currently used folder to grab XML files std::string xmlFolder; // the current menu Menu *currentMenu; -// the player object -Player *player; - // keeps a simple palette of colors for single-color draws GLuint colorIndex; @@ -137,13 +126,13 @@ int main(int argc, char *argv[]) game::briceUpdate(); // load sprites used in the inventory menu. See src/inventory.cpp - initInventorySprites(); + //initInventorySprites(); // load mouse texture, and other inventory textures mouseTex = Texture::loadTexture("assets/mouse.png"); - player = new Player(); - player->sspawn(0,100); + //player = new Player(); + //player->sspawn(0,100); // get a world if (xmlFolder.empty()) @@ -197,35 +186,21 @@ int main(int argc, char *argv[]) goto EXIT_ROUTINE; if (!worldActuallyUseThisXMLFile.empty()) { - delete currentWorld; - currentWorld = loadWorldFromXML(worldActuallyUseThisXMLFile); - } else if (currentWorld == nullptr) { - + game::engine.getSystem<WorldSystem>()->load(worldActuallyUseThisXMLFile); + } else { // load the first valid XML file for the world for (const auto &xf : xmlFiles) { if (xf[0] != '.') { // read it in std::cout << "File to load: " << xf << '\n'; - currentWorld = loadWorldFromXML(xf); + game::engine.getSystem<WorldSystem>()->load(xf); break; } } } - // make sure the world was made - if (currentWorld == nullptr) - UserError("Plot twist: The world never existed...?"); - ui::menu::init(); - game::events.emit<BGMToggleEvent>(currentWorld->bgm); - - game::engine.getSystem<WorldSystem>()->setWorld(currentWorld); - - // spawn the arena - arena = new Arena(); - arena->setStyle(""); - arena->setBackground(WorldBGType::Forest); - arena->bgm = "assets/music/embark.wav"; +// game::events.emit<BGMToggleEvent>(currentWorld->bgm); // the main loop, in all of its gloriousness.. std::thread([&]{ @@ -239,7 +214,7 @@ int main(int argc, char *argv[]) std::thread([&]{ while (game::engine.shouldRun()) { fps = 1000 / game::time::getDeltaTime(); - debugY = player->loc.y; +// debugY = player->loc.y; std::this_thread::sleep_for(std::chrono::seconds(1)); } @@ -259,36 +234,24 @@ EXIT_ROUTINE: Mix_HaltMusic(); Mix_CloseAudio(); - destroyInventory(); +// destroyInventory(); ui::destroyFonts(); Texture::freeTextures(); // close up the game stuff - currentWorld->save(); - delete arena; - //delete currentWorld; +// currentWorld->save(); game::engine.getSystem<WindowSystem>()->die(); return 0; // Calls everything passed to atexit } -extern std::vector<NPC *> aipreload; - void mainLoop(void){ game::time::mainLoopHandler(); if (currentMenu) { return; } else { - // Flush preloaded AI functions if necessary - if (!ui::dialogBoxExists) { - while (!aipreload.empty()) { - aipreload.front()->addAIFunc(false); - aipreload.erase(std::begin(aipreload)); - } - } - if (game::time::tickHasPassed()) logic(); @@ -300,18 +263,20 @@ void render() { const auto SCREEN_WIDTH = game::SCREEN_WIDTH; const auto SCREEN_HEIGHT = game::SCREEN_HEIGHT; - offset.x = player->loc.x + player->width / 2; +// offset.x = player->loc.x + player->width / 2; + + auto worldWidth = game::engine.getSystem<WorldSystem>()->getWidth(); // ortho x snapping - if (currentWorld->getTheWidth() < (int)SCREEN_WIDTH) + if (worldWidth < (int)SCREEN_WIDTH) offset.x = 0; - else if (offset.x - SCREEN_WIDTH / 2 < currentWorld->getTheWidth() * -0.5f) - offset.x = ((currentWorld->getTheWidth() * -0.5f) + SCREEN_WIDTH / 2); - else if (offset.x + SCREEN_WIDTH / 2 > currentWorld->getTheWidth() * 0.5f) - offset.x = ((currentWorld->getTheWidth() * 0.5f) - SCREEN_WIDTH / 2); + else if (offset.x - SCREEN_WIDTH / 2 < worldWidth * -0.5f) + offset.x = ((worldWidth * -0.5f) + SCREEN_WIDTH / 2); + else if (offset.x + SCREEN_WIDTH / 2 > worldWidth * 0.5f) + offset.x = ((worldWidth * 0.5f) - SCREEN_WIDTH / 2); // ortho y snapping - offset.y = std::max(player->loc.y + player->height / 2, SCREEN_HEIGHT / 2.0f); + offset.y = /*std::max(player->loc.y + player->height / 2,*/ SCREEN_HEIGHT / 2.0f; /*);*/ // "setup" glm::mat4 projection = glm::ortho(floor(offset.x - SCREEN_WIDTH / 2), // left @@ -343,10 +308,9 @@ void render() { // draw the world and player game::engine.getSystem<WorldSystem>()->render(); - currentWorld->draw(player); // draw the player's inventory - player->inv->draw(); + //player->inv->draw(); // draw the fade overlay ui::drawFade(); @@ -359,21 +323,21 @@ void render() { ui::putText(offset.x-SCREEN_WIDTH/2, (offset.y+SCREEN_HEIGHT/2)-ui::fontSize, "fps: %d\ngrounded:%d\nresolution: %ux%u\nentity cnt: %d\nloc: (%+.2f, %+.2f)\nticks: %u\nvolume: %f\nweather: %s\nxml: %s", fps, - player->ground, + 0,//player->ground, SCREEN_WIDTH, // Window dimensions SCREEN_HEIGHT, // - currentWorld->entity.size(),// Size of entity array - player->loc.x, // The player's x coordinate + 0,//currentWorld->entity.size(),// Size of entity array + 0,//player->loc.x, // The player's x coordinate debugY, // The player's y coordinate game::time::getTickCount(), game::config::VOLUME_MASTER, game::engine.getSystem<WorldSystem>()->getWeatherStr().c_str(), - currentXML.c_str() + ""//currentXML.c_str() ); // draw tracer lines if desired - static const GLuint tracerText = Texture::genColor(Color(100,100,255)); - if (ui::posFlag) { + //static const GLuint tracerText = Texture::genColor(Color(100,100,255)); + /*if (ui::posFlag) { GLfloat *tpoint = new GLfloat[currentWorld->getEntityCount() * 2 * 5]; auto tp = tpoint; @@ -403,7 +367,7 @@ void render() { Render::textShader.unuse(); delete[] tpoint; - } + }*/ } @@ -421,14 +385,14 @@ void render() { } void logic(){ - static bool NPCSelected = false; - static bool ObjectSelected = false; +// static bool NPCSelected = false; +// static bool ObjectSelected = false; // exit the game if the player falls out of the world - if (player->loc.y < 0) - game::endGame(); + /*if (player->loc.y < 0) + game::endGame();*/ - if (player->inv->usingi) { + /*if (player->inv->usingi) { for (auto &e : currentWorld->entity) { if (player->inv->usingi && !e->isHit() && player->inv->detectCollision(vec2 { e->loc.x, e->loc.y }, vec2 { e->loc.x + e->width, e->loc.y + e->height})) { @@ -437,9 +401,9 @@ void logic(){ } } player->inv->usingi = false; - } + }*/ - for (auto &e : currentWorld->entity) { + /*for (auto &e : currentWorld->entity) { if (e->isAlive() && ((e->type == NPCT) || (e->type == MERCHT) || (e->type == OBJECTT))) { if (e->type == OBJECTT && ObjectSelected) { e->near = false; @@ -475,7 +439,7 @@ void logic(){ e->near = player->isNear(e); e->wander(); } - } + }*/ // calculate the world shading value worldShade = 50 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI)); @@ -484,10 +448,11 @@ void logic(){ ui::fadeUpdate(); // create weather particles if necessary - auto weather = game::engine.getSystem<WorldSystem>()->getWeatherId(); + /*auto weather = game::engine.getSystem<WorldSystem>()->getWeatherId(); + auto worldWidth = game::engine.getSystem<WorldSystem>()->getWidth(); if (weather == WorldWeather::Rain) { for (unsigned int r = (randGet() % 25) + 11; r--;) { - currentWorld->addParticle(randGet() % currentWorld->getTheWidth() - (currentWorld->getTheWidth() / 2), + currentWorld->addParticle(randGet() % worldWidth - (worldWidth / 2), offset.y + game::SCREEN_HEIGHT / 2, HLINES(1.25), // width HLINES(1.25), // height @@ -500,7 +465,7 @@ void logic(){ } } else if (weather == WorldWeather::Snowy) { for (unsigned int r = (randGet() % 25) + 11; r--;) { - currentWorld->addParticle(randGet() % currentWorld->getTheWidth() - (currentWorld->getTheWidth() / 2), + currentWorld->addParticle(randGet() % worldWidth - (worldWidth / 2), offset.y + game::SCREEN_HEIGHT / 2, HLINES(1.25), // width HLINES(1.25), // height @@ -511,10 +476,10 @@ void logic(){ 0 // no gravity, no bounce ); } - } + }*/ // increment game ticker game::time::tick(); - NPCSelected = false; - ObjectSelected = false; + //NPCSelected = false; + //ObjectSelected = false; } diff --git a/src/engine.cpp b/src/engine.cpp index 56dee48..3d498d3 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -3,8 +3,7 @@ #include <config.hpp> #include <world.hpp> #include <ui.hpp> -#include <inventory.hpp> -#include <entities.hpp> +//#include <inventory.hpp> #include <window.hpp> extern World *currentWorld; @@ -20,9 +19,9 @@ void Engine::init(void) { systems.add<WindowSystem>(); systems.add<InputSystem>(); - systems.add<InventorySystem>(); +// systems.add<InventorySystem>(); systems.add<WorldSystem>(); - systems.add<PlayerSystem>(&player); +// systems.add<PlayerSystem>(&player); systems.configure(); @@ -37,8 +36,8 @@ void Engine::render(entityx::TimeDelta dt) void Engine::update(entityx::TimeDelta dt) { systems.update<InputSystem>(dt); - systems.update<InventorySystem>(dt); - systems.update<PlayerSystem>(dt); +// systems.update<InventorySystem>(dt); +// systems.update<PlayerSystem>(dt); systems.update<WorldSystem>(dt); } diff --git a/src/entities.cpp b/src/entities.cpp.bak index e005df5..e005df5 100644 --- a/src/entities.cpp +++ b/src/entities.cpp.bak diff --git a/src/inventory.cpp b/src/inventory.cpp.bak index f7a8df7..1b325c0 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp.bak @@ -2,7 +2,6 @@ #include <numeric> -#include <entities.hpp> #include <gametime.hpp> #include <render.hpp> diff --git a/src/items.cpp b/src/items.cpp.bak index 180c5fa..180c5fa 100644 --- a/src/items.cpp +++ b/src/items.cpp.bak diff --git a/src/mob.cpp b/src/mob.cpp.bak index e78e5cd..e78e5cd 100644 --- a/src/mob.cpp +++ b/src/mob.cpp.bak diff --git a/src/quest.cpp b/src/quest.cpp.bak index aa0bb2e..f19359e 100644 --- a/src/quest.cpp +++ b/src/quest.cpp.bak @@ -1,9 +1,6 @@ #include <algorithm>
#include <quest.hpp>
-#include <entities.hpp>
-
-extern Player *player;
int QuestHandler::assign(std::string title,std::string desc,std::string req) {
Quest tmp;
@@ -43,15 +40,15 @@ int QuestHandler::drop(std::string title) { int QuestHandler::finish(std::string t) {
for (auto c = current.begin(); c != current.end(); c++) {
if ((*c).title == t) {
- for (auto &n : (*c).need) {
- if (player->inv->hasItem(n.first) < n.second)
+ //for (auto &n : (*c).need) {
+ //if (player->inv->hasItem(n.first) < n.second)
return 0;
- }
+ //}
- for (auto &n : (*c).need)
- player->inv->takeItem(n.first, n.second);
- current.erase(c);
- return 1;
+ //for (auto &n : (*c).need)
+ //player->inv->takeItem(n.first, n.second);
+ //current.erase(c);
+ //return 1;
}
}
@@ -13,21 +13,6 @@ extern Menu* currentMenu; extern SDL_Window *window; -/** - * External references for updating player coords / current world. - */ - -extern Player *player; -extern World *currentWorld; -extern World *currentWorldToLeft; -extern World *currentWorldToRight; - -/** - * Pressing ESC or closing the window will set this to false. - */ -extern bool gameRunning; - - std::array<SDL_Keycode, 6> controlMap = { SDLK_w, SDLK_a, SDLK_d, SDLK_LSHIFT, SDLK_LCTRL, SDLK_e }; @@ -79,7 +64,6 @@ static std::vector<std::pair<vec2, std::string>> textToDraw; static std::vector<std::pair<std::string,vec3>> dialogOptText; static std::string dialogBoxText; -static std::vector<vec3> merchArrowLoc (2, vec3 { 0, 0, 0 }); static bool typeOutDone = true; static bool typeOutSustain = false; @@ -183,7 +167,6 @@ namespace ui { bool dialogPassive = false; bool dialogMerchant = false; int dialogPassiveTime = 0; - Trade merchTrade; int fontTransInv = 255; @@ -194,7 +177,6 @@ namespace ui { bool dialogBoxExists = false; bool dialogImportant = false; unsigned char dialogOptChosen = 0; - unsigned char merchOptChosen = 0; unsigned int textWrapLimit = 0; @@ -582,54 +564,6 @@ namespace ui { ret.clear(); } - void merchantBox(const char *name,Trade trade,const char *opt,bool passive,const char *text,...) { - va_list dialogArgs; - std::unique_ptr<char[]> printfbuf (new char[512]); - - dialogPassive = passive; - merchTrade = trade; - - // clear the buffer - dialogBoxText.clear(); - dialogBoxText = (std::string)name + ": "; - - va_start(dialogArgs,text); - vsnprintf(printfbuf.get(),512,text,dialogArgs); - va_end(dialogArgs); - dialogBoxText += printfbuf.get(); - - // free old option text - dialogOptText.clear(); - - dialogOptChosen = 0; - merchOptChosen = 0; - - // handle options if desired - if (opt) { - std::string soptbuf = opt; - char *sopt = strtok(&soptbuf[0], ":"); - - // cycle through options - while(sopt) { - dialogOptText.push_back(std::make_pair((std::string)sopt, vec3 {0,0,0})); - sopt = strtok(NULL,":"); - } - } - - // allow box to be displayed - dialogBoxExists = true; - dialogImportant = false; - dialogMerchant = true; - textWrapLimit = 50; - - ret.clear(); - } - - void merchantBox() { - textWrapLimit = 50; - dialogMerchant = true; - } - /** * Wait for a dialog box to be dismissed. */ @@ -904,7 +838,7 @@ namespace ui { auto SCREEN_HEIGHT = static_cast<float>(game::SCREEN_HEIGHT); // will return if not toggled - action::draw(vec2 {player->loc.x + player->width / 2, player->loc.y + player->height + game::HLINE}); + //action::draw(vec2 {player->loc.x + player->width / 2, player->loc.y + player->height + game::HLINE}); // will return if not toggled quest::draw(); @@ -960,132 +894,6 @@ namespace ui { putStringCentered(offset.x,offset.y,rtext); setFontSize(16); } - }else if (dialogMerchant) { - x = offset.x - SCREEN_WIDTH / 6; - y = (offset.y + SCREEN_HEIGHT / 2) - HLINES(8); - - drawNiceBox(vec2(x, y), vec2(x + (SCREEN_WIDTH / 3.0f), y - (SCREEN_HEIGHT * 0.6f)), -7.0f); - // draw typeOut'd text - putString(x + game::HLINE, y - fontSize - game::HLINE, (rtext = typeOut(dialogBoxText))); - - std::string itemString1 = std::to_string(merchTrade.quantity[0]) + "x", - itemString2 = std::to_string(merchTrade.quantity[1]) + "x"; - - vec2 merchBase = {offset.x, offset.y + SCREEN_HEIGHT / 5}; - - putStringCentered(merchBase.x + SCREEN_WIDTH / 10 - 20, merchBase.y + 40 + fontSize * 2, itemString1); - putStringCentered(merchBase.x + SCREEN_WIDTH / 10 - 20, merchBase.y + 40 + fontSize , merchTrade.item[0]); - putStringCentered(merchBase.x - SCREEN_WIDTH / 10 , merchBase.y + 40 + fontSize * 2, itemString2); - putStringCentered(merchBase.x - SCREEN_WIDTH / 10 , merchBase.y + 40 + fontSize , merchTrade.item[1]); - putStringCentered(offset.x, merchBase.y + 60, "for"); - - // render the two items we are trading - GLfloat item_tex[] = {0.0, 1.0, - 1.0, 1.0, - 1.0, 0.0, - - 1.0, 0.0, - 0.0, 0.0, - 0.0, 1.0}; - - GLfloat left_item[] = {offset.x - (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5), -7.2, - offset.x - (SCREEN_WIDTH / 10) + 40, offset.y + (SCREEN_HEIGHT / 5), -7.2, - offset.x - (SCREEN_WIDTH / 10) + 40, offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2, - - offset.x - (SCREEN_WIDTH / 10) + 40, offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2, - offset.x - (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2, - offset.x - (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5), -7.2}; - - GLfloat right_item[] = {offset.x + (SCREEN_WIDTH / 10) - 40, offset.y + (SCREEN_HEIGHT / 5), -7.2, - offset.x + (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5), -7.2, - offset.x + (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2, - - offset.x + (SCREEN_WIDTH / 10), offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2, - offset.x + (SCREEN_WIDTH / 10) - 40, offset.y + (SCREEN_HEIGHT / 5) + 40,-7.2, - offset.x + (SCREEN_WIDTH / 10) - 40, offset.y + (SCREEN_HEIGHT / 5), -7.2}; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, getItemTexture(merchTrade.item[1])); - glUniform1i(Render::textShader.uniform[WU_texture], 0); - - Render::textShader.use(); - Render::textShader.enable(); - - glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, left_item); - glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, item_tex); - glDrawArrays(GL_TRIANGLES, 0 ,6); - - glBindTexture(GL_TEXTURE_2D, getItemTexture(merchTrade.item[0])); - - glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, right_item); - glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, item_tex); - glDrawArrays(GL_TRIANGLES, 0 ,6); - - Render::textShader.disable(); - Render::textShader.unuse(); - - merchArrowLoc[0].x = offset.x - (SCREEN_WIDTH / 8.5) - 16; - merchArrowLoc[1].x = offset.x + (SCREEN_WIDTH / 8.5) + 16; - merchArrowLoc[0].y = offset.y + (SCREEN_HEIGHT *.2); - merchArrowLoc[1].y = offset.y + (SCREEN_HEIGHT *.2); - merchArrowLoc[0].z = offset.x - (SCREEN_WIDTH / 8.5); - merchArrowLoc[1].z = offset.x + (SCREEN_WIDTH / 8.5); - - for(i = 0; i < 2; i++) { - if (((merchArrowLoc[i].x < merchArrowLoc[i].z) ? - (mouse.x > merchArrowLoc[i].x && mouse.x < merchArrowLoc[i].z) : - (mouse.x < merchArrowLoc[i].x && mouse.x > merchArrowLoc[i].z)) && - mouse.y > merchArrowLoc[i].y - 8 && mouse.y < merchArrowLoc[i].y + 8) { - glColor3ub(255,255, 0); - glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255,255,0))); - }else{ - glColor3ub(255,255,255); - glBindTexture(GL_TEXTURE_2D, Texture::genColor(Color(255,255,255))); - } - - GLfloat tri_t[] = {0.0, 0.0, - 0.0, 1.0, - 1.0, 1.0}; - - GLfloat tri_c[] = {merchArrowLoc[i].x, merchArrowLoc[i].y, -7.1, - merchArrowLoc[i].z, merchArrowLoc[i].y - 8, -7.1, - merchArrowLoc[i].z, merchArrowLoc[i].y + 8, -7.1}; - - glUniform1i(Render::textShader.uniform[WU_texture], 0); - - Render::textShader.use(); - Render::textShader.enable(); - - glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, tri_c); - glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tri_t); - glDrawArrays(GL_TRIANGLES, 0 ,6); - - Render::textShader.disable(); - Render::textShader.unuse(); - } - - - // draw / handle dialog options if they exist - for(i = 0; i < dialogOptText.size(); i++) { - setFontColor(255, 255, 255); - - // draw option - dialogOptText[i].second.y = y - SCREEN_HEIGHT / 2 - (fontSize + game::HLINE) * (i + 1); - tmp = putStringCentered(offset.x, dialogOptText[i].second.y, dialogOptText[i].first); - - // get coordinate information on option - dialogOptText[i].second.z = offset.x + tmp; - dialogOptText[i].second.x = offset.x - tmp; - - // make text yellow if the mouse hovers over the text - if (mouse.x > dialogOptText[i].second.x && mouse.x < dialogOptText[i].second.z && - mouse.y > dialogOptText[i].second.y && mouse.y < dialogOptText[i].second.y + 16) { - setFontColor(255, 255, 0); - putStringCentered(offset.x, dialogOptText[i].second.y, dialogOptText[i].first); - } - } - - setFontColor(255, 255, 255); } else { //normal dialog box x = offset.x - SCREEN_WIDTH / 2 + HLINES(8); @@ -1125,15 +933,15 @@ namespace ui { } if (!fadeIntensity) { - vec2 hub = { + /*vec2 hub = { (SCREEN_WIDTH/2+offset.x)-fontSize*10, (offset.y+SCREEN_HEIGHT/2)-fontSize - }; + };*/ - putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0, + /*putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0, (unsigned)player->maxHealth - ); - static GLuint frontHealth = Texture::genColor(Color(255,0,0)); + );*/ + /*static GLuint frontHealth = Texture::genColor(Color(255,0,0)); static GLuint backHealth = Texture::genColor(Color(150,0,0)); if (player->isAlive()) { @@ -1174,13 +982,13 @@ namespace ui { Render::textShader.disable(); Render::textShader.unuse(); - } + }*/ /* * Lists all of the quests the player is currently taking. */ - setFontColor(255,255,255,fontTransInv); + /*setFontColor(255,255,255,fontTransInv); if (player->inv->invOpen) { hub.y = player->loc.y + fontSize * 8; hub.x = player->loc.x;// + player->width / 2; @@ -1201,7 +1009,7 @@ namespace ui { hub.x = offset.x - SCREEN_WIDTH/2 + 45*4*1.5; putStringCentered(hub.x,hub.y,"Inventory:"); - } + }*/ setFontColor(255,255,255,255); } } @@ -1248,26 +1056,8 @@ namespace ui { } } - if (dialogMerchant) { - for (i = 0; i < merchArrowLoc.size(); i++) { - - // TODO neaten this if statement - - if (((merchArrowLoc[i].x < merchArrowLoc[i].z) ? - (mouse.x > merchArrowLoc[i].x && mouse.x < merchArrowLoc[i].z) : - (mouse.x < merchArrowLoc[i].x && mouse.x > merchArrowLoc[i].z) && - mouse.y > merchArrowLoc[i].y - 8 && mouse.y < merchArrowLoc[i].y + 8)) { - merchOptChosen = i + 1; - goto EXIT; - } - } - } - - EXIT: - //if (!dialogMerchant)closeBox(); dialogBoxExists = false; - dialogMerchant = false; // handle important text if (dialogImportant) { @@ -1441,18 +1231,12 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, auto SCREEN_WIDTH = game::SCREEN_WIDTH; auto SCREEN_HEIGHT = game::SCREEN_HEIGHT; - Mob *m; // ;lkjfdsa - Entity *ent; // used for interaction - SDL_Event e; // update mouse coords mouse.x = premouse.x + offset.x - (SCREEN_WIDTH / 2); mouse.y = (offset.y + SCREEN_HEIGHT / 2) - premouse.y; - static vec2 fr; - static Entity *ig; - while(SDL_PollEvent(&e)) { switch(e.type) { @@ -1467,21 +1251,13 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, premouse.y=e.motion.y; break; - case SDL_MOUSEBUTTONUP: - if (ig) { - ig->vel.x = (fr.x - mouse.x) / 50.0f; - ig->vel.y = (fr.y - mouse.y) / 50.0f; - //ig->forcedMove = true; // kills vel.x too quickly - ig = NULL; - } - break; + //case SDL_MOUSEBUTTONUP: - // mouse clicks case SDL_MOUSEBUTTONDOWN: // run actions? - if ((action::make = e.button.button & SDL_BUTTON_RIGHT)) - /*player->inv->invHover =*/ edown = false; + //if ((action::make = e.button.button & SDL_BUTTON_RIGHT)) + // /*player->inv->invHover =*/ edown = false; textToDraw.clear(); @@ -1492,31 +1268,13 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, } else { // left click uses item if (e.button.button & SDL_BUTTON_LEFT) { - if ((ent = currentWorld->getNearMob(*player)) != nullptr) { + /*if ((ent = currentWorld->getNearMob(*player)) != nullptr) { player->inv->currentAddInteract(ent); } - player->inv->useCurrent(); + player->inv->useCurrent();*/ } } - - if(mouse.x > player->loc.x && mouse.x < player->loc.x + player->width && - mouse.y > player->loc.y && mouse.y < player->loc.y + player->height) { - player->vel.y = .05; - fr = mouse; - ig = player; - } else { - for (auto &e : currentWorld->entity) { - if (mouse.x > e->loc.x && mouse.x < e->loc.x + e->width && - mouse.y > e->loc.y && mouse.y < e->loc.y + e->height) { - e->vel.y = .05; - fr = mouse; - ig = e; - break; - } - } - } - break; case SDL_MOUSEWHEEL: @@ -1534,13 +1292,16 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, case SDL_KEYUP: ev.emit<KeyUpEvent>(SDL_KEY); + if (SDL_KEY == SDLK_ESCAPE) + ui::menu::toggle(); + if (SDL_KEY == SDLK_q) { - auto item = player->inv->getCurrentItem(); + /*auto item = player->inv->getCurrentItem(); if (item != nullptr) { if (player->inv->takeItem(item->name, 1) == 0) currentWorld->addObject(item->name, "o shit waddup", player->loc.x + player->width / 2, player->loc.y + player->height / 2); - } + }*/ } else if (SDL_KEY == SDLK_h) { quest::toggle(); } else switch (SDL_KEY) { @@ -1550,30 +1311,10 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, case SDLK_BACKSLASH: dialogBoxExists = false; break; - case SDLK_x: - m = currentWorld->getNearMob(*player); - if (m != nullptr) - m->ride(player); - break; - case SDLK_l: - currentWorld->addLight({player->loc.x + SCREEN_WIDTH/2, player->loc.y}, 300.0f, {1.0f,1.0f,1.0f}); - currentWorld->getLastLight().follow(player); - currentWorld->getLastLight().makeFlame(); - break; - case SDLK_f: - currentWorld->addLight({player->loc.x, player->loc.y}, 300.0f, {1.0f,1.0f,1.0f}); - break; case SDLK_b: if (debug) posFlag ^= true; - else { - auto s = new Structures(); - s->spawn(FIRE_PIT, player->loc.x, player->loc.y); - //currentWorld->addStructure(s); - //currentWorld->addLight({player->loc.x + SCREEN_WIDTH/2, player->loc.y}, 400.0f, {1.0f,1.0f,1.0f}); - //currentWorld->getLastLight()->follow(currentWorld->build.back()); - //currentWorld->getLastLight()->makeFlame(); - } + break; case SDLK_F12: // Make the BYTE array, factor of 3 because it's RBG. @@ -1585,10 +1326,10 @@ void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, std::cout << "Took screenshot" << std::endl; break; case SDLK_UP: - player->inv->setSelectionUp(); + //player->inv->setSelectionUp(); break; case SDLK_DOWN: - player->inv->setSelectionDown(); + //player->inv->setSelectionDown(); break; default: break; diff --git a/src/ui_action.cpp b/src/ui_action.cpp.bak index 9029907..9029907 100644 --- a/src/ui_action.cpp +++ b/src/ui_action.cpp.bak diff --git a/src/ui_menu.cpp b/src/ui_menu.cpp index 4b4b05c..cbe7718 100644 --- a/src/ui_menu.cpp +++ b/src/ui_menu.cpp @@ -2,6 +2,7 @@ #include <engine.hpp> #include <render.hpp> +#include <texture.hpp> #include <fstream> diff --git a/src/world.cpp b/src/world.cpp index ef9969f..2772160 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -47,12 +47,6 @@ void makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions_Ju ** Variables section ** --------------------------------------------------------------------------*/ -// external variables -extern Player *player; // main.cpp? -extern World *currentWorld; // main.cpp -extern World *currentWorldToLeft; // main.cpp -extern World *currentWorldToRight; // main.cpp -extern bool inBattle; // ui.cpp? extern std::string xmlFolder; // particle mutex @@ -73,9 +67,6 @@ constexpr const unsigned int GRASS_HEIGHT = 4; // the path of the currently loaded XML file, externally referenced in places std::string currentXML; -// keeps track of information of worlds the player has left to enter arenas -static std::vector<WorldSwitchInfo> arenaNest; - // pathnames of images for world themes using StyleList = std::array<std::string, 9>; @@ -120,88 +111,29 @@ XMLDocument currentXMLDoc; ** Functions section ** --------------------------------------------------------------------------*/ -/** - * Creates a world object. - * Note that all this does is nullify a pointer... - */ -World::World(bool indoor) - : m_Indoor(indoor), lineCount(0), worldStart(0) -{ -} - -/** - * The world destructor. - * This will free objects used by the world itself, then free the vectors of - * entity-related objects. - */ -World:: -~World(void) -{ - deleteEntities(); -} - -/** - * The entity vector destroyer. - * This function will free all memory used by all entities, and then empty the - * vectors they were stored in. - */ -template<class T> -void clearPointerVector(T &vec) -{ - while (!vec.empty()) { - delete vec.back(); - vec.pop_back(); - } -} - -void World:: -deleteEntities(void) -{ - // free particles - particles.clear(); - // clear light array - light.clear(); - // free villages - village.clear(); - // clear entity array - clearPointerVector(entity); -} - -/** - * Generates a world of the specified width. - * This will mainly populate the WorldData array, preparing most of the world - * object for usage. - */ -void World:: -generate(int width) +void WorldSystem::generate(unsigned int width) { float geninc = 0; - // check for valid width - if (width <= 0) - UserError("Invalid world dimensions"); - // allocate space for world - worldData = std::vector<WorldData> (width + GROUND_HILLINESS, WorldData { false, {0, 0}, 0, 0 }); - lineCount = worldData.size(); + world.data = std::vector<WorldData> (width + GROUND_HILLINESS, WorldData { false, {0, 0}, 0, 0 }); // prepare for generation - worldData.front().groundHeight = GROUND_HEIGHT_INITIAL; - auto wditer = std::begin(worldData) + GROUND_HILLINESS; - - if (m_Indoor) { - for(wditer = std::begin(worldData); wditer < std::end(worldData); wditer++) { - auto w = &*(wditer); - w->groundHeight = GROUND_HEIGHT_MINIMUM + 5; - w->groundColor = 4; + world.data[0].groundHeight = GROUND_HEIGHT_INITIAL; + auto wditer = std::begin(world.data) + GROUND_HILLINESS; + + if (world.indoor) { + for (auto &l : world.data) { + l.groundHeight = GROUND_HEIGHT_MINIMUM + 5; + l.groundColor = 4; } } else { // give every GROUND_HILLINESSth entry a groundHeight value - for (; wditer < std::end(worldData); wditer += GROUND_HILLINESS) + for (; wditer < std::end(world.data); wditer += GROUND_HILLINESS) wditer[-static_cast<int>(GROUND_HILLINESS)].groundHeight = wditer[0].groundHeight + (randGet() % 8 - 4); // create slopes from the points that were just defined, populate the rest of the WorldData structure - for (wditer = std::begin(worldData) + 1; wditer < std::end(worldData); wditer++){ + for (wditer = std::begin(world.data) + 1; wditer < std::end(world.data); wditer++){ auto w = &*(wditer); if (w->groundHeight != 0) @@ -216,585 +148,22 @@ generate(int width) } // define x-coordinate of world's leftmost 'line' - worldStart = (width - GROUND_HILLINESS) * game::HLINE / 2 * -1; - - // create empty star array, should be filled here as well... - star = std::vector<vec2> (100, vec2 { 0, 400 }); - for (auto &s : star) { - s.x = (randGet() % (static_cast<int>(-worldStart) * 2)) + worldStart; - s.y = (randGet() % game::SCREEN_HEIGHT) + 100; - } + world.startX = (width - GROUND_HILLINESS) * game::HLINE / 2 * -1; } static Color ambient; -void World::draw(Player *p) -{ - auto HLINE = game::HLINE; - - uint ls = light.size(); - - GLfloat *lightCoords = new GLfloat[ls * 4]; - GLfloat *lightColors = new GLfloat[ls * 4]; - - uint lpIndex = 0; - uint lcIndex = 0; - - static bool ambientUpdaterStarted = false; - if (!ambientUpdaterStarted) { - ambientUpdaterStarted = true; - std::thread([&](void) { - while (true) { - float v = 75 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI)); - float rg = std::clamp(.5f + (-v / 100.0f), 0.01f, .9f); - float b = std::clamp(.5f + (-v / 80.0f), 0.03f, .9f); - - ambient = Color(rg, rg, b, 1.0f); - - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - }).detach(); - } - - for (uint i = 0; i < ls; i++) { - auto &l = light[i]; - if (l.belongsTo) { - l.loc.x = l.following->loc.x; - l.loc.y = l.following->loc.y; - } - if (l.flame) { - l.fireFlicker = 0.9f + ((rand()% 2 ) / 10.0f); - l.fireLoc.x = l.loc.x + (rand() % 2 - 1) * 3; - l.fireLoc.y = l.loc.y + (rand() % 2 - 1) * 3; - } else { - l.fireFlicker = 1; - } - - lightCoords[lpIndex++] = l.loc.x; - lightCoords[lpIndex++] = l.loc.y; - lightCoords[lpIndex++] = 0.0; - lightCoords[lpIndex++] = l.radius; - - lightColors[lcIndex++] = l.color.red; - lightColors[lcIndex++] = l.color.green; - lightColors[lcIndex++] = l.color.blue; - lightColors[lcIndex++] = 1.0; - } - - Render::worldShader.use(); - - glUniform4fv(Render::worldShader.uniform[WU_light], ls, lightCoords); - glUniform4fv(Render::worldShader.uniform[WU_light_color], ls, lightColors); - glUniform1i(Render::worldShader.uniform[WU_light_size], ls); - - Render::worldShader.unuse(); - - for (auto &e :entity) - e->draw(); - - // flatten grass under the player if the player is on the ground - if (p->ground) { - int pOffset = (p->loc.x + p->width / 2 - worldStart) / HLINE; - - for (unsigned int i = 0; i < worldData.size(); i++) - worldData[i].grassUnpressed = !(i < static_cast<unsigned int>(pOffset + 6) && i > static_cast<unsigned int>(pOffset - 6)); - } else { - for (auto &wd : worldData) - wd.grassUnpressed = true; - } - - // draw the player - //p->draw(); - - // draw particles like a MASTAH - glBindTexture(GL_TEXTURE_2D, colorIndex); - glUniform1i(Render::worldShader.uniform[WU_texture], 0); - Render::worldShader.use(); - - glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, .8); - - Render::worldShader.enable(); - - partMutex.lock(); - uint ps = particles.size(); - uint pss = ps * 6 * 5; - uint pc = 0; - - std::vector<GLfloat> partVec(pss); - auto *pIndex = &partVec[0]; - for (uint i = 0; i < ps; i++) { - pc += 30; - if (pc > pss) { - // TODO resize the vector or something better than breaking - break; - } - particles[i].draw(pIndex); - } - partMutex.unlock(); - - glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &partVec[0]); - glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &partVec[3]); - glDrawArrays(GL_TRIANGLES, 0, ps * 6); - - Render::worldShader.disable(); - - glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0); - - Render::worldShader.unuse(); -} - -/** - * Get's the world's width in pixels. - */ -int World:: -getTheWidth(void) const -{ - return (worldStart * -2); -} - -float World:: -getWorldStart(void) const -{ - return static_cast<float>(worldStart); -} - -/** - * Get a pointer to the most recently created light. - * Meant to be non-constant. - */ -Light& World:: -getLastLight(void) -{ - return light.back(); -} - -/** - * Get a pointer to the most recently created mob. - * Meant to be non-constant. - */ -Mob* World:: -getLastMob(void) -{ - for (auto e = entity.rbegin(); e != entity.rend(); ++e) { - if ((*e)->type == MOBT) - return dynamic_cast<Mob *>(*e); - } - - return nullptr; -} - -/** - * Get the interactable entity that is closest to the entity provided. - */ -Entity* World:: -getNearInteractable(Entity &e) -{ - auto n = std::find_if(std::begin(entity), std::end(entity), [&](Entity *&a) { - return ((a->type == MOBT) || (a->type == NPCT) || a->type == MERCHT) && - e.isNear(a) && (e.left ? (a->loc.x < e.loc.x) : (a->loc.x > e.loc.x)); - }); - - return n == std::end(entity) ? nullptr : *n; -} - -Mob* World:: -getNearMob(Entity &e) -{ - auto n = std::find_if(std::begin(entity), std::end(entity), [&](Entity *a) { - return (a->type == MOBT && e.isNear(a) && (e.left ? (a->loc.x < e.loc.x + e.width / 2) : (a->loc.x + a->width > e.loc.x + e.width / 2))); - }); - - return (n == std::end(entity)) ? nullptr : dynamic_cast<Mob *>(*n); -} - - -/** - * Get the file path for the `index`th building. - */ -std::string World:: -getSTextureLocation(unsigned int index) const -{ - return index < sTexLoc.size() ? sTexLoc[ index ] : ""; -} - -/** - * Get the coordinates of the `index`th building, with -1 meaning the last building. - */ -vec2 World:: -getStructurePos(int index) -{ - if (index < 0) { - for (auto e = entity.rbegin(); e != entity.rend(); ++e) { - if ((*e)->type == STRUCTURET) - return (*e)->loc; - } - - return vec2 {0, 0}; - } - - int nth = 0; - for (const auto &e : entity) { - if (e->type == STRUCTURET) { - if (index == nth) - return e->loc; - else - ++nth; - } - } - - return vec2 {0, 0}; -} - -/** - * Saves world data to a file. - */ -void World::save(const std::string& s) +bool WorldSystem::save(const std::string& s) { - for (const auto &e : entity) + (void)s; + /*for (const auto &e : entity) e->saveToXML(); - currentXMLDoc.SaveFile((s.empty() ? currentXML : xmlFolder + s).c_str(), false); -} - -/** - * Sets the desired theme for the world's background. - * The images chosen for the background layers are selected depending on the - * world's background type. - */ -void World::setBackground(WorldBGType bgt) -{ - bgType = bgt; -} - -/** - * Sets the world's style. - * The world's style will determine what sprites are used for things like\ - * generic structures. - */ -void World::setStyle(std::string pre) -{ - // get folder prefix - std::string prefix = pre.empty() ? "assets/style/classic/" : pre; - styleFolder = prefix + "bg/"; - - for (const auto &s : buildPaths) - sTexLoc.push_back(prefix + s); -} - -/** - * Pretty self-explanatory. - */ -std::string World::setToLeft(std::string file) -{ - return (toLeft = file); -} - -/** - * Pretty self-explanatory. - */ -std::string World::setToRight(std::string file) -{ - return (toRight = file); -} - -/** - * Pretty self-explanatory. - */ -std::string World::getToLeft(void) const -{ - return toLeft; -} - -/** - * Pretty self-explanatory. - */ -std::string World::getToRight(void) const -{ - return toRight; -} - -/** - * Attempts to go to the left world, returning either that world or itself. - */ -WorldSwitchInfo World::goWorldLeft(Player *p) -{ - World *tmp; - // check if player is at world edge - if (!toLeft.empty() && p->loc.x < worldStart + HLINES(15)) { - // load world (`toLeft` conditional confirms existance) - tmp = loadWorldFromPtr(currentWorldToLeft); - - // return pointer and new player coords - return std::make_pair(tmp, vec2 {tmp->worldStart + tmp->getTheWidth() - (float)HLINES(15), - tmp->worldData[tmp->lineCount - 1].groundHeight}); - } - - return std::make_pair(this, vec2 {0, 0}); -} - -/** - * Attempts to go to the right world, returning either that world or itself. - */ -WorldSwitchInfo World::goWorldRight(Player *p) -{ - World *tmp; - if (!toRight.empty() && p->loc.x + p->width > -worldStart - HLINES(15)) { - tmp = loadWorldFromPtr(currentWorldToRight); - return std::make_pair(tmp, vec2 {tmp->worldStart + (float)HLINES(15.0), GROUND_HEIGHT_MINIMUM} ); - } - - return std::make_pair(this, vec2 {0, 0}); -} - -void World::adoptNPC(NPC *e) -{ - entity.push_back(e); -} - -void World::adoptMob(Mob* e) -{ - entity.push_back(e); -} - -/** - * Acts like goWorldLeft(), but takes an NPC; returning true on success. - */ -bool World::goWorldLeft(NPC *e) -{ - // check if entity is at world edge - if (!toLeft.empty() && e->loc.x < worldStart + HLINES(15)) { - currentWorldToLeft->adoptNPC(e); - - entity.erase(std::find(std::begin(entity), std::end(entity), e)); - - e->loc.x = currentWorldToLeft->worldStart + currentWorldToLeft->getTheWidth() - HLINES(15); - e->loc.y = GROUND_HEIGHT_MAXIMUM; - ++e->outnabout; - - return true; - } - - return false; -} - -bool World::goWorldRight(NPC *e) -{ - if (!toRight.empty() && e->loc.x + e->width > -worldStart - HLINES(15)) { - currentWorldToRight->adoptNPC(e); - - entity.erase(std::find(std::begin(entity), std::end(entity), e)); - - e->loc.x = currentWorldToRight->worldStart + HLINES(15); - e->loc.y = GROUND_HEIGHT_MINIMUM; - --e->outnabout; - - return true; - } + currentXMLDoc.SaveFile((s.empty() ? currentXML : xmlFolder + s).c_str(), false);*/ return false; } -/** - * Attempts to enter a building that the player is standing in front of. - */ -WorldSwitchInfo World::goInsideStructure(Player *p) -{ - World *tmp; - static std::string outdoorData, outdoorName; - - // enter a building - if (outdoorName.empty()) { - auto d = std::find_if(std::begin(entity), std::end(entity), [p](const Entity *s) { - return ((p->loc.x > s->loc.x) && (p->loc.x + p->width < s->loc.x + s->width)); - }); - - if ((d == std::end(entity)) || dynamic_cast<Structures *>(*d)->inside.empty()) - return std::make_pair(this, vec2 {0, 0}); - - outdoorData = currentXMLRaw; - outdoorName = currentXML; - currentXML = xmlFolder + dynamic_cast<Structures *>(*d)->inside; - const char *buf = readFile(currentXML.c_str()); - currentXMLRaw = buf; - delete[] buf; - - tmp = dynamic_cast<Structures *>(*d)->insideWorld; - tmp->houseTex = dynamic_cast<Structures *>(*d)->insideTex; - - return std::make_pair(tmp, vec2 {0, 100}); - } - - // exit the building - else { - std::string current = ¤tXML[xmlFolder.size()]; - currentXML = outdoorName; - currentXMLRaw = outdoorData; - outdoorName.clear(); - outdoorData.clear(); - - /*tmp = dynamic_cast<IndoorWorld *>(currentWorld)->outside; //loadWorldFromXML(inside.back()); - - Structures *b = nullptr; - for (auto &s : tmp->entity) { - if (s->type == STRUCTURET && dynamic_cast<Structures *>(s)->inside == current) { - b = dynamic_cast<Structures *>(s); - break; - } - } - - if (b == nullptr)*/ - return std::make_pair(currentWorld, vec2 {0, 100}); - - //return std::make_pair(tmp, vec2 {b->loc.x + (b->width / 2), 0}); - } - - return std::make_pair(this, vec2 {0, 0}); -} - -void World:: -addStructure(Structures *s) -{ - entityPending.push_back(s); -} - -Village *World:: -addVillage(std::string name, World *world) -{ - village.emplace_back(name, world); - return &village.back(); -} - -void World::addMob(Mob *m, vec2 coord) -{ - m->spawn(coord.x, coord.y); - - entityPending.push_back(m); -} - -void World:: -addNPC(NPC *n) -{ - entityPending.push_back(n); -} - -void World:: -addMerchant(float x, float y, bool housed) -{ - Merchant *tmp = new Merchant(); - - tmp->spawn(x, y); - - if (housed) { - tmp->inside = dynamic_cast<Structures *>(*std::find_if(entity.rbegin(), entity.rend(), [&](Entity *e){ return (e->type == STRUCTURET); })); - tmp->z = tmp->inside->z + 0.1f; - } - - entityPending.push_back(tmp); -} - -void World:: -addObject(std::string in, std::string p, float x, float y) -{ - Object *tmp = new Object(in, p); - tmp->spawn(x, y); - - entityPending.push_back(tmp); -} - -void World:: -addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d) -{ - particles.push_back(Particles(x, y, w, h, vx, vy, color, d)); - particles.back().canMove = true; -} - -void World:: -addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d, unsigned char flags) -{ - particles.push_back(Particles(x, y, w, h, vx, vy, color, d)); - particles.back().canMove = true; - particles.back().gravity = flags & (1 << 0); - particles.back().bounce = flags & (1 << 1); -} - -void World:: -addLight(vec2 loc, float radius, Color color) -{ - if (light.size() < 128) - light.emplace_back(loc, radius, color); -} - -void World:: -addHole(unsigned int start, unsigned int end) -{ - end = fmin(worldData.size(), end); - - for (unsigned int i = start; i < end; i++) - worldData[i].groundHeight = 0; -} - -void World:: -addHill(const ivec2 peak, const unsigned int width) -{ - int start = peak.x - width / 2, - end = start + width, - offset = 0; - const float thing = peak.y - worldData[std::clamp(start, 0, static_cast<int>(lineCount))].groundHeight; - const float period = PI / width; - - if (start < 0) { - offset = -start; - start = 0; - } - - end = fmin(worldData.size(), end); - - for (int i = start; i < end; i++) { - worldData[i].groundHeight += thing * sin((i - start + offset) * period); - if (worldData[i].groundHeight > peak.y) - worldData[i].groundHeight = peak.y; - } -} - -Arena::Arena(void) -{ - generate(800); - addMob(new Door(), vec2 {100, 100}); - mmob = nullptr; -} - -Arena::~Arena(void) -{ - if (mmob != nullptr) - mmob->die(); - deleteEntities(); -} - -void Arena::fight(World *leave, const Player *p, Mob *m) -{ - inBattle = true; - - entity.push_back((mmob = m)); - mmob->aggressive = false; - - arenaNest.emplace_back(leave, p->loc); -} - -WorldSwitchInfo Arena::exitArena(Player *p) -{ - if (!mmob->isAlive() && - p->loc.x + p->width / 2 > mmob->loc.x && - p->loc.x + p->width / 2 < mmob->loc.x + HLINES(12)) { - auto ret = arenaNest.back(); - arenaNest.pop_back(); - inBattle = !(arenaNest.empty()); - - return ret; - } - - return std::make_pair(this, vec2 {0, 0}); -} - -static bool loadedLeft = false; +/*static bool loadedLeft = false; static bool loadedRight = false; World *loadWorldFromXML(std::string path) { @@ -823,10 +192,6 @@ World *loadWorldFromPtr(World *ptr) return ptr; } -/** - * Loads a world from the given XML file. - */ - World * loadWorldFromXMLNoTakeover(std::string path) { @@ -835,7 +200,110 @@ loadWorldFromXMLNoTakeover(std::string path) loadedLeft = false, loadedRight = false; return ret; } +*/ + +void WorldSystem::load(const std::string& file) +{ + std::string xmlRaw; + std::string xmlPath; + + // check for empty file name + if (file.empty()) + return; + + // load file data to string + xmlPath = xmlFolder + file; + auto xmlRawData = readFile(xmlPath.c_str()); + xmlRaw = xmlRawData; + delete[] xmlRawData; + + // let tinyxml parse the file + if (xmlDoc.Parse(xmlRaw.data()) != XML_NO_ERROR) + UserError("XML Error: Failed to parse file (not your fault though..?)"); + + // look for an opening world tag + auto wxml = xmlDoc.FirstChildElement("World"); + if (wxml != nullptr) { + wxml = wxml->FirstChildElement(); + world.indoor = false; + } else { + wxml = xmlDoc.FirstChildElement("IndoorWorld"); + if (wxml != nullptr) { + wxml = wxml->FirstChildElement(); + world.indoor = true; + } else { + UserError("XML Error: Cannot find a <World> or <IndoorWorld> tag in " + xmlPath); + } + } + + // iterate through tags + while (wxml) { + std::string tagName = wxml->Name(); + + // style tag + if (tagName == "style") { + world.styleFolder = wxml->StrAttribute("folder"); + + unsigned int styleNo; + if (wxml->QueryUnsignedAttribute("background", &styleNo) != XML_NO_ERROR) + UserError("XML Error: No background given in <style> in " + xmlPath); + + world.style = static_cast<WorldBGType>(styleNo); + world.bgm = wxml->StrAttribute("bgm"); + + bgFiles.clear(); + + const auto& files = bgPaths[(int)world.style]; + + for (const auto& f : files) + bgFiles.push_back(world.styleFolder + "bg/" + f); + + bgTex = TextureIterator(bgFiles); + } + + // world generation + else if (tagName == "generation") { + generate(wxml->UnsignedAttribute("width") / game::HLINE); + } + + // indoor stuff + else if (tagName == "house") { + if (!world.indoor) + UserError("<house> can only be used inside <IndoorWorld>"); + + world.indoorWidth = wxml->FloatAttribute("width"); + world.indoorTex = Texture::loadTexture(wxml->Attribute("texture")); + } + + // weather tag + else if (tagName == "weather") { + setWeather(wxml->GetText()); + } + + // link tags + else if (tagName == "link") { + auto linkTo = wxml->Attribute("left"); + if (linkTo != nullptr) { + world.toLeft = linkTo; + } else { + linkTo = wxml->Attribute("right"); + if (linkTo != nullptr) + world.toRight = linkTo; + else + UserError("<link> doesn't handle left or right... huh"); + } + } + + // time setting + else if (tagName == "time") { + game::time::setTickCount(std::stoi(wxml->GetText())); + } + + wxml = wxml->NextSiblingElement(); + } +} +/* World * loadWorldFromXMLNoSave(std::string path) { XMLDocument *_currentXMLDoc; @@ -852,45 +320,6 @@ loadWorldFromXMLNoSave(std::string path) { const char *ptr; std::string name, sptr; - // no file? -> no world - if (path.empty()) - return nullptr; - - _currentXML = xmlFolder + path; - const char *worthless = readFile(_currentXML.c_str()); - _currentXMLRaw = worthless; - delete[] worthless; - - // create a temporary XMLDocument if this isn't the main world - if (!loadedLeft && !loadedRight) - _currentXMLDoc = ¤tXMLDoc; - else - _currentXMLDoc = new XMLDocument(); - - // parse the file - if (_currentXMLDoc->Parse(_currentXMLRaw.data()) != XML_NO_ERROR) - UserError("XML Error: Failed to parse file (not your fault though..?)"); - - // attempt to load a <World> tag - if ((wxml = _currentXMLDoc->FirstChildElement("World"))) { - wxml = wxml->FirstChildElement(); - vil = _currentXMLDoc->FirstChildElement("World")->FirstChildElement("village"); - tmp = new World(); - Indoor = false; - } - - // attempt to load an <IndoorWorld> tag - else if ((wxml = _currentXMLDoc->FirstChildElement("IndoorWorld"))) { - wxml = wxml->FirstChildElement(); - vil = NULL; - tmp = new World(true); - Indoor = true; - } - - // error: can't load a world... - else - UserError("XML Error: Cannot find a <World> or <IndoorWorld> tag in " + _currentXML + "!"); - // iterate through world tags while (wxml) { newEntity = nullptr; @@ -940,38 +369,6 @@ loadWorldFromXMLNoSave(std::string path) { } - // style tags - else if (name == "style") { - // set style folder - tmp->setStyle(wxml->StrAttribute("folder")); - - // set background folder - unsigned int bgt; - if (wxml->QueryUnsignedAttribute("background", &bgt) != XML_NO_ERROR) - UserError("XML Error: No background given in <style> in " + _currentXML + "!"); - tmp->setBackground(static_cast<WorldBGType>(bgt)); - - // set BGM file - tmp->bgm = wxml->StrAttribute("bgm"); - } - - // world generation (for outdoor areas) - else if (name == "generation") { - tmp->generate(wxml->UnsignedAttribute("width") / game::HLINE); - } - - else if (name == "house") { - if (Indoor) - tmp->HouseWidth = wxml->FloatAttribute("width"); - else - UserError("<house> can only be used with indoor worlds"); - } - - // weather tags - else if (name == "weather") { - game::engine.getSystem<WorldSystem>()->setWeather(wxml->GetText()); - } - // set spawn x for player else if (name == "spawnx" && !(loadedLeft | loadedRight)) { player->loc.x = std::stoi(wxml->GetText()); @@ -1009,11 +406,6 @@ loadWorldFromXMLNoSave(std::string path) { tmp->addHill(ivec2 { wxml->IntAttribute("peakx"), wxml->IntAttribute("peaky") }, wxml->UnsignedAttribute("width")); } - // time setting - else if (name == "time" && !(loadedLeft | loadedRight)) { - game::time::setTickCount(std::stoi(wxml->GetText())); - } - if (newEntity != nullptr) { //bool alive = true; //if (wxml->QueryBoolAttribute("alive", &alive) != XML_NO_ERROR || alive) { @@ -1053,9 +445,7 @@ loadWorldFromXMLNoSave(std::string path) { while(vil) { name = vil->Name(); - /** - * READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE - */ + //READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE if (name == "structure") { s = new Structures(); @@ -1147,17 +537,7 @@ loadWorldFromXMLNoSave(std::string path) { } return tmp; -} - -Village::Village(std::string meme, World *w) - : name(meme) -{ - start.x = w->getTheWidth() / 2.0f; - end.x = -start.x; - in = false; -} - - +}*/ WorldSystem::WorldSystem(void) : weather(WorldWeather::None), bgmObj(nullptr) {} @@ -1169,68 +549,6 @@ WorldSystem::~WorldSystem(void) Mix_FreeMusic(bgmObj); } -void WorldSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) -{ - (void)en; - (void)ev; - (void)dt; - - // fade in music if not playing - if (bgmObj != nullptr && !Mix_PlayingMusic()) - Mix_FadeInMusic(bgmObj, -1, 2000); - - // update player coords - player->loc.y += player->vel.y * dt; - player->loc.x += (player->vel.x * player->speed) * dt; - - // update entity coords - for (auto &e : world->entity) { - // dont let structures move? - if (e->type != STRUCTURET && e->canMove) { - e->loc.x += e->vel.x * dt; - e->loc.y += e->vel.y * dt; - - // update boolean directions - e->left = e->vel.x ? (e->vel.x < 0) : e->left; - } else if (e->vel.y < 0) { - e->loc.y += e->vel.y * dt; - } - } - - partMutex.lock(); - // iterate through particles - world->particles.remove_if([](const Particles &part) { - return part.duration <= 0; - }); - - for (auto &pa : world->particles) { - if (pa.canMove) { // causes overhead - pa.loc.y += pa.vel.y * dt; - pa.loc.x += pa.vel.x * dt; - - if (pa.stu != nullptr) { - if (pa.loc.x >= pa.stu->loc.x && pa.loc.x <= pa.stu->loc.x + pa.stu->width && - pa.loc.y <= pa.stu->loc.y + pa.stu->height * 0.25f) - pa.duration = 0; - } - } - } - partMutex.unlock(); - - // add entities if need be - auto& entityPending = world->entityPending; - - if (!entityPending.empty()) { - while (entityPending.size() > 0) { - world->entity.push_back(entityPending.back()); - entityPending.pop_back(); - } - } - - // run detect stuff - detect(dt); -} - void WorldSystem::render(void) { const auto SCREEN_WIDTH = game::SCREEN_WIDTH; @@ -1241,18 +559,32 @@ void WorldSystem::render(void) static_cast<int>(SCREEN_WIDTH) / 2, static_cast<int>(SCREEN_HEIGHT) / 2 }; - auto& worldData = currentWorld->worldData; - auto& star = currentWorld->star; - auto worldStart = currentWorld->worldStart; - int iStart, iEnd, pOffset; // world width in pixels - int width = worldData.size() * HLINE; + int width = world.data.size() * HLINE; // used for alpha values of background textures int alpha; + + static bool ambientUpdaterStarted = false; + if (!ambientUpdaterStarted) { + ambientUpdaterStarted = true; + std::thread([&](void) { + while (true) { + float v = 75 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI)); + float rg = std::clamp(.5f + (-v / 100.0f), 0.01f, .9f); + float b = std::clamp(.5f + (-v / 80.0f), 0.03f, .9f); + + ambient = Color(rg, rg, b, 1.0f); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + }).detach(); + } + + switch (weather) { case WorldWeather::Snowy: alpha = 150; @@ -1348,7 +680,7 @@ void WorldSystem::render(void) makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions(0, fron_tex_coord, tex_coord, 6); // TODO make stars dynamic - static GLuint starTex = Texture::loadTexture("assets/style/classic/bg/star.png"); + /*static GLuint starTex = Texture::loadTexture("assets/style/classic/bg/star.png"); const static float stardim = 24; GLfloat star_coord[star.size() * 5 * 6 + 1]; GLfloat *si = &star_coord[0]; @@ -1374,7 +706,7 @@ void WorldSystem::render(void) glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.3 - static_cast<float>(alpha)/255.0f); makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions(5 * sizeof(GLfloat), &star_coord[0], &star_coord[3], star.size() * 6); - } + }*/ Render::worldShader.disable(); @@ -1389,7 +721,7 @@ void WorldSystem::render(void) bgTex++; dim2 mountainDim = bgTex.getTextureDim(); auto xcoord = width / 2 * -1 + offset.x * 0.85f; - for (unsigned int i = 0; i <= worldData.size() * HLINE / mountainDim.x; i++) { + for (int i = 0; i <= width / mountainDim.x; i++) { bg_items.emplace_back(mountainDim.x * i + xcoord, GROUND_HEIGHT_MINIMUM, 8.0f); bg_items.emplace_back(mountainDim.x * (i + 1) + xcoord, GROUND_HEIGHT_MINIMUM, 8.0f); bg_items.emplace_back(mountainDim.x * (i + 1) + xcoord, GROUND_HEIGHT_MINIMUM + mountainDim.y, 8.0f); @@ -1420,18 +752,20 @@ void WorldSystem::render(void) bg_items.clear(); bg_tex.clear(); - if (world->isIndoor() && i == 3) { - glBindTexture(GL_TEXTURE_2D, world->houseTex); + if (world.indoor && i == 3) { + glBindTexture(GL_TEXTURE_2D, world.indoorTex); - bg_items.emplace_back(worldStart, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); - bg_items.emplace_back(worldStart + world->HouseWidth, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); - bg_items.emplace_back(worldStart + world->HouseWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); + const auto& startx = world.startX; - bg_items.emplace_back(worldStart + world->HouseWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); - bg_items.emplace_back(worldStart, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); - bg_items.emplace_back(worldStart, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); + bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); + bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); + bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); + + bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); + bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); + bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); } else { - for (int j = worldStart; j <= -worldStart; j += dim.x) { + for (int j = world.startX; j <= -world.startX; j += dim.x) { bg_items.emplace_back(j + xcoord, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); bg_items.emplace_back(j + dim.x + xcoord, GROUND_HEIGHT_MINIMUM, 7-(i*.1)); bg_items.emplace_back(j + dim.x + xcoord, GROUND_HEIGHT_MINIMUM + dim.y, 7-(i*.1)); @@ -1462,38 +796,38 @@ void WorldSystem::render(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // get the line that the player is currently standing on - pOffset = (offset.x + player->width / 2 - worldStart) / HLINE; + pOffset = 200;//(offset.x + player->width / 2 - worldStart) / HLINE; // only draw world within player vision iStart = std::clamp(static_cast<int>(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS), - 0, static_cast<int>(world->lineCount)); + 0, static_cast<int>(world.data.size())); iEnd = std::clamp(static_cast<int>(pOffset + (SCREEN_WIDTH / 2 / HLINE)), - 0, static_cast<int>(world->lineCount)); + 0, static_cast<int>(world.data.size())); // draw the dirt bgTex++; std::vector<std::pair<vec2,vec3>> c; for (int i = iStart; i < iEnd; i++) { - if (worldData[i].groundHeight <= 0) { // TODO holes (andy) - worldData[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1; + if (world.data[i].groundHeight <= 0) { // TODO holes (andy) + world.data[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1; glColor4ub(0, 0, 0, 255); } else { safeSetColorA(150, 150, 150, 255); } - int ty = worldData[i].groundHeight / 64 + worldData[i].groundColor; + int ty = world.data[i].groundHeight / 64 + world.data[i].groundColor; - c.push_back(std::make_pair(vec2(0, 0), vec3(worldStart + HLINES(i), worldData[i].groundHeight - GRASS_HEIGHT, -4.0f))); - c.push_back(std::make_pair(vec2(1, 0), vec3(worldStart + HLINES(i) + HLINE, worldData[i].groundHeight - GRASS_HEIGHT, -4.0f))); - c.push_back(std::make_pair(vec2(1, ty),vec3(worldStart + HLINES(i) + HLINE, 0, -4.0f))); + c.push_back(std::make_pair(vec2(0, 0), vec3(world.startX + HLINES(i), world.data[i].groundHeight - GRASS_HEIGHT, -4.0f))); + c.push_back(std::make_pair(vec2(1, 0), vec3(world.startX + HLINES(i) + HLINE, world.data[i].groundHeight - GRASS_HEIGHT, -4.0f))); + c.push_back(std::make_pair(vec2(1, ty),vec3(world.startX + HLINES(i) + HLINE, 0, -4.0f))); - c.push_back(std::make_pair(vec2(1, ty),vec3(worldStart + HLINES(i) + HLINE, 0, -4.0f))); - c.push_back(std::make_pair(vec2(0, ty),vec3(worldStart + HLINES(i), 0, -4.0f))); - c.push_back(std::make_pair(vec2(0, 0), vec3(worldStart + HLINES(i), worldData[i].groundHeight - GRASS_HEIGHT, -4.0f))); + c.push_back(std::make_pair(vec2(1, ty),vec3(world.startX + HLINES(i) + HLINE, 0, -4.0f))); + c.push_back(std::make_pair(vec2(0, ty),vec3(world.startX + HLINES(i), 0, -4.0f))); + c.push_back(std::make_pair(vec2(0, 0), vec3(world.startX + HLINES(i), world.data[i].groundHeight - GRASS_HEIGHT, -4.0f))); - if (worldData[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1) - worldData[i].groundHeight = 0; + if (world.data[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1) + world.data[i].groundHeight = 0; } std::vector<GLfloat> dirtc; @@ -1520,7 +854,7 @@ void WorldSystem::render(void) Render::worldShader.disable(); Render::worldShader.unuse(); - if (!world->isIndoor()) { + if (!world.indoor) { bgTex++; safeSetColorA(255, 255, 255, 255); @@ -1529,7 +863,7 @@ void WorldSystem::render(void) std::vector<GLfloat> grasst; for (int i = iStart; i < iEnd; i++) { - auto wd = worldData[i]; + auto wd = world.data[i]; auto gh = wd.grassHeight; // flatten the grass if the player is standing on it. @@ -1540,6 +874,8 @@ void WorldSystem::render(void) // actually draw the grass. if (wd.groundHeight) { + const auto& worldStart = world.startX; + c.push_back(std::make_pair(vec2(0, 0),vec3(worldStart + HLINES(i) , wd.groundHeight + gh[0], -3))); c.push_back(std::make_pair(vec2(1, 0),vec3(worldStart + HLINES(i) + HLINE / 2, wd.groundHeight + gh[0], -3))); c.push_back(std::make_pair(vec2(1, 1),vec3(worldStart + HLINES(i) + HLINE / 2, wd.groundHeight - GRASS_HEIGHT, -3))); @@ -1583,39 +919,24 @@ void WorldSystem::render(void) Render::worldShader.use(); static const GLuint rug = Texture::genColor(Color {255, 0, 0}); glBindTexture(GL_TEXTURE_2D, rug); - vec2 ll = vec2 {worldStart, GROUND_HEIGHT_MINIMUM}; - Render::drawRect(ll, vec2 {ll.x + world->HouseWidth, ll.y + 4}, -3); + vec2 ll = vec2 {world.startX, GROUND_HEIGHT_MINIMUM}; + Render::drawRect(ll, vec2 {ll.x + world.indoorWidth, ll.y + 4}, -3); Render::worldShader.unuse(); } - player->draw(); + //player->draw(); } -void WorldSystem::setWorld(World *w) -{ - world = w; - - bgFiles.clear(); - - const auto& files = bgPaths[(int)w->bgType]; - - for (const auto& f : files) - bgFiles.push_back(w->styleFolder + f); - - bgTex = TextureIterator(bgFiles); -} - - void WorldSystem::receive(const BGMToggleEvent &bte) { - if (bte.world == nullptr || bgmObjFile != bte.file) { + if (bte.world == nullptr || world.bgm != bte.file) { Mix_FadeOutMusic(800); if (bgmObj != nullptr) Mix_FreeMusic(bgmObj); - bgmObjFile = bte.file; - bgmObj = Mix_LoadMUS(bgmObjFile.c_str()); + //worldBgmFile = bte.file; + bgmObj = Mix_LoadMUS(world.bgm.c_str()); Mix_PlayMusic(bgmObj, -1); } } @@ -1632,118 +953,21 @@ void WorldSystem::setWeather(const std::string &s) weather = WorldWeather::None; } -void WorldSystem::enterWorld(World *w) -{ - if (w != nullptr) { - outside = world; - world = w; - } -} - -void WorldSystem::leaveWorld(void) -{ - world = currentWorld = outside; -} - -void WorldSystem::singleDetect(Entity *e, entityx::TimeDelta dt) +void WorldSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) { - std::string killed; - unsigned int i; - int l; - - auto& worldData = world->worldData; - - if (e == nullptr || !(e->isAlive())) - return; - - // kill dead entities - if (e->health <= 0) { - // die - e->die(); - if (inBattle && e->type == MOBT) - Mobp(e)->onDeath(); - - // delete the entity - for (i = 0; i < world->entity.size(); i++) { - if (world->entity[i] == e) { - switch (e->type) { - case STRUCTURET: - killed = " structure"; - break; - case NPCT: - killed = "n NPC"; - break; - case MOBT: - killed = " mob"; - break; - case OBJECTT: - killed = "n object"; - break; - default: - break; - } - - std::cout << "Killed a" << killed << "...\n"; - world->entity.erase(world->entity.begin() + i); - return; - } - } - - // exit on player death - std::cout << "RIP " << e->name << ".\n"; - exit(0); - } - - // collision / gravity: handle only living entities - else { - - // forced movement gravity (sword hits) - e->handleHits(); - - // calculate the line that this entity is currently standing on - l = std::clamp(static_cast<int>((e->loc.x + e->width / 2 - world->worldStart) / game::HLINE), - 0, - static_cast<int>(world->lineCount)); - - // if the entity is under the world/line, pop it back to the surface - if (e->loc.y < worldData[l].groundHeight) { - int dir = e->vel.x < 0 ? -1 : 1; - if (l + (dir * 2) < static_cast<int>(worldData.size()) && - worldData[l + (dir * 2)].groundHeight - 30 > worldData[l + dir].groundHeight) { - e->loc.x -= (PLAYER_SPEED_CONSTANT + 2.7f) * e->speed * 2 * dir; - e->vel.x = 0; - } else { - e->loc.y = worldData[l].groundHeight - 0.001f * dt; - e->ground = true; - e->vel.y = 0; - } - - } + (void)en; + (void)ev; + (void)dt; - // handle gravity if the entity is above the line - else { - if (e->type == STRUCTURET) { - e->loc.y = worldData[l].groundHeight; - e->vel.y = 0; - e->ground = true; - return; - } else if (e->vel.y > -2) { - e->vel.y -= GRAVITY_CONSTANT * dt; - } - } + // fade in music if not playing + if (bgmObj != nullptr && !Mix_PlayingMusic()) + Mix_FadeInMusic(bgmObj, -1, 2000); - // insure that the entity doesn't fall off either edge of the world. - if (e->loc.x < world->worldStart) { - e->vel.x = 0; - e->loc.x = world->worldStart + HLINES(0.5f); - } else if (e->loc.x + e->width + game::HLINE > -((int)world->worldStart)) { - e->vel.x = 0; - e->loc.x = -((int)world->worldStart) - e->width - game::HLINE; - } - } + // run detect stuff + detect(dt); } -void WorldSystem::detect2(entityx::TimeDelta dt) +void WorldSystem::detect(entityx::TimeDelta dt) { game::entities.each<Position, Direction, Health, Solid>( [&](entityx::Entity e, Position &loc, Direction &vel, Health &health, Solid &dim) { @@ -1754,12 +978,12 @@ void WorldSystem::detect2(entityx::TimeDelta dt) UserError("die mofo"); // get the line the entity is on - int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world->worldStart) / game::HLINE), + int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world.startX) / game::HLINE), 0, - static_cast<int>(world->lineCount)); + static_cast<int>(world.data.size())); // make sure entity is above ground - auto& data = world->worldData; + const auto& data = world.data; if (loc.y < data[line].groundHeight) { int dir = vel.x < 0 ? -1 : 1; if (line + dir * 2 < static_cast<int>(data.size()) && @@ -1779,90 +1003,14 @@ void WorldSystem::detect2(entityx::TimeDelta dt) } // insure that the entity doesn't fall off either edge of the world. - if (loc.x < world->worldStart) { + if (loc.x < world.startX) { vel.x = 0; - loc.x = world->worldStart + HLINES(0.5f); - } else if (loc.x + dim.width + game::HLINE > -((int)world->worldStart)) { + loc.x = world.startX + HLINES(0.5f); + } else if (loc.x + dim.width + game::HLINE > -((int)world.startX)) { vel.x = 0; - loc.x = -((int)world->worldStart) - dim.width - game::HLINE; + loc.x = -((int)world.startX) - dim.width - game::HLINE; } }); } -void WorldSystem::detect(entityx::TimeDelta dt) -{ - int l; - - // handle the player - singleDetect(player, dt); - - // handle other entities - for (auto &e : world->entity) - singleDetect(e, dt); - - partMutex.lock(); - // handle particles - for (auto &part : world->particles) { - // get particle's current world line - l = std::clamp(static_cast<int>((part.loc.x + part.width / 2 - world->worldStart) / game::HLINE), - 0, - static_cast<int>(world->lineCount - 1)); - part.update(GRAVITY_CONSTANT, world->worldData[l].groundHeight); - } - - // handle particle creation - for (auto &e : world->entity) { - if (e->type == STRUCTURET) { - auto b = dynamic_cast<Structures *>(e); - switch (b->bsubtype) { - case FOUNTAIN: - for (unsigned int r = (randGet() % 25) + 11; r--;) { - world->addParticle(randGet() % HLINES(3) + b->loc.x + b->width / 2, // x - b->loc.y + b->height, // y - HLINES(1.25), // width - HLINES(1.25), // height - randGet() % 7 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x - randGet() % 1 ? (8 + randGet() % 6) * .05 : (4 + randGet() % 6) * .05,// vel.y - { 0, 0, 255 }, // RGB color - 2500 // duration (ms) - ); - world->particles.back().fountain = true; - world->particles.back().stu = b; - } - break; - case FIRE_PIT: - for(unsigned int r = (randGet() % 20) + 11; r--;) { - world->addParticle(randGet() % (int)(b->width / 2) + b->loc.x + b->width / 4, // x - b->loc.y + HLINES(3), // y - game::HLINE, // width - game::HLINE, // height - randGet() % 3 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x - (4 + randGet() % 6) * .005, // vel.y - { 255, 0, 0 }, // RGB color - 400 // duration (ms) - ); - world->particles.back().gravity = false; - world->particles.back().behind = true; - world->particles.back().stu = b; - } - break; - default: - break; - } - } - } - partMutex.unlock(); - - // draws the village welcome message if the player enters the village bounds - for (auto &v : world->village) { - if (player->loc.x > v.start.x && player->loc.x < v.end.x) { - if (!v.in) { - ui::passiveImportantText(5000, "Welcome to %s", v.name.c_str()); - v.in = true; - } - } else { - v.in = false; - } - } -} diff --git a/xml/!town.xml b/xml/!town.xml index 2d110e8..bfaa6a9 100644 --- a/xml/!town.xml +++ b/xml/!town.xml @@ -4,11 +4,11 @@ <generation width="1600"/> <time>6000</time> <spawnx>-300</spawnx> - <npc name="Sanc" hasDialog="true" health="1" x="-324.26083" y="70.398842" dindex="9999"/> - <npc name="Bob" hasDialog="true" spawnx="30" health="1" x="151.69295" y="71.5989" dindex="0"/> - <structure type="1" spawnx="300" alive="1"/> - <structure inside="bobshouse.xml" insideTexture="assets/style/classic/bg/insideWoodHouse.png" type="1" spawnx="10" alive="1"/> - <chest alive="1"/> + <npc name="Sanc" hasDialog="true"/> + <npc name="Bob" hasDialog="true" spawnx="30"/> + <structure type="1" spawnx="300"/> + <structure inside="bobshouse.xml" insideTexture="assets/style/classic/bg/insideWoodHouse.png" type="1" spawnx="10"/> + <chest/> </World> <Dialog name="Bob"> diff --git a/xml/bobshouse.xml b/xml/bobshouse.xml index f13d5ff..a1d4e7c 100644 --- a/xml/bobshouse.xml +++ b/xml/bobshouse.xml @@ -1,8 +1,8 @@ <?xml version="1.0"?> <IndoorWorld> <style background="0" bgm="assets/music/theme_jazz.wav" folder="assets/style/classic/"/> - <house width="800" /> - <generation width="1600" /> + <house width="800"/> + <generation width="1600"/> <link outside="town.xml"/> <npc name="Bob" hasDialog="false" spawnx="30"/> </IndoorWorld> |