diff options
-rw-r--r-- | Changelog | 6 | ||||
-rw-r--r-- | include/entities.hpp | 3 | ||||
-rw-r--r-- | include/world.hpp | 337 | ||||
-rw-r--r-- | main.cpp | 9 | ||||
-rw-r--r-- | src/entities.cpp | 43 | ||||
-rw-r--r-- | src/ui.cpp | 20 | ||||
-rw-r--r-- | src/world.cpp | 85 |
7 files changed, 384 insertions, 119 deletions
@@ -991,3 +991,9 @@ - fixed important bugs/memory leaks, few segfaults happen now - new rendering almost complete - brice stuff almost done + +5/13/2016: +========== + + - NPCs and mobs can gracefully walk between worlds, carry dialog + - began more work on combat stuffs diff --git a/include/entities.hpp b/include/entities.hpp index ce2e14d..7487bbe 100644 --- a/include/entities.hpp +++ b/include/entities.hpp @@ -207,6 +207,9 @@ public: // tells direction entity is facing bool right, left; + // tells if the entity is from another world + char outnabout; + // set to 1 if entity is on the ground, 0 if in the air unsigned char ground; diff --git a/include/world.hpp b/include/world.hpp index c40f5f5..74f9cb7 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -1,24 +1,15 @@ -/* ---------------------------------------------------------------------------- -** The world stuffs. -** -** This file contains the classes and variables necessary to create an in-game -** world... "and stuffs". -** --------------------------------------------------------------------------*/ #ifndef WORLD_H #define WORLD_H -/* ---------------------------------------------------------------------------- -** Includes section -** --------------------------------------------------------------------------*/ +/** + * @file world.hpp + * @brief The world system + */ // local game includes #include <common.hpp> #include <entities.hpp> -/* ---------------------------------------------------------------------------- -** Structures section -** --------------------------------------------------------------------------*/ - /** * The background type enum. * This enum contains all different possibilities for world backgrounds; used @@ -47,164 +38,363 @@ enum class WorldWeather : unsigned char { * lines. Dirt color and grass properties are also kept track of here. */ typedef struct { - bool grassUnpressed; - float grassHeight[2]; - float groundHeight; - unsigned char groundColor; + bool grassUnpressed; /**< squishes grass if false */ + float grassHeight[2]; /**< height of the two grass blades */ + float groundHeight; /**< height of the 'line' */ + unsigned char groundColor; /**< a value that affects the ground's color */ } 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. + */ typedef std::pair<World *, vec2> WorldSwitchInfo; -/* ---------------------------------------------------------------------------- -** Variables section -** --------------------------------------------------------------------------*/ - -// affects brightness of world elements when drawn +/** + * Alters how bright world elements are drawn. + * This value is based off of the current time of day (tick count), set in + * main.cpp. + */ extern int worldShade; -// the path to the currently loaded XML file. +/** + * The file path to the currently loaded XML file. + */ extern std::string currentXML; -// defines how many game ticks it takes for a day to elapse +/** + * Defines how many game ticks it takes to go from day to night or vice versa. + */ constexpr const unsigned int DAY_CYCLE = 12000; -// velocity of player when moved by user +/** + * Defines the velocity of player when moved by the keyboard + */ constexpr const float PLAYER_SPEED_CONSTANT = 0.15f; -// maximum pull of gravity in one game tick +/** + * Defines the strongest pull gravity can have on an entity. + * This is the most that can be subtracted from an entity's velocity in one + * game tick. + */ constexpr const float GRAVITY_CONSTANT = 0.001f; -// height of the floor in an indoor world +/** + * Defines the thickness of the floor in an indoor world. + */ constexpr const unsigned int INDOOR_FLOOR_THICKNESS = 50; + +/** + * Defines how far each floor can be from the next (height). + */ constexpr const unsigned int INDOOR_FLOOR_HEIGHTT = 400; -constexpr const unsigned int INDOOR_FLOOR_HEIGHT = (INDOOR_FLOOR_HEIGHTT + INDOOR_FLOOR_THICKNESS); -/* ---------------------------------------------------------------------------- -** Classes / function prototypes section -** --------------------------------------------------------------------------*/ +/** + * Gets a combined height of the floor and the area before it. + * This value is commonly used for operations like moving between floors. + */ +constexpr const unsigned int INDOOR_FLOOR_HEIGHT = (INDOOR_FLOOR_HEIGHTT + INDOOR_FLOOR_THICKNESS); /** - * The village class, used to group structures into villages. + * 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){} }; /** - * The world class. This class does everything a world should do. + * 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 { protected: - // an array of all the world's ground data + /** + * An array of all the world's ground data, populated through + * World::generate(). + * + * @see generate() + */ std::vector<WorldData> worldData; - // the world's current weather + /** + * Contains the current state of weather in the world. + */ WorldWeather weather; - // the size of `worldData` + /** + * Contains the size of the 'worldData' array. + */ unsigned int lineCount; - // the left-most (negative) coordinate of the worldStart + /** + * The starting x-coordinate of the world. + */ float worldStart; - // holds / handles textures for background elements + /** + * Handles textures for the background elements. + */ TextureIterator bgTex; - // defines what type of background is being used + /** + * Defines the set of background images being used for the world. + * + * @see setBackground() + */ WorldBGType bgType; - // an SDL_mixer object for the world's BGM + /** + * SDL_Mixer's object for the loaded BGM. + */ Mix_Music *bgmObj; - // the pathname of the loaded BGM + /** + * The filename of the world's BGM file. + * + * @see setBGM() + */ std::string bgm; - // XML file names of worlds to the left and right, empty if nonexistant + /** + * 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; - // structure texture file paths + /** + * 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; - // TODO + /** + * The paths of files to be used for the background textures. + * + * @see setStyle() + */ std::vector<std::string> bgFiles; + + /** + * The paths of files to be used for the indoor background textures. + * + * @see setStyle() + */ std::vector<std::string> bgFilesIndoors; - // an array of star coordinates + /** + * Contains randomly generated coordinates for stars. + */ std::vector<vec2> star; - // entity vectors + /** + * A vector of all light elements in the world. + * + * @see addLight() + * @see getLastLight() + */ std::vector<Light> light; + + /** + * A vector of all mobs in the world. + * + * @see addMob() + * @see getLastMob() + * @see getNearMob() + */ std::vector<Mob *> mob; + + /** + * A vector of all objects in the world. + * + * @see addObject() + */ std::vector<Object> object; + + /** + * A vector of all particles in the world. + * + * @see addParticle() + */ std::vector<Particles> particles; + + /** + * A vector of all structures in the world. + * + * @see addStructure() + * @see getStructurePos() + */ std::vector<Structures *> build; + + /** + * A vector of all villages in the world. + * + * @see addVillage() + */ std::vector<Village> village; - // handles death, gravity, etc. for a single entity + /** + * Handles death, gravity, etc. for a single entity + */ virtual void singleDetect(Entity *e); - // frees entities and clears vectors that contain them + /** + * Destroys entities and clears vectors that contain them. + * This function is only called in the world destructor. + */ void deleteEntities(void); - -protected: + /** + * Draws background textures. + */ void drawBackgrounds(); public: - // entity vectors that need to be public because we're based + /** + * 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; + /** + * A vector of all NPCs in the world. + * + * @see addNPC() + */ std::vector<NPC *> npc; + + /** + * A vector of all merchants in the world. + * + * @see addMerchant() + */ std::vector<Merchant *> merchant; - // the world constructor, prepares variables + /** + * Constructs the world, resets variables. + */ World(void); - // destructor, frees used memory + /** + * Destructs the world, frees memory. + */ virtual ~World(void); - // generates a world of the specified width + /** + * 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 to the screen + /** + * 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); - // handles collisions/death of player and all entities + /** + * Handles physics for all entities and the player. + * + * @see singleDetect() + */ void detect(Player *p); - // updates entities, moving them and such + /** + * Updates entity positions, time of day, and music. + */ void update(Player *p, unsigned int delta, unsigned int ticks); - // gets the world's width in TODO + /** + * Gets the width of the world, presumably in pixels. + * TODO + */ int getTheWidth(void) const; - // gets the starting x coordinate of the world + /** + * Gets the starting x-coordinate of the world. + * + * @see worldStart + */ float getWorldStart(void) const; - // gets a pointer to the most recently added light + /** + * 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); - // gets a pointer to the most recently added mob + /** + * 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); - // gets the nearest interactable entity to the given one + /** + * 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 + /** + * Gets the coordinates of the `index`th structure. + */ vec2 getStructurePos(int index); - // gets the texture path of the `index`th structure + /** + * 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 @@ -239,12 +429,29 @@ public: WorldSwitchInfo goWorldLeft(Player *p); WorldSwitchInfo goWorldRight(Player *p); - // attempts to move an NPC to the left adjacent world, returning true on success + /** + * 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); @@ -506,6 +506,8 @@ void logic(){ e->near = false; continue; } else if (e->canMove) { + if (!currentWorld->goWorldLeft(dynamic_cast<NPC *>(e))) + currentWorld->goWorldRight(dynamic_cast<NPC *>(e)); e->wander((rand() % 120 + 30)); if (NPCSelected) { e->near = false; @@ -520,8 +522,13 @@ void logic(){ else NPCSelected = true; - if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT)) && !ui::dialogBoxExists) + if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT)) && !ui::dialogBoxExists) { + if (ui::mouse.x < player->loc.x && player->right) + player->left = true, player->right = false; + else if(ui::mouse.x > player->loc.x && player->left) + player->right = true, player->left = false; e->interact(); + } } else { e->near = false; } diff --git a/src/entities.cpp b/src/entities.cpp index 14e1503..6b5e1d3 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -79,6 +79,7 @@ Entity::Entity(void) height = 0; health = 0; maxHealth = 0; + outnabout = 0; z = 1.0f; targetx = 0.9112001f; @@ -383,18 +384,19 @@ void Entity::draw(void) case PLAYERT: static int texState = 0; if (speed && !(game::time::getTickCount() % ((2.0f/speed) < 1 ? 1 : (int)((float)2.0f/(float)speed)))) { - if (++texState==9)texState=1; + if (++texState == 9) + texState = 1; glActiveTexture(GL_TEXTURE0); tex(texState); } if (!ground) { - glActiveTexture(GL_TEXTURE0 + 0); + glActiveTexture(GL_TEXTURE0); tex(0); - }else if (vel.x) { - glActiveTexture(GL_TEXTURE0 + 0); + } else if (vel.x) { + glActiveTexture(GL_TEXTURE0); tex(texState); - }else{ - glActiveTexture(GL_TEXTURE0 + 0); + } else { + glActiveTexture(GL_TEXTURE0); tex(0); } break; @@ -436,13 +438,13 @@ if (health != maxHealth) { glUniform1i(worldShader_uniform_texture, 0); GLfloat coord_back[] = { - loc.x, loc.y + height, z, - loc.x + width, loc.y + height, z, - loc.x + width, loc.y + height + game::HLINE * 2,z, + loc.x, loc.y + height, z, + loc.x + width, loc.y + height, z, + loc.x + width, loc.y + height + game::HLINE * 2, z, - loc.x + width, loc.y + height + game::HLINE * 2,z, - loc.x, loc.y + height + game::HLINE * 2,z, - loc.x, loc.y + height, z, + loc.x + width, loc.y + height + game::HLINE * 2, z, + loc.x, loc.y + height + game::HLINE * 2, z, + loc.x, loc.y + height, z, }; GLfloat coord_front[] = { @@ -559,7 +561,12 @@ void NPC::interact() { //have the npc's interact back to the player if (dialogCount && dialogIndex != 9999) { // load the XML file and find the dialog tags - xml.LoadFile(currentXML.c_str()); + if (outnabout == 0) + xml.LoadFile(currentXML.c_str()); + else if (outnabout < 0) + xml.LoadFile((xmlFolder + currentWorld->getToLeft()).c_str()); + else + xml.LoadFile((xmlFolder + currentWorld->getToRight()).c_str()); COMMONAIFUNC: idx = 0; stop = false; @@ -617,6 +624,10 @@ COMMONAIFUNC: if ((oxml = exml->FirstChildElement("gotox"))) moveTo(std::stoi(oxml->GetText())); + // asdlfkj + auto ptr = exml->GetText() - 1; + while (isspace(*++ptr)); + // handle dialog options if ((oxml = exml->FirstChildElement("option"))) { std::string optstr; @@ -629,9 +640,9 @@ COMMONAIFUNC: // save the associated XMLElement dopt.push_back(oxml); } while ((oxml = oxml->NextSiblingElement())); - + // run the dialog stuff - ui::dialogBox(name, optstr, false, exml->GetText() + 2); + ui::dialogBox(name, optstr, false, ptr); ui::waitForDialog(); if (ui::dialogOptChosen) @@ -642,7 +653,7 @@ COMMONAIFUNC: // optionless dialog else { - ui::dialogBox(name, "", false, exml->GetText()); + ui::dialogBox(name, "", false, ptr); ui::waitForDialog(); } @@ -442,7 +442,7 @@ namespace ui { std::string ret; std::string typeOut(std::string str) { - static unsigned int tadv = TICKS_PER_SEC / 12; + static unsigned int tadv = 1; static unsigned int tickk, linc=0, // Contains the number of letters that should be drawn. size=0; // Contains the full size of the current string. @@ -467,9 +467,21 @@ namespace ui { tickk = tickCount + tadv; ret += str[linc]; - if (linc < size) - linc++; - else + if (linc < size) { + switch (str[++linc]) { + case '!': + case '?': + case '.': + tadv = 10; + break; + case ',': + tadv = 5; + break; + default: + tadv = 1; + break; + } + } else typeOutDone = true; } diff --git a/src/world.cpp b/src/world.cpp index 88ef57a..327a787 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1089,8 +1089,7 @@ void World::load(void){ * Toggle play/stop of the background music. * If new music is to be played a crossfade will occur, otherwise... uhm. */ -void World:: -bgmPlay(World *prev) const +void World::bgmPlay(World *prev) const { if (prev == nullptr || bgm != prev->bgm) { Mix_FadeOutMusic(800); @@ -1103,8 +1102,7 @@ bgmPlay(World *prev) const * This will load a sound file to be played while the player is in this world. * If no file is found, no music should play. */ -void World:: -setBGM(std::string path) +void World::setBGM(std::string path) { if (!path.empty()) bgmObj = Mix_LoadMUS((bgm = path).c_str()); @@ -1115,8 +1113,7 @@ setBGM(std::string path) * The images chosen for the background layers are selected depending on the * world's background type. */ -void World:: -setBackground(WorldBGType bgt) +void World::setBackground(WorldBGType bgt) { // load textures with a limit check switch ((bgType = bgt)) { @@ -1137,8 +1134,7 @@ setBackground(WorldBGType bgt) * The world's style will determine what sprites are used for things like\ * generic structures. */ -void World:: -setStyle(std::string pre) +void World::setStyle(std::string pre) { // get folder prefix std::string prefix = pre.empty() ? "assets/style/classic/" : pre; @@ -1157,8 +1153,7 @@ setStyle(std::string pre) /** * Pretty self-explanatory. */ -std::string World:: -getWeatherStr(void) const +std::string World::getWeatherStr(void) const { switch (weather) { case WorldWeather::Sunny: @@ -1177,8 +1172,7 @@ getWeatherStr(void) const return "???"; } -const WorldWeather& World:: -getWeatherId(void) const +const WorldWeather& World::getWeatherId(void) const { return weather; } @@ -1186,8 +1180,7 @@ getWeatherId(void) const /** * Pretty self-explanatory. */ -std::string World:: -setToLeft(std::string file) +std::string World::setToLeft(std::string file) { return (toLeft = file); } @@ -1195,8 +1188,7 @@ setToLeft(std::string file) /** * Pretty self-explanatory. */ -std::string World:: -setToRight(std::string file) +std::string World::setToRight(std::string file) { return (toRight = file); } @@ -1204,8 +1196,7 @@ setToRight(std::string file) /** * Pretty self-explanatory. */ -std::string World:: -getToLeft(void) const +std::string World::getToLeft(void) const { return toLeft; } @@ -1213,8 +1204,7 @@ getToLeft(void) const /** * Pretty self-explanatory. */ -std::string World:: -getToRight(void) const +std::string World::getToRight(void) const { return toRight; } @@ -1222,8 +1212,7 @@ getToRight(void) const /** * Attempts to go to the left world, returning either that world or itself. */ -WorldSwitchInfo World:: -goWorldLeft(Player *p) +WorldSwitchInfo World::goWorldLeft(Player *p) { World *tmp; @@ -1243,8 +1232,7 @@ goWorldLeft(Player *p) /** * Attempts to go to the right world, returning either that world or itself. */ -WorldSwitchInfo World:: -goWorldRight(Player *p) +WorldSwitchInfo World::goWorldRight(Player *p) { World *tmp; @@ -1256,19 +1244,51 @@ goWorldRight(Player *p) return std::make_pair(this, vec2 {0, 0}); } +void World::adoptNPC(NPC *e) +{ + entity.push_back(e); + npc.push_back(e); +} + +void World::adoptMob(Mob *e) +{ + entity.push_back(e); + mob.push_back(e); +} + /** * Acts like goWorldLeft(), but takes an NPC; returning true on success. */ -bool World:: -goWorldLeft(NPC *e) +bool World::goWorldLeft(NPC *e) { // check if entity is at world edge - if(!toLeft.empty() && e->loc.x < worldStart + HLINES(15)) { - currentWorldToLeft->addNPC(e->loc.x,e->loc.y); - e->die(); + if (!toLeft.empty() && e->loc.x < worldStart + HLINES(15)) { + currentWorldToLeft->adoptNPC(e); + + npc.erase(std::find(std::begin(npc), std::end(npc), 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); - currentWorldToLeft->npc.back()->loc.x = currentWorldToLeft->worldStart + currentWorldToLeft->getTheWidth() - HLINES(15); - currentWorldToLeft->npc.back()->loc.y = GROUND_HEIGHT_MAXIMUM; + npc.erase(std::find(std::begin(npc), std::end(npc), 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; } @@ -1279,8 +1299,7 @@ goWorldLeft(NPC *e) /** * Attempts to enter a building that the player is standing in front of. */ -WorldSwitchInfo World:: -goInsideStructure(Player *p) +WorldSwitchInfo World::goInsideStructure(Player *p) { World *tmp; |