]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
documentation part 1
authorClyne Sullivan <tullivan99@gmail.com>
Mon, 19 Oct 2015 12:50:14 +0000 (08:50 -0400)
committerClyne Sullivan <tullivan99@gmail.com>
Mon, 19 Oct 2015 12:50:14 +0000 (08:50 -0400)
Changelog
include/entities.h
main.cpp
src/common.cpp
src/entities.cpp
src/ui.cpp
src/world.cpp

index 752d92cc71eb36085b34e5bf1e453f17b8614760..77edf73223fc76737946122f2dc437974579c054 100644 (file)
--- a/Changelog
+++ b/Changelog
 
        - fixed quest assignment/completion
        - entities can't move when interacting now
+       - added GLEW libraries
+       - worked on delaying quest assignments until dialog is closed
+
+10/16/2015:
+===========
+
+       - fixed delaying quest assignments until dialog is closed
+       - checked and secured errors in malloc/calloc calls
+       
+10/19/2015:
+===========
+
+       - fixed malloc/strlen bug that crashes the game on some linux systems
+       - broke andy's linux system on his laptop, allowing for test game build on Windows
+       - began extensive documentation in main.cpp
index 431407b98801d91028aea8d15e4ab72f6e40648b..655390b6a9d89a8fa1ea6cd026ca0a092148fd44 100644 (file)
@@ -23,8 +23,8 @@ public:
        float height;
        float speed;    //speed of the play
 
-       int health;
-       int maxHealth;
+       float health;
+       float maxHealth;
 
        int subtype;
        _TYPE type;
@@ -68,7 +68,6 @@ public:
        std::vector<int (*)(NPC *)>aiFunc;
        NPC();
        void addAIFunc(int (*func)(NPC *),bool preload);
-       void flushAIFunc(void);
        void interact();
        void wander(int, vec2*);
 };
index bb93a07b01a7829ab8d0357220f52067d8c9fb98..828c0b2d1ec7c13369f5e4204b5460ed12d0ffde 100644 (file)
--- a/main.cpp
+++ b/main.cpp
 #include <ui.h>
 #include <entities.h>
 
-#define TICKS_PER_SEC 20                                       // The amount of game ticks that should occur in one second
-#define MSEC_PER_TICK (1000/TICKS_PER_SEC)     // The amount of milliseconds there should be between ticks
-
-SDL_Window    *window = NULL;                  // The game's window
+/*
+ *     TICKS_PER_SEC & MSEC_PER_TICK
+ * 
+ *     The game's main loop mainly takes care of two things: drawing to the
+ *     screen and handling game logic, from user input to world gravity stuff.
+ *     The call for rendering is made every time the main loop loops, and then
+ *     uses interpolation for smooth drawing to the screen. However, the call
+ *     for logic would be preferred to be run every set amount of time.
+ * 
+ *     The logic loop is currently implemented to run at a certain interval
+ *     that we call a 'tick'. As one may now guess, TICKS_PER_SEC defines the
+ *     amount of ticks that should be made every second. MSEC_PER_TICK then
+ *     does a simple calculation of how many milliseconds elapse per each
+ *     'tick'. Simple math is then done in the main loop using MSEC_PER_TICK
+ *     to call the logic handler when necessary.
+ * 
+*/
+
+#define TICKS_PER_SEC 20
+#define MSEC_PER_TICK (1000/TICKS_PER_SEC)
+
+/*
+ *     window & mainGLContext
+ * 
+ *     In order to draw using SDL and its openGL facilities SDL requires
+ *     an SDL_Window object, which spawns a window for the program to draw
+ *     to. Once the SDL_Window is initialized, an SDL_GLContext is made so
+ *     that openGL calls can be made to SDL. The game requires both of these
+ *     variables to initialize.
+ * 
+*/
+
+SDL_Window    *window = NULL;
 SDL_GLContext  mainGLContext = NULL;
-static GLuint  bgImage;
-
-bool gameRunning = true;       // The game will exit if this is false
-
-World  *currentWorld=NULL;     // A pointer to the world that the player is currently in
-Player *player;                                // The player
 
