]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
WIP save/load
authorClyne Sullivan <tullivan99@gmail.com>
Wed, 20 Jan 2016 13:42:46 +0000 (08:42 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Wed, 20 Jan 2016 13:42:46 +0000 (08:42 -0500)
16 files changed:
Changelog
include/Texture.h
include/common.h
include/entities.h
include/inventory.h
include/ui.h
include/world.h
main.cpp
src/Texture.cpp
src/common.cpp
src/entities.cpp
src/gameplay.cpp
src/inventory.cpp
src/ui.cpp
src/world.cpp
xml/playerSpawnHill1_Building1.xml

index a4c3ede6639f47d50e6f94d3a7999d7862634f02..8b01fe75163d7b15e41a154c2f1a1c4e01bb57f2 100644 (file)
--- a/Changelog
+++ b/Changelog
        - removed layers
        - switched world linking from pointers to file names, rewrote all world-linking code
        - worlds are now loaded dynamically
+
+1/19/2015:
+==========
+
+       - memory management
+       - began reconsidering save/load stuff
index 85225d841cbd39aae85406d3f652ebc8ebe67823..03593bf6745419d945cb51836983e0e0cba3c508 100644 (file)
@@ -28,6 +28,8 @@ namespace Texture{
         */
        
        GLuint loadTexture(const char *fileName);
+       
+       void freeTextures(void);
 }
 
 /**
index ae832f1bed777c09fe06f22895c8f6e27d42ba0a..fa7356ae4da4b923069f34441d41f0d29bdaf911 100644 (file)
@@ -205,6 +205,8 @@ unsigned int millis(void);
 int getdir(const char *dir, std::vector<std::string> &files);
 void strVectorSortAlpha(std::vector<std::string> *v);
 
+const char *readFile(const char *path);
+
 int strCreateFunc(const char *equ);
 
 extern void *NULLPTR;
index d434546914614038dcc0e59b72e49dd2822a9030..6328770572ecf6206c4dbcc630fb9a6d9d029abb 100644 (file)
@@ -63,15 +63,13 @@ public:
        bool gravity;
        bool behind;
        Particles(float x, float y, float w, float h, float vx, float vy, Color c, float d){
-               loc.x = (x);
-               loc.y = (y);
-               width = (w);
-               height = (h);
+               loc.x = x;
+               loc.y = y;
+               width = w;
+               height = h;
                velx = vx;
                vely = vy;
-               color.red = (c.red);
-               color.green = (c.green);
-               color.blue = (c.blue);
+               color = c;
                duration = d;
                fountain = false;
                gravity = true;
@@ -166,7 +164,7 @@ public:
 class NPC : public Entity{
 public:
        std::vector<int (*)(NPC *)>aiFunc;
-       unsigned int dialogIndex;
+       int dialogIndex;
        
        NPC();
        ~NPC();
@@ -180,7 +178,6 @@ class Structures : public Entity{
 public:
        BUILD_SUB bsubtype;
        char *inside;
-       //char *outside;
        
        Structures();
        ~Structures();
index b035f91d6e693d69bc22a78715de7f332d4e3c20..a08954aeef8dccf0e002373293ff5d314201de7c 100644 (file)
@@ -106,8 +106,9 @@ public:
        }
 };
 
-void itemUse(void *p);
 void initInventorySprites(void);
+void destroyInventory(void);
+
 char *getItemTexturePath(ITEM_ID id);
 int getItemWidth(ITEM_ID);
 int getItemHeight(ITEM_ID);
index b769bbff4943feea86d4c9f1273f526642f993e3..c018008c6fba643ec9b27bfe376ba491a3099cb9 100644 (file)
@@ -41,6 +41,8 @@ namespace ui {
 
        void initFonts(void);
        
+       void destroyFonts(void);
+       
        /*
         *      Sets the current font/font size.
        */
index a1cc870b58962aa12643c1cfbfee929ba9b17817..320928467906fb96e3f06fda347ae750fa3f4b8c 100644 (file)
@@ -272,6 +272,9 @@ public:
        */
        
        int getTheWidth(void);
+       
+       void save(void);
+       void load(void);
 };
 
 /*
index 7487e4c0df48d868198e6ca07b1fe285fc913465..76ea66e2aaa4b2a6858836f8a16d84c06ea15c9f 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -166,25 +166,6 @@ void logic(void);
 void render(void);
 void mainLoop(void);
 
-std::string readFile(const char *filePath) {
-    std::string content;
-    std::ifstream fileStream(filePath, std::ios::in);
-
-    if(!fileStream.is_open()) {
-        std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl;
-        return "";
-    }
-
-    std::string line = "";
-    while(!fileStream.eof()) {
-        std::getline(fileStream, line);
-        content.append(line + "\n");
-    }
-
-    fileStream.close();
-    return content;
-}
-
 /*
  *     This offset is used as the player offset in the world drawing so
  *     everything can be moved according to the player
@@ -253,7 +234,6 @@ int main(/*int argc, char *argv[]*/){
        Mix_AllocateChannels(8);
 
        // Run Mix_Quit when main returns
-       atexit(Mix_CloseAudio);
        atexit(Mix_Quit);
 
        /*
@@ -355,21 +335,21 @@ int main(/*int argc, char *argv[]*/){
        
        std::cout << "Initializing shaders!" << std::endl;
 
-       fragShader = glCreateShader(GL_FRAGMENT_SHADER);
-
-       std::string shaderFileContents = readFile("test.frag");
-       const GLchar *shaderSource = shaderFileContents.c_str();
+       const GLchar *shaderSource = readFile("test.frag");
 
-       GLint bufferln = GL_FALSE;
-       int logLength;  
+       GLint bufferln = 0;
+       int logLength;
 
 
+       fragShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragShader, 1, &shaderSource, NULL);
        glCompileShader(fragShader);
 
        glGetShaderiv(fragShader, GL_COMPILE_STATUS, &bufferln);
        glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
