]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
bug/memory fixes
authorClyne Sullivan <tullivan99@gmail.com>
Tue, 10 May 2016 19:40:52 +0000 (15:40 -0400)
committerClyne Sullivan <tullivan99@gmail.com>
Tue, 10 May 2016 19:40:52 +0000 (15:40 -0400)
include/entities.hpp
include/world.hpp
main.cpp
src/entities.cpp
src/inventory.cpp
src/mob.cpp
src/ui.cpp
src/world.cpp
xml/playerSpawnHill1.xml

index 3e78687dbf453e07a165ff8d1a58cd0e2675637d..85b0ec19d698cb39594371dba49e163ce218864b 100644 (file)
  * An entity type enumerator for identifying entities.
  */
 enum _TYPE {
-       OBJECTT = -2,   /**< an object (Object) */
-       STRUCTURET,             /**< a structure (Structures *) */
-       PLAYERT,                /**< the player (Player *) */
-       NPCT,                   /**< an NPC (NPC *) */
-       MERCHT,                 /**< a merchant (Merchant *) */
-       MOBT                    /**< A mob (Mob *) */
+       UNKNOWNT = -999, /**< who knows? */
+       OBJECTT = -2,    /**< an object (Object) */
+       STRUCTURET,              /**< a structure (Structures *) */
+       PLAYERT,                 /**< the player (Player *) */
+       NPCT,                    /**< an NPC (NPC *) */
+       MERCHT,                  /**< a merchant (Merchant *) */
+       MOBT                     /**< A mob (Mob *) */
 };
 
 /**
@@ -279,6 +280,9 @@ public:
        // returns true if the coordinate is within the entity
        bool isInside(vec2 coord) const;
 
+       // a common constructor, clears variables
+       Entity(void);
+
        // frees memory taken by the entity
        virtual ~Entity(){}
 };
@@ -329,7 +333,7 @@ public:
        virtual void wander(int);
 };
 
-class Merchant : public NPC{
+class Merchant : public NPC {
 public:
        std::vector<Trade>trade;
        uint currTrade;
index ac17580c4903885a3c587ae65d3991839d403fc0..c40f5f5373e1fd711b053cc5468e0093a421de81 100644 (file)
@@ -154,6 +154,10 @@ protected:
        // frees entities and clears vectors that contain them
        void deleteEntities(void);
 
+protected:
+       
+       void drawBackgrounds();
+
 public:
 
        // entity vectors that need to be public because we're based
index 570f12f5ce7316d315a87899f195e395f023d070..14f51663b65a19b14e2984f6a0516dd278700d94 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -321,7 +321,6 @@ static float debugY=0;
 
 void mainLoop(void){
        static unsigned int debugDiv=0;                 // A divisor used to update the debug menu if it's open
-       World *prev;
 
        game::time::mainLoopHandler();
 
@@ -329,14 +328,8 @@ void mainLoop(void){
                return;
        } else {
                // handle keypresses - currentWorld could change here
-               prev = currentWorld;
                ui::handleEvents();
 
-               if(prev != currentWorld){
-                       currentWorld->bgmPlay(prev);
-                       ui::dialogBoxExists = false;
-               }
-
                if (game::time::tickHasPassed())
                        logic();
 
index a8f5e484cec5dca85584734f17410fddb0182623..64feaa5afa04b8a6464275333ef35afabaa45c9d 100644 (file)
@@ -72,30 +72,45 @@ void randGetomName(Entity *e)
        delete[] bufs;
 }
 
-// spawns the entity you pass to it based off of coords and global entity settings
-void Entity::spawn(float x, float y)
+Entity::Entity(void)
 {
-       loc.x = x;
-       loc.y = y;
-       vel.x = 0;
-       vel.y = 0;
+       vel = 0;
+       width = 0;
+       height = 0;
+       health = 0;
+       maxHealth = 0;
+       z = 1.0f;
        targetx = 0.9112001f;
 
-       alive   = true;
-       right   = true;
-       left    = false;
-       near    = false;
-       //canMove       = true;
-       ground  = false;
+       type = UNKNOWNT;
+
+       // set flags
+       alive      = true;
+       right      = true;
+       left       = false;
+       near       = false;
+       canMove    = true;
+       ground     = false;
        forcedMove = false;
-       z = 1.0f;
 
+       // clear counters
        ticksToUse = 0;
        hitCooldown = 0;
 
-       if (!maxHealth)
+       inv = nullptr;
+       name = nullptr;
+}
+
+// spawns the entity you pass to it based off of coords and global entity settings
+void Entity::spawn(float x, float y)
+{
+       loc.x = x;
+       loc.y = y;
+
+       if (health == 0 && maxHealth == 0)
                health = maxHealth = 1;
 
+       // generate a name
        name = new char[32];
        if (type == MOBT)
                name[0] = '\0';
@@ -131,11 +146,7 @@ void Entity::setCooldown(unsigned int c)
 
 void Entity::handleHits(void)
 {
-       int c = hitCooldown - game::time::getDeltaTime();
-       if (c >= 0)
-               hitCooldown = c;
-       else
-               hitCooldown = 0;
+       hitCooldown = fmax(hitCooldown - game::time::getDeltaTime(), 0);
 
        if (!forcedMove)
                return;
@@ -168,7 +179,8 @@ void Entity::moveTo(float dest_x)
        targetx = dest_x;
 }
 
-Player::Player(){ //sets all of the player specific traits on object creation
+Player::Player() : Entity() 
+{
        width = HLINES(10);
        height = HLINES(16);
 
@@ -191,12 +203,15 @@ Player::Player(){ //sets all of the player specific traits on object creation
 
        inv = new Inventory(PLAYER_INV_SIZE);
 }
-Player::~Player() {
+
+Player::~Player()
+{
        delete inv;
        delete[] name;
 }
 
-NPC::NPC() {   //sets all of the NPC specific traits on object creation
+NPC::NPC() : Entity()
+{
        width = HLINES(10);
        height = HLINES(16);
 
@@ -213,6 +228,7 @@ NPC::NPC() {        //sets all of the NPC specific traits on object creation
 
        randDialog = rand() % RAND_DIALOG_COUNT - 1;
        dialogIndex = 0;
+       dialogCount = 0;
 }
 
 NPC::~NPC()
@@ -221,7 +237,8 @@ NPC::~NPC()
        delete[] name;
 }
 
-Merchant::Merchant() { //sets all of the Merchant specific traits on object creation
+Merchant::Merchant() : NPC()
+{
        width = HLINES(10);
        height = HLINES(16);
 
@@ -230,7 +247,6 @@ Merchant::Merchant() {      //sets all of the Merchant specific traits on object crea
 
        health = maxHealth = 100;
 
-       maxHealth = health = 100;
        canMove = true;
 
        trade.reserve(100);
@@ -246,64 +262,49 @@ Merchant::Merchant() {    //sets all of the Merchant specific traits on object crea
        dialogIndex = 0;
 }
 
-Merchant::~Merchant() {
-       delete inside;
+Merchant::~Merchant()
+{
        //delete inv;
-       //delete[] name;
+       delete[] name;
 }
 
-Structures::Structures() { //sets the structure type
-       health = maxHealth = 1;
-
-       alive = false;
-       near  = false;
-
-       name = NULL;
-
-       //inv = NULL;
+Structures::Structures() : Entity()
+{
        canMove = false;
-
-       z = 1.0f;
+       health = maxHealth = 1;
 }
-Structures::~Structures() {
-       if (name)
-               delete[] name;
+
+Structures::~Structures()
+{
+       delete[] name;
 }
 
-Object::Object() {
+Object::Object()
+{
        type = OBJECTT;
-       alive = true;
-       near = false;
-       width  = 0;
-       height = 0;
-       canMove = false;
-
-       maxHealth = health = 1;
-
-       inv = NULL;
 }
 
-Object::Object(std::string in, std::string pd) {
+Object::Object(std::string in, std::string pd)
+{
        iname = in;
 
        pickupDialog = pd;
        questObject = !pd.empty();
 
        type = OBJECTT;
-       alive = true;
-       near = false;
        width  = getItemWidth(in);
        height = getItemHeight(in);
 
-       maxHealth = health = 1;
        tex = TextureIterator({getItemTexturePath(in)});
-       inv = NULL;
 }
-Object::~Object() {
+
+Object::~Object()
+{
        delete[] name;
 }
 
-void Object::reloadTexture(void) {
+void Object::reloadTexture(void)
+{
        tex = TextureIterator({getItemTexturePath(iname)});
        width  = getItemWidth(iname);
        height = getItemHeight(iname);
@@ -411,7 +412,7 @@ void Entity::draw(void)
                glEnableVertexAttribArray(worldShader_attribute_tex);
 
                glVertexAttribPointer(worldShader_attribute_coord, 3, GL_FLOAT, GL_FALSE, 0, coords);
-               if(left)
+               if (left)
                        glVertexAttribPointer(worldShader_attribute_tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coordL);
                else
                        glVertexAttribPointer(worldShader_attribute_tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coord);
index a1181e282f6861cdbeebc94e1d98019cb5b3b5c6..5445aa98727d92047955d9b5d4bc7b709a717f3b 100644 (file)
@@ -110,14 +110,10 @@ void items(void)
 
                exml = exml->NextSiblingElement();
        }
-       for (auto &i : ItemMap) {
-               std::cout << i->name << ", " << i->maxStackSize << ", " << i->dim.x << ", " << i->dim.y << std::endl;
-       }
 }
 
 int Inventory::addItem(std::string name, uint count)
 {
-       std::cout << "Adding: " << count << " " << name << "\n";
        for (uint i = 0; i < ItemMap.size(); i++) {
                if (strCaseCmp(ItemMap[i]->name, name)) {
                        for (auto &it : Items) {
index ec8b8497602712c590c61eb03166642e1de1bd9c..db0b88aa821c85a9a4bd46a0eb6e314be5b5ce26 100644 (file)
@@ -8,6 +8,7 @@ extern World *currentWorld;
 Mob::Mob(void)
 {
     type = MOBT;
+       inv = nullptr;
     rider = nullptr;
     canMove = true;
 }
index 6a68cc0a1fe427471fba2716491bd983f0323137..a57886ce7e2be2644ae5c9430a61a299a54ce857 100644 (file)
@@ -998,6 +998,16 @@ EXIT:
                static vec2 fr;
                static Entity *ig;
 
+               auto worldSwitch = [&](const WorldSwitchInfo& wsi){
+                       player->canMove = false;
+                       toggleBlackFast();
+                       waitForCover();
+                       wsi.first->bgmPlay(currentWorld);
+                       std::tie(currentWorld, player->loc) = wsi;
+                       toggleBlackFast();
+                       player->canMove = true;
+               };
+
                while(SDL_PollEvent(&e)) {
                        switch(e.type) {
 
@@ -1089,6 +1099,9 @@ EXIT:
                                // only let other keys be handled if dialog allows it
                                } else if (!dialogBoxExists || dialogPassive) {
                                        switch(SDL_KEY) {
+                                       case SDLK_DELETE:
+                                               gameRunning = false;
+                                               break;
                                        case SDLK_t:
                                                game::time::tick(50);
                                                break;
@@ -1101,15 +1114,8 @@ EXIT:
                                                if (currentWorldToLeft) {
                                                        std::thread([&](void){
                                                                auto thing = currentWorld->goWorldLeft(player);
-                                                               if (thing.first != currentWorld) {
-                                                                       player->canMove = false;
-                                                                       toggleBlackFast();
-                                                                       waitForCover();
-                                                                       currentWorld = thing.first;
-                                                                       player->loc = thing.second;
-                                                                       toggleBlackFast();
-                                                                       player->canMove = true;
-                                                               }
+                                                               if (thing.first != currentWorld)
+                                                                       worldSwitch(thing);
                                                        }).detach();
                                                }
                                                break;
@@ -1122,15 +1128,8 @@ EXIT:
                                                if (currentWorldToRight) {
                                                        std::thread([&](void){
                                                                auto thing = currentWorld->goWorldRight(player);
-                                                               if (thing.first != currentWorld) {
-                                                                       player->canMove = false;
-                                                                       toggleBlackFast();
-                                                                       waitForCover();
-                                                                       currentWorld = thing.first;
-                                                                       player->loc = thing.second;
-                                                                       toggleBlackFast();
-                                                                       player->canMove = true;
-                                                               }
+                                                               if (thing.first != currentWorld)
+                                                                       worldSwitch(thing);
                                                        }).detach();
                                                }
                                                break;
@@ -1138,30 +1137,14 @@ EXIT:
                                                if (inBattle) {
                                                        std::thread([&](void){
                                                                auto thing = dynamic_cast<Arena *>(currentWorld)->exitArena(player);
-                                                               if (thing.first != currentWorld) {
-                                                                       player->canMove = false;
-                                                                       toggleBlackFast();
-                                                                       waitForCover();
-                                                                       //delete dynamic_cast<Arena *>(currentWorld);
-                                                                       currentWorld = thing.first;
-                                                                       player->loc = thing.second;
-                                                                       toggleBlackFast();
-                                                                       player->canMove = true;
-                                                               }
+                                                               if (thing.first != currentWorld)
+                                                                       worldSwitch(thing);
                                                        }).detach();
                                                } else {
                                                        std::thread([&](void){
                                                                auto thing = currentWorld->goInsideStructure(player);
-                                                               if (thing.first != currentWorld) {
-                                                                       player->canMove = false;
-                                                                       toggleBlackFast();
-                                                                       waitForCover();
-                                                                       currentWorld = thing.first;
-                                                                       if (thing.second.x)
-                                                                               player->loc.x = thing.second.x;
-                                                                       toggleBlackFast();
-                                                                       player->canMove = true;
-                                                               }
+                                                               if (thing.first != currentWorld)
+                                                                       worldSwitch(thing);
                                                        }).detach();
                                                }
                                                break;
@@ -1239,11 +1222,10 @@ EXIT:
                                        right = false;
                                        break;
                                case SDLK_LSHIFT:
-                                       if (player->speed == 4) {
+                                       if (player->speed == 4)
                                                Mix_FadeOutChannel(1,2000);
-                                       }
-                                       player->speed = 1;
-                                       break;
+
+                                       // fall through                                 
                                case SDLK_LCTRL:
                                        player->speed = 1;
                                        break;
@@ -1251,9 +1233,11 @@ EXIT:
                                        edown=false;
                                        if (player->inv->invHover) {
                                                player->inv->invHover = false;
-                                       }else{
-                                               if (!player->inv->selected)player->inv->invOpening ^= true;
-                                               else player->inv->selected = false;
+                                       } else {
+                                               if (!player->inv->selected)
+                                                       player->inv->invOpening ^= true;
+                                               else
+                                                       player->inv->selected = false;
                                                player->inv->mouseSel = false;
                                        }
 
index 362cc8b89eb32c2cde37428289e2ac905d07cdac..8c3d2f85c57a2467b71b3e50055780b7b78b36ca 100644 (file)
@@ -104,6 +104,8 @@ World::
 World(void)
 {
     bgmObj = nullptr;
+       worldStart = 0;
+       lineCount = 0;
 }
 
 /**
@@ -218,8 +220,7 @@ generate(int width)
  * This function will draw the background layers, entities, and player to the
  * screen.
  */