-std::vector<Entity*>entity;            // An array of all entities in existance
-std::vector<NPC>npc;                   // An array of all NPCs in existance            (entries in `entity` point to these)
-std::vector<Structures *>build;        // An array of all Structures in existance      (entries in `entity` point to these)
-std::vector<Mob>mob;                   // An array of all Mobs in existance            (entries in `entity` point to these)
+/*
+ *     bgImage contains the GLuint returned when creating a texture for the
+ *     background image. Currently there is only one background image for the
+ *     main world; this will be changed and bgImage likely removed once better
+ *     backgrounds are implemented.
+ * 
+*/
 
-unsigned int tickCount   = 0,  // The amount of generated ticks since the game entered the main loop
-                        deltaTime   = 0;       // Used for frame regulation / smooth animation n' stuff
-
-int mx, my;            // The mouse's coordinates in the window
+static GLuint  bgImage;
 
-FILE *names;   // A pointer to the file containing possible NPC names
+/*
+ *     gameRunning
+ * 
+ *     This is one of the most important variables in the program. The main
+ *     loop of the game is set to break once this variable is set to false.
+ *     The only call to modify this variable is made in src/ui.cpp, where it
+ *     is set to false if either an SDL_QUIT message is received (the user
+ *     closes the window through their window manager) or if escape is pressed.
+ * 
+*/
+
+bool gameRunning = true;
+
+/*
+ *     currentWorld -  This is a pointer to the current world that the player
+ *                                     is in. Most drawing/entity handling is done through this
+ *                                     variable. This should only be changed when layer switch
+ *                                     buttons are pressed (see src/ui.cpp), or when the player
+ *                                     enters a Structure/Indoor World (see src/ui.cpp again).
+ * 
+ *     player           -      This points to a Player object, containing everything for
+ *                                     the player. Most calls made with currentWorld require a
+ *                                     Player object as an argument, and glOrtho is set based
+ *                                     off of the player's coordinates. This is probably the one
+ *                                     Entity-derived object that is not pointed to in the entity
+ *                                     array.
+ * 
+ *     entity           -      Contains pointers to 'all' entities that have been created in
+ *                                     the game, including NPCs, Structures, and Mobs. World draws
+ *                                     and entity handling done by the world cycle through entities
+ *                                     using this array. Entities made that aren't added to this
+ *                                     array probably won't be noticable by the game.
+ * 
+ *     npc                      -      An array of all NPCs in the game. It's not exactly clear how
+ *                                     NPC initing is done, their constructed in this array, then set
+ *                                     to be pointed to by entity, then maybe spawned with Entity->spawn().
+ *                                     See src/entities.cpp for more.
+ *                                     This variable might be referenced as an extern in other files.
+ * 
+ *     build            -      An array of all Structures in the game. Entries in entity point to
+ *                                     these, allowing worlds to handle the drawing and stuff of these.
+ *                                     See src/entities.cpp for more.
+ * 
+ *     mob                      -      An array of all Mobs in the game, entity entries should point to these
+ *                                     so the world can take care of them. See src/entities.cpp for more.
+ * 
+*/
+
+World                                                  *currentWorld=NULL;
+Player                                                 *player;
+std::vector<Entity *   >        entity;
+std::vector<NPC                        >        npc;
+std::vector<Structures *>       build;
+std::vector<Mob                        >        mob;
+
+/*
+ *     tickCount contains the number of ticks generated since main loop entrance.
+ *     This variable might be used anywhere.
+ * 
+ *     deltaTime is used for interpolation stuff.
+ * 
+ *     Pretty sure these variables are considered static as they might be externally
+ *     referenced somewhere.
+*/
+
+unsigned int tickCount = 0;
+unsigned int deltaTime = 0;
+
+/*
+ *     names is used to open a file containing all possible NPC names. It is externally
+ *     referenced in src/entities.cpp for getting random names.
+ *
+*/
+
+FILE *names;
+
+/*
+ *     These variables are used by SDL_mixer to create sound.
+ *     horn is not currently used, although it may be set.
+ * 
+*/
 
 Mix_Music *music;
 Mix_Chunk *horn;