-       std::vector<char>fragShaderError((logLength > 1) ? logLength : 1);
+       
+       std::vector<char> fragShaderError ((logLength > 1) ? logLength : 1);
+       
        glGetShaderInfoLog(fragShader, logLength, NULL, &fragShaderError[0]);
        std::cout << &fragShaderError[0] << std::endl;
        
@@ -388,6 +368,7 @@ int main(/*int argc, char *argv[]*/){
     glGetProgramInfoLog(shaderProgram, logLength, NULL, &programError[0]);
     std::cout << &programError[0] << std::endl;
                        
+       delete[] shaderSource;
        
        //glEnable(GL_DEPTH_TEST); //THIS DOESN'T WORK ON LINUX
        glEnable(GL_MULTISAMPLE);
@@ -432,7 +413,7 @@ int main(/*int argc, char *argv[]*/){
        ****     GAMELOOP      ****
        **************************/
        
-       gameRunning=true;
+       gameRunning = true;
        while(gameRunning){
                mainLoop();
        }
@@ -446,9 +427,14 @@ int main(/*int argc, char *argv[]*/){
     */
     
     Mix_HaltMusic();
+    Mix_CloseAudio();
     
     fb.close();
     
+    destroyInventory();
+       ui::destroyFonts();
+    Texture::freeTextures();
+    
     SDL_GL_DeleteContext(mainGLContext);
     SDL_DestroyWindow(window);
     
index 5e367a969dcd131088ee899eff6433b8844b3e27..0dd1efffe31d412ff835257a82a1e542f74afea9 100644 (file)
@@ -63,6 +63,13 @@ namespace Texture{
                
                return object;
        }
+       void freeTextures(void){
+               for(unsigned int i=0;i<LoadedTextureCounter;i++){
+                       glDeleteTextures(1,&LoadedTexture[i]->tex);
+                       delete[] LoadedTexture[i]->name;
+                       delete LoadedTexture[i];
+               }
+       }
 }
 
 Texturec::Texturec(uint amt, ...){
index 2d3531373dcf1ca15e015158c09dc2c588c581b2..334671e05ea13056f521e6a8e0eaddce04a37360 100644 (file)
@@ -93,7 +93,24 @@ void strVectorSortAlpha(std::vector<std::string> *v){
        }while(change);
 }
 
-
+const char *readFile(const char *path){
+       std::ifstream in (path,std::ios::in);
+       unsigned int size;
+       GLchar *buf;
+       
+       if(!in.is_open()){
+               std::cout<<"Error reading file "<<path<<"!"<<std::endl;
+               abort();
+       }
+       
+       in.seekg(0,in.end);
+       buf = new GLchar[(size = in.tellg())];
+       in.seekg(0,in.beg);
+       in.read(buf,size);
+       
+       in.close();
+       return buf;
+}
 
 /*int strCreateFunc(const char *equ){
        static unsigned int size;
index ec335c7cde3073f007415104ae38f29018abeabf..faf415b02c7a2483743057f83bc7218ed6b84b12 100644 (file)
@@ -137,6 +137,8 @@ Structures::~Structures(){
        delete tex;
        if(name)
                delete[] name;
+       if(inside)
+               delete[] inside;
 }
 
 Mob::Mob(int sub){
index 486c16ea4cbe0acffdd53e4caf1a853de4ea053a..b8e51dc01cd132f7d3d514fef489ad872f1f9b88 100644 (file)
@@ -20,21 +20,38 @@ std::vector<XMLElement *>           dopt;
 int commonAIFunc(NPC *speaker){
        XMLDocument xml;
        XMLElement *exml,*oxml;
+       
        const char *name;
        unsigned int idx = 0;
        bool stop = false;
        
+       /*
+        * Load the current world's XML file into memory for reading.
+        */
+       
        xml.LoadFile(currentXML);
        exml = xml.FirstChildElement("Dialog");
        
+       /*
+        * Search for the correct dialog block.
+        */
+       
        while(strcmp(exml->Attribute("name"),speaker->name))
                exml = exml->NextSiblingElement();
        
        exml = exml->FirstChildElement();
        
+       /*
+        * Search for which text block should be used.
+        */
+       
        do{
                if(!strcmp(exml->Name(),"text")){
-                       if(exml->UnsignedAttribute("id") == speaker->dialogIndex){
+                       if(exml->UnsignedAttribute("id") == (unsigned)speaker->dialogIndex){
+                               
+                               /*
+                                * Handle any 'give' requests.
+                                */
                                
                                if((oxml = exml->FirstChildElement("give"))){
                                        while(oxml){
@@ -43,64 +60,106 @@ int commonAIFunc(NPC *speaker){
                                        }
                                }
                                
+                               /*
+                                * Handle any 'take' requests.
+                                */
+                               
+                               if((oxml = exml->FirstChildElement("take"))){
+                                       while(oxml){
+                                               player->inv->takeItem((ITEM_ID)oxml->UnsignedAttribute("id"),oxml->UnsignedAttribute("count"));
+                                               oxml = oxml->NextSiblingElement();
+                                       }
+                               }
+                               
+                               /*
+                                * Handle dialog options.
+                                */
+                               
                                if((oxml = exml->FirstChildElement("option"))){
-                                       const char *op;
-                                       char *bp1 = new char[1],*bp2,*tmp;
-                                       bp1[0] = '\0';
+                                       
+                                       /*
+                                        * Convert the list of options into a single colon-separated string.
+                                        */
+                                       
+                                       std::string optstr;
+
                                        while(oxml){
-                                               op = oxml->Attribute("text");
-                                               
-                                               bp2 = new char[strlen(bp1) + strlen(op) + 2];
-                                               strcpy(bp2,bp1);
                                                
-                                               bp2[idx++] = ':';
-                                               strcpy(bp2+idx,op);
-                                               idx += strlen(op);
+                                               /*
+                                                * Create a buffer big enough for the next option.
+                                                */
+                                                
+                                               optstr.append((std::string)":" + oxml->Attribute("text"));
                                                
-                                               tmp = bp1;
-                                               bp1 = bp2;
-                                               delete[] tmp;
+                                               /*
+                                                * Append the next option.
+                                                */
                                                
                                                dopt.push_back(oxml);
                                                
                                                oxml = oxml->NextSiblingElement();
                                        }
                                        
-                                       ui::dialogBox(speaker->name,bp1,false,exml->GetText());
+                                       /*
+                                        * Get the player's choice, then set the XMLElement to the option's block.
+                                        */
+                                       
+                                       ui::dialogBox(speaker->name,optstr.c_str(),false,exml->GetText());
                                        ui::waitForDialog();
-                                       if(ui::dialogOptChosen){
+                                       
+                                       if(ui::dialogOptChosen)
                                                exml = dopt[ui::dialogOptChosen-1];
-                                       }
+                                       
                                        while(!dopt.empty())
                                                dopt.pop_back();
                                }else{
+                                       
+                                       /*
+                                        * No options - simply print the text.
+                                        */
+                                       
                                        ui::dialogBox(speaker->name,"",false,exml->GetText());
                                        ui::waitForDialog();
                                }
+                               
+                               /*
+                                * Give another NPC dialog if requested.
+                                */
+                               
                                if((name = exml->Attribute("call"))){
                                        for(auto &n : currentWorld->npc){
                                                if(!strcmp(n->name,name)){
-                                                       if(exml->QueryUnsignedAttribute("callid",&idx) == XML_NO_ERROR){
+                                                       if(exml->QueryUnsignedAttribute("callid",&idx) == XML_NO_ERROR)
                                                                n->dialogIndex = idx;
-                                                       }
                                                        n->addAIFunc(commonAIFunc,false);
                                                        break;
                                                }
                                        }
                                }
+                               
+                               /*
+                                * Handle the next dialog block if this one leads to another.
+                                */
+                               
                                if(exml->QueryUnsignedAttribute("nextid",&idx) == XML_NO_ERROR){
                                        speaker->dialogIndex = idx;
-                                       if(exml->QueryBoolAttribute("stop",&stop) == XML_NO_ERROR && stop)
+                                       
+                                       if(exml->QueryBoolAttribute("stop",&stop) == XML_NO_ERROR && stop){
+                                               speaker->dialogIndex = -1;
                                                return 0;
-                                       else if(exml->QueryBoolAttribute("pause",&stop) == XML_NO_ERROR && stop)
+                                       }else if(exml->QueryBoolAttribute("pause",&stop) == XML_NO_ERROR && stop){
+                                               speaker->dialogIndex = -1;
                                                return 1;
-                                       else return commonAIFunc(speaker);
+                                       }else return commonAIFunc(speaker);
                                }
                                return 0;
                        }
                }
+               
                exml = exml->NextSiblingElement();
+               
        }while(exml);
+       
        return 0;
 }
 
@@ -155,6 +214,8 @@ extern std::vector<int (*)(NPC *)> AIpreload;
 extern std::vector<NPC *> AIpreaddr;
 
 void destroyEverything(void){
+       currentWorld->save();
+       delete currentWorld;
        
        while(!AIpreload.empty())
                AIpreload.pop_back();
index b6819d12fb1e08e8841c07292b194916ec583e1b..108051c10cd0ff891c51c7662069e5723a11cc24 100644 (file)
@@ -29,6 +29,10 @@ void initInventorySprites(void){
        Mix_Volume(2,100);
 }
 
+void destroyInventory(void){
+       Mix_FreeChunk(swordSwing);
+}
+
 char *getItemTexturePath(ITEM_ID id){
        return item[id].textureLoc;
 }
index eecd7ef57237572f588149d419e97f1fe1397d9c..2896102c752b86e0b87531bb096c8bab8780d91c 100644 (file)
@@ -67,6 +67,8 @@ unsigned int fadeIntensity = 0;
 bool inBattle = false;
 Mix_Chunk *battleStart;
 
+Mix_Chunk *sanic;
+
 namespace ui {
        
        /*
@@ -119,9 +121,20 @@ namespace ui {
                DEBUG_printf("Initialized FreeType2.\n",NULL);
 #endif // DEBUG
                dialogClick = Mix_LoadWAV("assets/click.wav");
+               battleStart = Mix_LoadWAV("assets/sounds/frig.wav");
+               sanic = Mix_LoadWAV("assets/sounds/sanic.wav");
                Mix_Volume(1,50);
        }
        
+       void destroyFonts(void){
+               FT_Done_Face(ftf);
+               FT_Done_FreeType(ftl);
+               
+               Mix_FreeChunk(dialogClick);
+               Mix_FreeChunk(battleStart);
+               Mix_FreeChunk(sanic);
+       }
+       
        /*
         *      Sets a new font family to use (*.ttf).
        */
@@ -740,8 +753,6 @@ DONE:
                                                break;
                                        case SDLK_LSHIFT:
                                                if(debug){
-                                                       Mix_Chunk *sanic;
-                                                       sanic = Mix_LoadWAV("assets/sounds/sanic.wav");
                                                        Mix_PlayChannel(1,sanic,-1);
                                                        player->speed = 4.0f;
                                                }else
@@ -884,7 +895,6 @@ DONE:
                fadeEnable ^= true;
                fadeWhite = true;
                fadeFast = true;
-               battleStart = Mix_LoadWAV("assets/sounds/frig.wav");
                Mix_PlayChannel(1,battleStart,0);
        }
 }
index 3ad877b5bc72d0e1145498010db7243a9f3beed4..ed1b522a62b85acd6b09c374819446509b6a0d35 100644 (file)
@@ -102,7 +102,7 @@ void World::deleteEntities(void){
                entity.pop_back();
        }
        while(!particles.empty()){
-               //delete particles.back();
+               delete particles.back();
                particles.pop_back();
        }
        while(!light.empty()){
@@ -121,6 +121,9 @@ World::~World(void){
        delete bgTex;
        delete[] star;
        delete[] line;
+       
+       delete[] toLeft;
+       delete[] toRight;
 
        deleteEntities();
 }
@@ -1150,6 +1153,51 @@ int World::getTheWidth(void){
        return -hey->x_start*2;
 }
 
+void World::save(void){
+       static std::string data;
+       
+       std::string save = (std::string)currentXML + ".dat";
+       std::ofstream out (save,std::ios::out | std::ios::binary);
+       
+       std::cout<<"Saving to "<<save<<" ..."<<std::endl;
+       
+       //data.append(std::to_string(npc.size()) + "\n");
+       for(auto &n : npc)
+               data.append(std::to_string(n->dialogIndex) + "\n");
+               
+       data.append("dOnE\0");
+       out.write(data.c_str(),data.size());
+       
+       out.close();
+}
+
+#include <sstream>
+
+extern int commonAIFunc(NPC *);
+
+void World::load(void){
+       std::string save,data,line;
+       
+       save = (std::string)currentXML + ".dat";
+       data = readFile(save.c_str());
+       std::istringstream iss (data);
+       
+       for(auto &n : npc){
+               std::getline(iss,line);
+               if((n->dialogIndex = std::stoi(line)) != -1)
+                       n->addAIFunc(commonAIFunc,false);
+       }
+       
+       while(std::getline(iss,line)){
+               if(line == "dOnE")
+                       break;
+               
+               std::cout<<line<<std::endl;
+       }
+       
+       //abort();
+}
+
 IndoorWorld::IndoorWorld(void){
 }
 
@@ -1306,7 +1354,7 @@ using namespace tinyxml2;
 
 char *currentXML = NULL;
 
-extern int commonAIFunc(NPC *);
+extern World *currentWorld;
 
 World *loadWorldFromXML(const char *path){
        XMLDocument xml;
@@ -1320,8 +1368,10 @@ World *loadWorldFromXML(const char *path){
        
        unsigned int size = 5 + strlen(path);
        
-       if(currentXML)
+       if(currentXML){
+               currentWorld->save();
                delete[] currentXML;
+       }
        
        memset((currentXML = new char[size]),0,size);
        strcpy(currentXML,"xml/");
@@ -1388,6 +1438,7 @@ World *loadWorldFromXML(const char *path){
                        dialog = false;
                        if(wxml->QueryBoolAttribute("hasDialog",&dialog) == XML_NO_ERROR && dialog)
                                tmp->npc.back()->addAIFunc(commonAIFunc,false);
+                       else tmp->npc.back()->dialogIndex = -1;
                        
                }else if(!strcmp(name,"structure")){
                        ptr = wxml->Attribute("inside");
@@ -1398,5 +1449,12 @@ World *loadWorldFromXML(const char *path){
                }
                wxml = wxml->NextSiblingElement();
        }
+       
+       std::ifstream dat (((std::string)currentXML + ".dat").c_str());
+       if(dat.good()){
+               dat.close();
+               tmp->load();
+       }
+       
        return tmp;
 }
index 1580bd28d2459838f8e830d7812ff00ff6db8a6b..f33fcf5fee8ff45ab272fc0874015afe778244e8 100644 (file)
@@ -2,6 +2,8 @@
 <IndoorWorld>
        <style background="1" bgm="assets/music/theme_jazz.wav" />
        <generation type="Random" width="300" />
+       
+       <npc name="Bob" />
 
 </IndoorWorld>