aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog13
-rw-r--r--include/Texture.h3
-rw-r--r--include/common.h2
-rw-r--r--include/entities.h15
-rw-r--r--include/inventory.h3
-rw-r--r--include/ui.h2
-rw-r--r--include/world.h3
-rw-r--r--main.cpp42
-rw-r--r--src/Texture.cpp14
-rw-r--r--src/common.cpp19
-rw-r--r--src/entities.cpp2
-rw-r--r--src/gameplay.cpp105
-rw-r--r--src/inventory.cpp4
-rw-r--r--src/ui.cpp16
-rw-r--r--src/world.cpp64
-rw-r--r--xml/playerSpawnHill1_Building1.xml2
16 files changed, 239 insertions, 70 deletions
diff --git a/Changelog b/Changelog
index a4c3ede..b88ebe4 100644
--- a/Changelog
+++ b/Changelog
@@ -547,3 +547,16 @@
- 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
+
+1/20/2015:
+==========
+
+ - can save npc dialog positions
+ - worked on player sprite redesign
+ - greatly simplified/documented gameplay.cpp
diff --git a/include/Texture.h b/include/Texture.h
index 7160d37..50681bf 100644
--- a/include/Texture.h
+++ b/include/Texture.h
@@ -28,6 +28,9 @@ namespace Texture{
*/
GLuint loadTexture(const char *fileName);
+
+ void freeTextures(void);
+
void initColorIndex();
vec2 getIndex(Color c);
}
diff --git a/include/common.h b/include/common.h
index f5952eb..0df6533 100644
--- a/include/common.h
+++ b/include/common.h
@@ -215,6 +215,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;
diff --git a/include/entities.h b/include/entities.h
index edf7022..fa98285 100644
--- a/include/entities.h
+++ b/include/entities.h
@@ -65,15 +65,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;
@@ -186,7 +184,7 @@ public:
class NPC : public Entity{
public:
std::vector<int (*)(NPC *)>aiFunc;
- unsigned int dialogIndex;
+ int dialogIndex;
NPC();
~NPC();
@@ -200,7 +198,6 @@ class Structures : public Entity{
public:
BUILD_SUB bsubtype;
char *inside;
- //char *outside;
Structures();
~Structures();
diff --git a/include/inventory.h b/include/inventory.h
index b035f91..a08954a 100644
--- a/include/inventory.h
+++ b/include/inventory.h
@@ -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);
diff --git a/include/ui.h b/include/ui.h
index b769bbf..c018008 100644
--- a/include/ui.h
+++ b/include/ui.h
@@ -41,6 +41,8 @@ namespace ui {
void initFonts(void);
+ void destroyFonts(void);
+
/*
* Sets the current font/font size.
*/
diff --git a/include/world.h b/include/world.h
index a1cc870..3209284 100644
--- a/include/world.h
+++ b/include/world.h
@@ -272,6 +272,9 @@ public:
*/
int getTheWidth(void);
+
+ void save(void);
+ void load(void);
};
/*
diff --git a/main.cpp b/main.cpp
index fb13b5a..cb5a20a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -167,25 +167,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
@@ -254,7 +235,6 @@ int main(/*int argc, char *argv[]*/){
Mix_AllocateChannels(8);
// Run Mix_Quit when main returns
- atexit(Mix_CloseAudio);
atexit(Mix_Quit);
/*
@@ -358,21 +338,21 @@ int main(/*int argc, char *argv[]*/){
std::cout << "Initializing shaders!" << std::endl;
- fragShader = glCreateShader(GL_FRAGMENT_SHADER);
-
- std::string shaderFileContents = readFile("frig.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;
@@ -391,6 +371,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);
@@ -435,7 +416,7 @@ int main(/*int argc, char *argv[]*/){
**** GAMELOOP ****
**************************/
- gameRunning=true;
+ gameRunning = true;
while(gameRunning){
mainLoop();
}
@@ -449,9 +430,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);
diff --git a/src/Texture.cpp b/src/Texture.cpp
index f688327..4418a3b 100644
--- a/src/Texture.cpp
+++ b/src/Texture.cpp
@@ -70,6 +70,14 @@ 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];
+ }
+ }
void initColorIndex(){
colorIndex = loadTexture("assets/colorIndex.png");
@@ -90,7 +98,7 @@ namespace Texture{
pixels[y][x].red = buffer[i++];
pixels[y][x].green = buffer[i++];
pixels[y][x].blue = buffer[i++];
- std::cout << pixels[y][x].red << "," << pixels[y][x].green << "," << pixels[y][x].blue << std::endl;
+ //std::cout << pixels[y][x].red << "," << pixels[y][x].green << "," << pixels[y][x].blue << std::endl;
//std::cout << std::endl;
}
}
@@ -111,7 +119,7 @@ namespace Texture{
float shit = 999;
for(uint y = 0; y < 8; y++){
for(uint x = 0; x < 4; x++){
- std::cout << y << "," << x << ":" << pixels[y][x].red << "," << pixels[y][x].green << "," << pixels[y][x].blue << std::endl;
+ //std::cout << y << "," << x << ":" << pixels[y][x].red << "," << pixels[y][x].green << "," << pixels[y][x].blue << std::endl;
buff = sqrt(pow((pixels[y][x].red- c.red), 2)+
pow((pixels[y][x].green-c.green),2)+
pow((pixels[y][x].blue- c.blue), 2));
@@ -126,7 +134,7 @@ namespace Texture{
}
}
ind.push_back({c, (int)buf[1], (int)buf[0]});
- std::cout << float(buf[1]) << ", " << float(buf[0]) << std::endl;
+ //std::cout << float(buf[1]) << ", " << float(buf[0]) << std::endl;
return {float(buf[1]),float(buf[0])};
}
}
diff --git a/src/common.cpp b/src/common.cpp
index 2d35313..334671e 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -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;
diff --git a/src/entities.cpp b/src/entities.cpp
index 76b9aa4..65085ae 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -143,6 +143,8 @@ Structures::~Structures(){
delete tex;
if(name)
delete[] name;
+ if(inside)
+ delete[] inside;
}
Mob::Mob(int sub){
diff --git a/src/gameplay.cpp b/src/gameplay.cpp
index 486c16e..b8e51dc 100644
--- a/src/gameplay.cpp
+++ b/src/gameplay.cpp
@@ -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();
diff --git a/src/inventory.cpp b/src/inventory.cpp
index b6819d1..108051c 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -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;
}
diff --git a/src/ui.cpp b/src/ui.cpp
index 6dd5cd7..76e2777 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -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
@@ -885,7 +896,6 @@ DONE:
fadeEnable ^= true;
fadeWhite = true;
fadeFast = true;
- battleStart = Mix_LoadWAV("assets/sounds/frig.wav");
Mix_PlayChannel(1,battleStart,0);
}
}
diff --git a/src/world.cpp b/src/world.cpp
index 3ad877b..ed1b522 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -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;
}
diff --git a/xml/playerSpawnHill1_Building1.xml b/xml/playerSpawnHill1_Building1.xml
index 1580bd2..f33fcf5 100644
--- a/xml/playerSpawnHill1_Building1.xml
+++ b/xml/playerSpawnHill1_Building1.xml
@@ -2,6 +2,8 @@
<IndoorWorld>
<style background="1" bgm="assets/music/theme_jazz.wav" />
<generation type="Random" width="300" />
+
+ <npc name="Bob" />
</IndoorWorld>