+
+/*
+ *     loops is used for texture animation. It is believed to be passed to entity
+ *     draw functions, although it may be externally referenced instead.
+ * 
+*/
+
 unsigned int loops = 0;        // Used for texture animation
 
 extern void initEverything(void);      // Sets up the worlds and NPCs, see gameplay.cpp
@@ -193,8 +303,8 @@ void mainLoop(void){
                debugY = player->loc.y;
        }
        
-       mx = (ui::mouse.x+player->loc.x) - (SCREEN_WIDTH/2);
-       my = SCREEN_HEIGHT - ui::mouse.y;
+       //mx = (ui::mouse.x+player->loc.x) - (SCREEN_WIDTH/2);
+       //my = SCREEN_HEIGHT - ui::mouse.y;
        
        render();
 }
@@ -240,12 +350,12 @@ void render(){
                                        fps,player->ground,SCREEN_WIDTH,SCREEN_HEIGHT,entity.size(),player->loc.x,debugY,player->qh.current.size());
        }
        
-       glColor3ub(255,255,255);                        // Draw the mouse
-       glBegin(GL_TRIANGLES);                          //
-               glVertex2i(mx,my);                              //
-               glVertex2i(mx+HLINE*3.5,my);    //
-               glVertex2i(mx,my-HLINE*3.5);    //
-       glEnd();                                                        //
+       glColor3ub(255,255,255);                                                        // Draw the mouse
+       glBegin(GL_TRIANGLES);                                                          //
+               glVertex2i(ui::mouse.x,ui::mouse.y);                    //
+               glVertex2i(ui::mouse.x+HLINE*3.5,ui::mouse.y);  //
+               glVertex2i(ui::mouse.x,ui::mouse.y-HLINE*3.5);  //
+       glEnd();                                                                                        //
 
        /**************************
        ****  END RENDERING   ****
@@ -255,7 +365,7 @@ void render(){
        SDL_GL_SwapWindow(window);                                              //give the stack to SDL to render it
 }
 
-void logic(){
+void logic(){  
        ui::handleEvents();                             // Handle keyboard / mouse input
        currentWorld->detect(player);   // Handle gravity and world bounds
        
@@ -267,13 +377,13 @@ void logic(){
                                if(entity[i]->canMove)entity[i]->wander((rand()%120 + 30), &entity[i]->vel); // Make the NPC wander
                                
                                // Check if the NPC is near the player and handle potential interaction
-                               if(pow((entity[i]->loc.x - player->loc.x),2) + pow((entity[i]->loc.y - player->loc.y),2) <= pow(40*HLINE,2)){
-                                       if(mx >= entity[i]->loc.x && mx <= entity[i]->loc.x + entity[i]->width &&
-                                          my >= entity[i]->loc.y && my <= entity[i]->loc.y + entity[i]->width){
+                               if(pow((entity[i]->loc.x - player->loc.x),2) + pow((entity[i]->loc.y - player->loc.y),2) <= pow(40*HLINE,2)){   // NPC in range
+                                       if(ui::mouse.x >= entity[i]->loc.x && ui::mouse.x <= entity[i]->loc.x + entity[i]->width &&     // Mouse is hovering over NPC
+                                          ui::mouse.y >= entity[i]->loc.y && ui::mouse.y <= entity[i]->loc.y + entity[i]->width){
                                                entity[i]->near=true; // Allows the NPC's name to be drawn
-                                               if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)){
-                                                       entity[i]->interact(); // Interact with the player
-                                                       //Mix_PlayChannel( -1, horn, 0);
+                                               if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)){ // If right click
+                                                       entity[i]->interact();                          // Interact with the player
+                                                       //Mix_PlayChannel( -1, horn, 0);        // Audio feedback
                                                }
                                        }else entity[i]->near=false;
                                }
index 182b5b85887bb93e0a99c22ce5e1c39a6f6fb248..8dcbd1181ab4ce5181dc87646bb8f863b34609ed 100644 (file)
@@ -31,4 +31,3 @@ void DEBUG_prints(const char* file, int line, const char *s,...){
        vprintf(s,args);
        va_end(args);
 }
-
index 32b74fe7c11f4a738d599c54ed1ce52b111adeea..2bc5a6105a20ca7242229c7fadd6d06ab59503b4 100644 (file)
@@ -16,6 +16,8 @@ void Entity::spawn(float x, float y){ //spawns the entity you pass to it based o
        ticksToUse = 0;
        canMove = true;
        ground = false;
+       alive = true;
+       if(!maxHealth)health = maxHealth = 50;
        name = (char*)malloc(16);
        getName();
 }
@@ -156,12 +158,6 @@ void Entity::draw(void){           //draws the entities
        glDisable(GL_TEXTURE_2D);
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
-       if(type == PLAYERT){
-               ui::setFontSize(16);
-               ui::putText(((SCREEN_WIDTH / 2 ) + loc.x) - 125, SCREEN_HEIGHT - ui::fontSize, "Health: %d/%d",health,maxHealth);
-               glColor3ub(255,0,0);
-               glRectf((SCREEN_WIDTH / 2 + loc.x) - 125, SCREEN_HEIGHT - 32, ((SCREEN_WIDTH / 2 + loc.x) - 125) + (((float)health / (float)maxHealth) * 100), SCREEN_HEIGHT - 32 + 12);
-       }
        if(near){
                ui::setFontSize(14);
                ui::putText(loc.x,loc.y-ui::fontSize-HLINE/2,"%s",name);
@@ -217,31 +213,20 @@ void NPC::wander(int timeRun, vec2 *v){ //this makes the entites wander about
        ticksToUse--; //removes one off of the entities timer
 }
 
-static int (*AIpreload)(NPC *);
+std::vector<int (*)(NPC *)> AIpreload; // A dynamic array of AI functions that are being preloaded
+std::vector<void *> AIpreaddr;                 // A dynamic array of pointers to the NPC's that are being assigned the preloads
 
 void NPC::addAIFunc(int (*func)(NPC *),bool preload){
-       if(preload)
-#ifdef DEBUG
-       {
+       if(preload){                                                                            // Preload AI functions so that they're given after 
+#ifdef DEBUG                                                                                   // the current dialog box is closed
                DEBUG_printf("Preloading an AI %x.\n",func);
 #endif // DEBUG
-               AIpreload=func;
-#ifdef DEBUG
+               AIpreload.push_back(func);
+               AIpreaddr.push_back(this);
        }
-#endif // DEBUG
        else aiFunc.push_back(func);
 }
 
-void NPC::flushAIFunc(void){
-       if(AIpreload){
-#ifdef DEBUG
-               DEBUG_printf("Unloading preloaded AI function %x.\n",AIpreload);
-#endif // DEBUG
-               aiFunc.push_back(AIpreload);
-               AIpreload=NULL;
-       }
-}
-
 void NPC::interact(){ //have the npc's interact back to the player
        int (*func)(NPC *);
        loc.y += 5;
@@ -259,6 +244,7 @@ unsigned int Structures::spawn(_TYPE t, float x, float y){ //spawns a structure
        loc.x = x;
        loc.y = y;
        type = t;
+       alive = true;
 
        /*VILLAGE*/
        //spawns a village