-void World::
-draw(Player *p)
+void World::drawBackgrounds(void)
 {
     auto SCREEN_WIDTH = game::SCREEN_WIDTH;
        auto SCREEN_HEIGHT = game::SCREEN_HEIGHT;
@@ -229,15 +230,6 @@ draw(Player *p)
         static_cast<int>(SCREEN_WIDTH) / 2, static_cast<int>(SCREEN_HEIGHT) / 2
     };
 
-    // iterators ranges
-    int iStart, iEnd;
-
-    // shade value for draws -- may be unnecessary
-       //int shadeBackground = -worldShade;
-
-    // player's offset in worldData[]
-       int pOffset;
-
     // world width in pixels
        int width = worldData.size() * HLINE;
 
@@ -250,7 +242,6 @@ draw(Player *p)
        if (shadeAmbient > 0.9f)
                shadeAmbient = 1;
 
-
        // the sunny wallpaper is faded with the night depending on tickCount
     switch (weather) {
     case WorldWeather::Snowy:
@@ -285,14 +276,6 @@ draw(Player *p)
                             vec2(0.0f, 1.0f),
                             vec2(0.0f, 0.0f)};
 
-       /*safeSetColorA(255, 255, 255, alpha);
-       glBegin(GL_QUADS);
-               glTexCoord2i(0, 0); glVertex2i(offset.x - backgroundOffset.x - 5, offset.y + backgroundOffset.y);
-               glTexCoord2i(1, 0); glVertex2i(offset.x + backgroundOffset.x + 5, offset.y + backgroundOffset.y);
-               glTexCoord2i(1, 1); glVertex2i(offset.x + backgroundOffset.x + 5, offset.y - backgroundOffset.y);
-               glTexCoord2i(0, 1); glVertex2i(offset.x - backgroundOffset.x - 5, offset.y - backgroundOffset.y);
-       glEnd();*/
-
     bgTex(0);
     GLfloat back_tex_coord[] = {offset.x - backgroundOffset.x - 5, offset.y + backgroundOffset.y, 1.0f,
                                 offset.x + backgroundOffset.x + 5, offset.y + backgroundOffset.y, 1.0f,
@@ -318,36 +301,10 @@ draw(Player *p)
 
 
        bgTex++;
-    //TODO
-    //glDrawArrays(GL_TRIANGLES, 0 , 6);
-
-    // TODO fade and draw night bg
-       /*safeSetColorA(255, 255, 255, !alpha ? 255 : worldShade * 4);
-       glBegin(GL_QUADS);
-        glTexCoord2i(0, 0); glVertex2i(offset.x - backgroundOffset.x - 5, offset.y + backgroundOffset.y);
-        glTexCoord2i(1, 0); glVertex2i(offset.x + backgroundOffset.x + 5, offset.y + backgroundOffset.y);
-        glTexCoord2i(1, 1); glVertex2i(offset.x + backgroundOffset.x + 5, offset.y - backgroundOffset.y);
-        glTexCoord2i(0, 1); glVertex2i(offset.x - backgroundOffset.x - 5, offset.y - backgroundOffset.y);
-       glEnd();*/
-
-       //glDisable(GL_TEXTURE_2D);
-
-       // draw the stars if the time deems it appropriate
-       /*if (worldShade > 0) {
-               safeSetColorA(255, 255, 255, 255 - (randGet() % 30 - 15));
-
-        auto xcoord = offset.x * 0.9f;
-               for (auto &s : star)
-                       glRectf(s.x + xcoord, s.y, s.x + xcoord + HLINE, s.y + HLINE);
-       }*/
-
-       // draw remaining background items
-       //glEnable(GL_TEXTURE_2D);
 
     std::vector<vec3> bg_items;
 
        bgTex++;
-       //safeSetColorA(150 + shadeBackground * 2, 150 + shadeBackground * 2, 150 + shadeBackground * 2, 255);
     auto xcoord = width / 2 * -1 + offset.x * 0.85f;
        for (unsigned int i = 0; i <= worldData.size() * HLINE / 1920; i++) {
         bg_items.push_back(vec3(1920 * i       + xcoord, GROUND_HEIGHT_MINIMUM, 1.0f));
@@ -389,16 +346,10 @@ draw(Player *p)
 
     glUseProgram(0);
 
-    //GARNBSFJBSJOFBSJDVFJDSF
-
+       // draw the remaining layers
        for (unsigned int i = 0; i < 4; i++) {
         std::vector<vec3>c;
                bgTex++;
-               /*safeSetColorA(bgDraw[i][0] + shadeBackground * 2,
-                      bgDraw[i][0] + shadeBackground * 2,
-                      bgDraw[i][0] + shadeBackground * 2,
-                      bgDraw[i][1]
-                  );*/
         auto xcoord = offset.x * bgDraw[i][2];
                for (int j = worldStart; j <= -worldStart; j += 600) {
             c.push_back(vec3(j       + xcoord, GROUND_HEIGHT_MINIMUM, 1));
@@ -440,12 +391,16 @@ draw(Player *p)
 
         glUseProgram(0);
        }
+}
 
-       //glDisable(GL_TEXTURE_2D);
+void World::draw(Player *p)
+{
+       int iStart, iEnd, pOffset;
+
+       auto SCREEN_WIDTH = game::SCREEN_WIDTH;
+       auto HLINE = game::HLINE;
 
-       // draw black under backgrounds (y-coordinate)
-       //glColor3ub(0, 0, 0);
-       //glRectf(worldStart, GROUND_HEIGHT_MINIMUM, -worldStart, 0);
+       drawBackgrounds();
 
        // draw particles and buildings
     glBindTexture(GL_TEXTURE_2D, colorIndex);
@@ -510,41 +465,6 @@ draw(Player *p)
         }
     }
 
-    // draw light elements
-    //glEnable(GL_TEXTURE_2D);
-    //glActiveTexture(GL_TEXTURE0);
-
-    /*std::unique_ptr<GLfloat[]> pointArrayBuf = std::make_unique<GLfloat[]> (2 * (light.size()));
-       auto pointArray = pointArrayBuf.get();
-    GLfloat flameArray[64];
-
-       for (unsigned int i = 0; i < light.size(); i++) {
-        if (light[i].flame) {
-               pointArray[2 * i    ] = light[i].fireLoc.x - offset.x;
-               pointArray[2 * i + 1] = light[i].fireLoc.y;
-        }else{
-            pointArray[2 * i    ] = light[i].loc.x - offset.x;
-            pointArray[2 * i + 1] = light[i].loc.y;
-        }
-       }
-
-    for (unsigned int i = 0; i < light.size(); i++) {
-        flameArray[i] = light[i].fireFlicker;
-    }
-
-       //glUseProgram(shaderProgram);
-       //glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
-       //glUniform1f(glGetUniformLocation(shaderProgram, "amb"), shadeAmbient);
-
-       if (light.empty())
-               glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 0);
-       else {
-               glUniform1i (glGetUniformLocation(shaderProgram, "numLight"), light.size());
-               glUniform2fv(glGetUniformLocation(shaderProgram, "lightLocation"), light.size(), pointArray);
-               glUniform3f (glGetUniformLocation(shaderProgram, "lightColor"), 1.0f, 1.0f, 1.0f);
-        glUniform1fv(glGetUniformLocation(shaderProgram,"fireFlicker"), light.size(),flameArray);
-       }*/
-
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
@@ -553,13 +473,9 @@ draw(Player *p)
 
     // only draw world within player vision
     iStart = static_cast<int>(fmax(pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS, 0));
-    iEnd   = static_cast<int>(fmin(pOffset + (SCREEN_WIDTH / 2 / HLINE) + GROUND_HILLINESS + HLINE, worldData.size()));
-    iEnd   = static_cast<int>(fmax(iEnd, GROUND_HILLINESS));
-
-
-
-       //glBegin(GL_QUADS);
-    //std::for_each(std::begin(worldData) + iStart, std::begin(worldData) + iEnd, [&](WorldData wd) {
+       iEnd = std::clamp(static_cast<int>(pOffset + (SCREEN_WIDTH / 2 / HLINE)),
+                      static_cast<int>(GROUND_HILLINESS),
+                      static_cast<int>(worldData.size()));
 
     // draw the dirt
     bgTex++;
@@ -895,8 +811,9 @@ detect(Player *p)
     // handle particles
        for (auto &part : particles) {
                // get particle's current world line
-               l = (int)fmax((part.loc.x + part.width / 2 - worldStart) / game::HLINE, 0);
-        l = (int)fmin(lineCount - 1, l);
+               l = std::clamp(static_cast<int>((part.loc.x + part.width / 2 - worldStart) / game::HLINE),
+                       0,
+                       static_cast<int>(lineCount - 1));
                part.update(GRAVITY_CONSTANT, worldData[l].groundHeight);
        }
 
@@ -1199,15 +1116,7 @@ void World::load(void){
 void World::
 bgmPlay(World *prev) const
 {
-       if (prev) {
-        if (bgm != prev->bgm) {
-                   // new world, new music
-                   Mix_FadeOutMusic(800);
-                   Mix_PlayMusic(bgmObj, -1);
-        }
-        // sucks to be here
-       } else {
-        // first call
+       if (prev == nullptr || bgm != prev->bgm) {
                Mix_FadeOutMusic(800);
                Mix_PlayMusic(bgmObj, -1);
        }
@@ -1399,6 +1308,7 @@ goInsideStructure(Player *p)
 {
        World *tmp;
 
+       // enter a building
        if (inside.empty()) {
         auto d = std::find_if(std::begin(build), std::end(build), [p](const Structures *s) {
             return ((p->loc.x > s->loc.x) && (p->loc.x + p->width < s->loc.x + s->width));
@@ -1412,8 +1322,11 @@ goInsideStructure(Player *p)
                inside.push_back(&currentXML[xmlFolder.size()]);
                tmp = loadWorldFromXML(b->inside);
 
-               return std::make_pair(tmp, vec2 {0, 0});
-       } else {
+               return std::make_pair(tmp, vec2 {0, 100});
+       }
+
+       // exit the building
+       else {
         std::string current = &currentXML[xmlFolder.size()];
                tmp = loadWorldFromXML(inside.back());
         inside.clear();
@@ -1531,7 +1444,7 @@ 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[start].groundHeight;
+       const float thing = peak.y - worldData[std::clamp(start, 0, static_cast<int>(lineCount))].groundHeight;
     const float period = PI / width;
 
        if (start < 0) {
index d848847354d9cc53616309b0d5de1dad0f5b6323..82563e9f9c8e7a32066fd95cf71bbc67e1cc6c80 100644 (file)
@@ -7,7 +7,7 @@
 
        <hill peakx="0" peaky="1000" width="50" />
 
-       <rabbit x="300" aggressive="true" health="100" />
+       <rabbit x="300" aggressive="false" health="100" />
        <bird y="500"/>
        <cat />