From e017c5cbc9f1cf357ca82593e5d2829dd7f729ce Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Mon, 26 Oct 2015 08:49:10 -0400 Subject: bug fixes --- Changelog | 13 +++++- Makefile | 8 +--- include/entities.h | 14 +++++-- main.cpp | 76 ++++++++++++++++++++++------------ src/Makefile | 4 +- src/entities.cpp | 69 +++++++++++++++++++------------ src/gameplay.cpp | 5 ++- src/world.cpp | 118 ++++++++++++++++++++++++++++++++++++++++------------- 8 files changed, 211 insertions(+), 96 deletions(-) diff --git a/Changelog b/Changelog index ad5f1b6..c1426fd 100644 --- a/Changelog +++ b/Changelog @@ -162,4 +162,15 @@ - fixed entity initialization - added multiple mobs - - improved texture handling \ No newline at end of file + - improved texture handling + +10/26/2015: +=========== + + - removed windows build commands + - fixed bug with spawning 'dead' NPCs + - entities are now drawn behind the current world as well as the grass + - player can now only highlight one NPC at a time + - fixed GLEW shader initialization segfault + - began working on bird mob + - improved world scenery diff --git a/Makefile b/Makefile index a362803..8ac3b3d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ -LIBS = -lGL -WIN_LIBS = -lopengl32 -lmingw32 +LIBS = -lGL -lGLEW -lSDL2main -lSDL2 -lfreetype -lSDL2_image -lSDL2_mixer -FLAGS = -std=c++11 -Iinclude -Iinclude/freetype2 -lGL -lGLEW -lSDL2 -lfreetype -lSDL2_image -lSDL2_mixer +FLAGS = -m32 -std=c++11 -Iinclude -Iinclude/freetype2 all: @rm -f out/*.o @@ -9,9 +8,6 @@ all: @echo " CXX main.cpp" @g++ $(FLAGS) -o main main.cpp out/*.o $(LIBS) -win32: - @g++ $(FLAGS) -o main main.cpp src/*.cpp $(WIN_LIBS) - clean: @echo " RM main" @-rm -f main diff --git a/include/entities.h b/include/entities.h index 47f7f55..c111ea7 100644 --- a/include/entities.h +++ b/include/entities.h @@ -16,9 +16,9 @@ enum _TYPE { //these are the main types of entities STRUCTURET = -1, - PLAYERT = 0, - NPCT = 1, - MOBT = 2 + PLAYERT, + NPCT, + MOBT }; enum GENDER{ @@ -27,6 +27,11 @@ enum GENDER{ NONE }; +enum MOB_SUB { + MS_RABBIT = 1, + MS_BIRD +}; + class Entity{ public: Inventory *inv; @@ -94,8 +99,9 @@ public: }; class Mob : public Entity{ public: + float init_y; Mob(int); - void wander(int, vec2*); + void wander(int); }; #endif // ENTITIES_H diff --git a/main.cpp b/main.cpp index e43029a..8e67d8e 100644 --- a/main.cpp +++ b/main.cpp @@ -173,16 +173,6 @@ unsigned int millis(void){ * MAIN ************************************************************************ *******************************************************************************/ int main(int argc, char *argv[]){ - /* - * Initialize GLEW libraries, and exit if there was an error. - * Not sure what they're for yet. - * - */ - - if(glewInit() < 0){ - std::cout << "GLEW was not able to initialize! Error: " << std::endl; - return -1; - } /* * (Attempt to) Initialize SDL libraries so that we can use SDL facilities and eventually @@ -267,6 +257,19 @@ int main(int argc, char *argv[]){ return -1; } + /* + * Initialize GLEW libraries, and exit if there was an error. + * Not sure what they're for yet. + * + */ + + GLenum err; + glewExperimental = GL_TRUE; + if((err=glewInit()) != GLEW_OK){ + std::cout << "GLEW was not able to initialize! Error: " << glewGetErrorString(err) << std::endl; + return -1; + } + /* * Initialize the FreeType libraries and select what font to use using functions from the ui * namespace, defined in include/ui.h and src/ui.cpp. These functions should abort with errors @@ -303,22 +306,21 @@ int main(int argc, char *argv[]){ SDL_ShowCursor(SDL_DISABLE); /* - * TODO - Initialize shaders n' stuff + * Initializes our shaders so that the game has shadows. */ - /* - - GLuint fragShader; + /*GLuint fragShader; GLuint shaderProgram; const GLchar *shaderSource = "shader.frag"; - GLint bufferln = GL_FALSE; + GLint bufferln = GL_FALSE; - shaderProgram = glCreateProgram(); fragShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragShader, 1, &shaderSource, NULL); glCompileShader(fragShader); + + shaderProgram = glCreateProgram(); + glGetShaderiv(fragShader, GL_COMPILE_STATUS, &bufferln); if(bufferln == GL_TRUE){ @@ -329,10 +331,8 @@ int main(int argc, char *argv[]){ glLinkProgram(shaderProgram); glValidateProgram(shaderProgram); - //glEnable(GL_DEPTH_TEST); - //glEnable(GL_MULTISAMPLE); - - */ + glEnable(GL_DEPTH_TEST); + glEnable(GL_MULTISAMPLE);*/ /* * Open the names file containing potential names for NPCs and store it in the names file @@ -628,6 +628,14 @@ void render(){ } void logic(){ + + /* + * NPCSelected is used to insure that only one NPC is made interactable with the mouse + * if, for example, multiple entities are occupying one space. + */ + + static bool NPCSelected = false; + /* * Handle user input (keyboard & mouse). */ @@ -647,10 +655,11 @@ void logic(){ * click detection is done as well for NPC/player interaction. * */ - //std::cout << "Game Loop: "<< loops << std::endl; for(unsigned int i=0;ialive)std::cout<<"Entity "<canMove) NPCp(entity[i])->wander((rand() % 120 + 30), &entity[i]->vel); + /* + * Don't bother handling the NPC if another has already been handled. + */ + + if(NPCSelected){ + entity[i]->near=false; + break; + } + /* * Check if the NPC is under the mouse. */ @@ -698,10 +716,12 @@ void logic(){ if(pow((entity[i]->loc.x - player->loc.x),2) + pow((entity[i]->loc.y - player->loc.y),2) <= pow(40*HLINE,2)){ /* - * Set Entity->near so that this NPC's name is drawn under them. + * Set Entity->near so that this NPC's name is drawn under them, and toggle NPCSelected + * so this NPC is the only one that's clickable. */ entity[i]->near=true; + NPCSelected=true; /* * Check for a right click, and allow the NPC to interact with the @@ -729,8 +749,13 @@ void logic(){ /* * Run the Mob's AI function. */ - - Mobp(entity[i])->wander((rand()%240 + 15),&entity[i]->vel); // Make the mob wander + + switch(entity[i]->subtype){ + case MS_RABBIT: + case MS_BIRD: + Mobp(entity[i])->wander((rand()%240 + 15)); // Make the mob wander + break; + } break; // End case MOBT @@ -745,4 +770,5 @@ void logic(){ */ loops++; + NPCSelected=false; } diff --git a/src/Makefile b/src/Makefile index 8021f42..a243846 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ -LIBS = -lGL -lSDL2_image -lSDL2_mixer +LIBS = -lGL -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -lfreetype -FLAGS = -std=c++11 -I../include -I../include/freetype2 -lSDL2main -lSDL2 -lfreetype +FLAGS = -m32 -std=c++11 -I../include -I../include/freetype2 OUT = `echo "" $$(ls -c $(wildcard *.cpp)) | sed s/.cpp/.o/g | sed 's/ / ..\/out\//g'` diff --git a/src/entities.cpp b/src/entities.cpp index ae8b4c8..8100a4c 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -26,6 +26,9 @@ void Entity::spawn(float x, float y){ //spawns the entity you pass to it based o if(!maxHealth)health = maxHealth = 1; + if(type==MOBT) + Mobp(this)->init_y=loc.y; + name = (char*)malloc(16); getName(); } @@ -49,6 +52,8 @@ NPC::NPC(){ //sets all of the NPC specific traits on object creation type = NPCT; //sets type to npc subtype = 0; + maxHealth = health = 100; + tex = new Texturec(1,"assets/NPC.png"); inv = new Inventory(NPC_INV_SIZE); } @@ -63,15 +68,20 @@ Structures::Structures(){ //sets the structure type } Mob::Mob(int sub){ - width = HLINE * 10; + width = HLINE * 10; height = HLINE * 8; - type = MOBT; //sets type to MOB - subtype = sub; //SKIRL - if(subtype == 1){//RABBIT + type = MOBT; + + maxHealth = health = 50; + + switch((subtype = sub)){ + case MS_RABBIT: tex = new Texturec(2, "assets/rabbit.png", "assets/rabbit1.png"); - }else if(subtype == 2){//BIRD - //add bird textures and bird things + break; + case MS_BIRD: + break; } + inv = new Inventory(NPC_INV_SIZE); } @@ -287,8 +297,8 @@ unsigned int Structures::spawn(_TYPE t, float x, float y){ //spawns a structure for(int i=0;ix *= direction; //changes the velocity based off of the direction - } - if(ground && direction != 0){ - v->y=.15; - loc.y+=HLINE*.25; - ground=false; - v->x = (.07*HLINE)*direction; //sets the inital velocity of the entity - } - ticksToUse--; //removes one off of the entities timer + case MS_RABBIT: + if(!ticksToUse){ + ticksToUse = timeRun; + direction = (getRand() % 3 - 1); //sets the direction to either -1, 0, 1 + //this lets the entity move left, right, or stay still + if(direction==0)ticksToUse/=2; + vel.x *= direction; //changes the velocity based off of the direction + } + if(ground && direction){ + vel.y=.15; + loc.y+=HLINE*.25; + ground=false; + vel.x = (.07*HLINE)*direction; //sets the inital velocity of the entity + } + ticksToUse--; //removes one off of the entities timer + break; + case MS_BIRD: + if(loc.y<=init_y-.2)vel.y+=.005*deltaTime; // TODO handle direction + break; + default: break; - default:break; } } diff --git a/src/gameplay.cpp b/src/gameplay.cpp index 1f4b3fe..77d0021 100644 --- a/src/gameplay.cpp +++ b/src/gameplay.cpp @@ -78,8 +78,9 @@ void initEverything(void){ /* * Spawn a mob. - */ - mob.push_back(new Mob(1)); + */ + + mob.push_back(new Mob(MS_RABBIT)); entity.push_back(mob.back()); mob.back()->spawn(200,100); diff --git a/src/world.cpp b/src/world.cpp index a05c155..9f18180 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -3,11 +3,11 @@ #define getWidth(w) ((w->lineCount-GEN_INC)*HLINE) // Calculates the width of world 'w' #define GEN_INC 10 // Defines at what interval y values should be calculated for the array 'line'. - // As explained in World(), the last few lines in the array 'line' are incorrectly calculated - // or not calculated at all, so GEN_INC is also used to decrease 'lineCount' in functions like draw() - // and detect(). + // As explained in World(), the last few lines in the array 'line' are incorrectly calculated + // or not calculated at all, so GEN_INC is also used to decrease 'lineCount' in functions like draw() + // and detect(). -#define GRASS_HEIGHT 4 // Defines how long the grass layer of a line should be in multiples of HLINE. +#define GRASS_HEIGHT 4 // Defines how long the grass layer of a line should be in multiples of HLINE. #define DRAW_Y_OFFSET 50 // Defines how many pixels each layer should be offset from each other on the y axis when drawn. @@ -31,8 +31,8 @@ World::World(void){ } void World::generate(unsigned int width){ // Generates the world and sets all variables contained in the World class. - unsigned int i; // Used for 'for' loops - float inc; // See line 40 + unsigned int i; + float inc; /* * Calculate the world's real width. The current form of generation fails to generate @@ -69,8 +69,8 @@ void World::generate(unsigned int width){ // Generates the world and sets all va */ line[i].y=rand() % 8 - 4 + line[i-GEN_INC].y; // Add +/- 4 to the previous line - if(line[i].y < 60)line[i].y = 60; // Minimum bound - else if(line[i].y > 110)line[i].y = 110; // Maximum bound + if(line[i].y < 60)line[i].y = 60; // Minimum bound + else if(line[i].y > 90)line[i].y = 90; // Maximum bound } @@ -145,36 +145,99 @@ void World::draw(Player *p){ static World *current; int i,is,ie,v_offset,cx_start; struct line_t *cline; - current=this; // yeah glClearColor(.1,.3,.6,0); -LOOP1: // Check for worlds behind the current one and set 'current' to them if they exist - if(current->behind){ // so that once LOOP1 is exited 'current' contains the furthest back world. + + /* + * World drawing is done recursively, meaning that this function jumps + * back as many 'layers' as it can and then draws, eventually coming + * back to the initial or 'root' layer. LOOP1 does the recursion back + * to the furthest behind layer, modifying shade and y offsets as it + * does. + * + */ + + current=this; + +LOOP1: + + if(current->behind){ + + /* + * Add to the y offset and shade values (explained further below) + * and recurse. + * + */ + yoff+=DRAW_Y_OFFSET; shade+=DRAW_SHADE; current=current->behind; goto LOOP1; } -LOOP2: // Draw each world - v_offset=(p->loc.x-current->x_start)/HLINE; // Calculate the player's offset in the array 'line' using the player's location 'vec' - is=v_offset-SCREEN_WIDTH/(yoff/(DRAW_Y_OFFSET/2)); // Set 'i' to that somehow - if(is<0)is=0; // If the player is past the start of that world 'i' should start at the beginning - // of the world - ie=v_offset+SCREEN_WIDTH/(yoff/(DRAW_Y_OFFSET/2)); // Set how many lines should be drawn (the drawing for loop loops from 'i' to 'ie') - if(ie>current->lineCount)ie=current->lineCount; // If the player is past the end of that world 'ie' should contain the end of that world - cline=current->line; // 'cline' and 'cx_start' only exist to make the for loop clear (and maybe make it faster) + + /* + * Here is where the actual world drawing begins. A goto is made to + * LOOP2 once the current layer is drawn and the function shifts to + * draw the next closest layer. + */ + +LOOP2: + + /* + * Calculate the offset in the line array that the player is (or would) + * currently be on. This function then calculates reasonable values for + * the 'for' loop below that draws the layer. + */ + + v_offset=(p->loc.x - current->x_start) / HLINE; + + // is -> i start + + is=v_offset - SCREEN_WIDTH / (yoff / (DRAW_Y_OFFSET / 2)); + if(is<0)is=0; // Minimum bound + + ie=v_offset + SCREEN_WIDTH / (yoff / (DRAW_Y_OFFSET / 2)); + if(ie>current->lineCount)ie=current->lineCount; // Maximum bound + + /* + * Make more direct variables for quicker referencing. + */ + + cline =current->line; cx_start=current->x_start; + + /* + * Invert shading if desired. + */ + //shade*=-1; + + /* + * Draw entities in the current layer if we're on the one we started at. + */ + + if(current==this){ + for(i=0;iinWorld==this) + entity[i]->draw(); + } + } + + /* + * Draw the layer up until the grass portion, which is done later. + */ + glBegin(GL_QUADS); - for(i=is;iloc.x+p->width/2-x_start)/HLINE; // Calculate what line the player is currently on @@ -182,11 +245,6 @@ LOOP2: // Draw each world if(p->ground==1&&iph-6)cline[i].gs=false; else cline[i].gs=true; } - for(i=0;iinWorld==this){ - entity[i]->draw(); - } - } p->draw(); } float cgh[2]; @@ -234,9 +292,11 @@ void World::singleDetect(Entity *e){ * Kill any dead entities. */ - if(e->health<=0){ + if(e->alive&&e->health<=0){ e->alive=false; + std::cout<<"Killing entity..."<