index 26897668d257f4df4a70fba7db3034db14a90b71..a62086e5920a8c0947e00cbf87b24f4bc9fa9480 100644 (file)
@@ -8,7 +8,8 @@
 extern Player *player;                 // 'player' should be (must be) defined in main.cpp
 extern World  *currentWorld;   // should/must also be defined in main.cpp
 
-extern std::vector<NPC>npc;
+extern std::vector<int (*)(NPC *)> AIpreload;  // see entities.cpp
+extern std::vector<void *> AIpreaddr;                  //
 
 static FT_Library   ftl;               // Variables for the FreeType library and stuff
 static FT_Face      ftf;
@@ -171,18 +172,31 @@ namespace ui {
                        setFontSize(16);
                        putString(x+HLINE,y-fontSize-HLINE,dialogBoxText);
                }
+               setFontSize(16);
+               putText(((SCREEN_WIDTH/2)+player->loc.x)-125,SCREEN_HEIGHT-fontSize,"Health: %u/%u",player->health>0?(unsigned)player->health:0,
+                                                                                                                                                                                       (unsigned)player->maxHealth);
+               if(player->alive){
+                       glColor3ub(255,0,0);
+                       glRectf((SCREEN_WIDTH/2+player->loc.x)-125,
+                                       SCREEN_HEIGHT-32,
+                                       ((SCREEN_WIDTH/2+player->loc.x)-125)+((player->health/player->maxHealth)*100),
+                                       SCREEN_HEIGHT-32+12);
+               }
        }
        void handleEvents(void){
                static bool left=false,right=false;
+               static vec2 premouse={0,0};
                SDL_Event e;
+               mouse.x=premouse.x+player->loc.x-(SCREEN_WIDTH/2);
+               mouse.y=SCREEN_HEIGHT-premouse.y;
                while(SDL_PollEvent(&e)){
                        switch(e.type){
                        case SDL_QUIT:
                                gameRunning=false;
                                break;
                        case SDL_MOUSEMOTION:
-                               mouse.x=e.motion.x;
-                               mouse.y=e.motion.y;
+                               premouse.x=e.motion.x;
+                               premouse.y=e.motion.y;
                                break;
                        case SDL_MOUSEBUTTONDOWN:
                                if((e.button.button&SDL_BUTTON_RIGHT)&&dialogBoxExists){
@@ -244,13 +258,14 @@ namespace ui {
                                break;
                        }
                }
-               static bool once=false;
+               
                unsigned int i;
-               if(!dialogBoxExists&&!once){
-                       for(i=0;i<npc.size();i++){
-                               npc[i].flushAIFunc();
+               if(!dialogBoxExists&&AIpreaddr.size()){ // Flush preloaded AI functions if necessary
+                       for(i=0;i<AIpreaddr.size();i++){
+                               NPCp(AIpreaddr.front())->addAIFunc(AIpreload.front(),false);
+                               AIpreaddr.erase(AIpreaddr.begin());
+                               AIpreload.erase(AIpreload.begin());
                        }
-                       once=true;
-               }else once=false;
+               }
        }
 }
index 14980161b6a63f0fb9261023a392b96f6e44820e..3b1fd87f253074f291670aff9e0be1aff22a059b 100644 (file)
@@ -34,6 +34,7 @@ void World::generate(unsigned int width){     // Generates the world and sets all va
        unsigned int i;                                         // Used for 'for' loops 
        float inc;                                                      // See line 40
        lineCount=width+GEN_INC;                        // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
+       if(lineCount<=0)abort();
        
        line=(struct line_t *)calloc(lineCount,sizeof(struct line_t));  // Allocate memory for the array 'line'
        
@@ -156,7 +157,9 @@ LOOP2:                                                                                                      // Draw each world
 
 void World::singleDetect(Entity *e){
        unsigned int i;
-       if(e->alive){
+       if(e->health<=0){
+               e->alive=false;
+       }else if(e->alive){
                i=(e->loc.x+e->width/2-x_start)/HLINE;  // Calculate what line the player is currently on
                if(e->type==STRUCTURET||e->loc.y<line[i].y){
                        e->vel.y=0;
@@ -166,7 +169,7 @@ void World::singleDetect(Entity *e){
                                //std::cout<<e->loc.x<<" "<<e->loc.y<<std::endl;
                                return;
                        }
-               }else if(e->loc.y>line[i].y-.002*deltaTime){    // Snap the player to the top of that line if the player is inside it
+               }else if(e->loc.y>line[i].y-.002*deltaTime){
                        for(i=0;i<platform.size();i++){
                                if(((e->loc.x+e->width>platform[i].p1.x)&(e->loc.x+e->width<platform[i].p2.x))||
                                   ((e->loc.x<platform[i].p2.x)&(e->loc.x>platform[i].p1.x))){
@@ -290,6 +293,7 @@ IndoorWorld::~IndoorWorld(void){
 void IndoorWorld::generate(unsigned int width){                // Generates a flat area of width 'width'
        unsigned int i;                                         // Used for 'for' loops 
        lineCount=width+GEN_INC;                        // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
+       if(lineCount<=0)abort();
        
        line=(struct line_t *)calloc(lineCount,sizeof(struct line_t));  // Allocate memory for the array 'line'