aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog15
-rw-r--r--include/entities.h5
-rw-r--r--main.cpp178
-rw-r--r--src/common.cpp1
-rw-r--r--src/entities.cpp32
-rw-r--r--src/ui.cpp33
-rw-r--r--src/world.cpp8
7 files changed, 200 insertions, 72 deletions
diff --git a/Changelog b/Changelog
index 752d92c..77edf73 100644
--- a/Changelog
+++ b/Changelog
@@ -117,3 +117,18 @@
- 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
diff --git a/include/entities.h b/include/entities.h
index 431407b..655390b 100644
--- a/include/entities.h
+++ b/include/entities.h
@@ -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*);
};
diff --git a/main.cpp b/main.cpp
index bb93a07..828c0b2 100644
--- a/main.cpp
+++ b/main.cpp
@@ -6,32 +6,142 @@
#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;
}
diff --git a/src/common.cpp b/src/common.cpp
index 182b5b8..8dcbd11 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -31,4 +31,3 @@ void DEBUG_prints(const char* file, int line, const char *s,...){
vprintf(s,args);
va_end(args);
}
-
diff --git a/src/entities.cpp b/src/entities.cpp
index 32b74fe..2bc5a61 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -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
diff --git a/src/ui.cpp b/src/ui.cpp
index 2689766..a62086e 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -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;
+ }
}
}
diff --git a/src/world.cpp b/src/world.cpp
index 1498016..3b1fd87 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -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'