aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordrumsetmonkey <abelleisle@roadrunner.com>2016-03-01 08:43:33 -0500
committerdrumsetmonkey <abelleisle@roadrunner.com>2016-03-01 08:43:33 -0500
commitd42b81661ac1d1303746082b3606e80e92f5fdd6 (patch)
tree1458419db1bc95c0ac63311385c34cb2913445d2
parent20948cfe47f1fbeeed04e890c457d83cc826d74d (diff)
parent47f8aa5b312a5ef671e83322bcbe201a034f84c0 (diff)
Merge branch 'master' of http://github.com/tcsullivan/gamedev
-rw-r--r--Changelog17
-rw-r--r--include/common.h5
-rw-r--r--include/world.h61
-rw-r--r--main.cpp56
-rw-r--r--src/common.cpp7
-rw-r--r--src/entities.cpp2
-rw-r--r--src/gameplay.cpp10
-rw-r--r--src/inventory.cpp4
-rw-r--r--src/ui.cpp967
-rw-r--r--src/world.cpp1377
-rw-r--r--xml/playerSpawnHill1.xml2
11 files changed, 1073 insertions, 1435 deletions
diff --git a/Changelog b/Changelog
index b85c195..0384181 100644
--- a/Changelog
+++ b/Changelog
@@ -690,10 +690,25 @@
- looked into better automated Makefiles
- improving villages, began work on shops
-2/26/2015:
+2/26/2016:
==========
- made fonts more memory-efficient
- C++-ified loaded texture handlers
- documented more stuff
- made merchant menu
+
+2/29/2016:
+==========
+
+ - renewed branch 'remake': re-wrote world.cpp and pushed
+ - fixed world linkage errors
+ - considered more formal coding? (as in documentation and indentation)
+ - fixed dialog boxes and options
+ - broke screenshots
+
+3/1/2016:
+=========
+
+ - merged 'remake' with 'master', fixed font issues and world stuffs
+ - continued work on merchant dialog
diff --git a/include/common.h b/include/common.h
index 933067b..9650f49 100644
--- a/include/common.h
+++ b/include/common.h
@@ -151,6 +151,9 @@ extern float VOLUME_SFX;
#define getRand() rand()
+#define randGet rand
+#define randInit srand
+
/**
* Included in common.h is a prototype for DEBUG_prints, which writes a formatted
* string to the console containing the callee's file and line number. This macro simplifies
@@ -230,4 +233,6 @@ int strCreateFunc(const char *equ);
template<typename N, size_t s>
size_t arrAmt(N (&)[s]){return s;}
+void UserError(std::string reason);
+
#endif // COMMON_H
diff --git a/include/world.h b/include/world.h
index 733daae..b3d1071 100644
--- a/include/world.h
+++ b/include/world.h
@@ -11,24 +11,11 @@
#include <common.h>
#include <entities.h>
-/**
- * Defines at what interval y values should be calculated for the array 'line'.
- */
-
-#define GEN_INC 10
-
-/**
- * Defines the lowest possible y value for a world line.
- */
-
-#define GEN_MIN 80
-
-/**
- * Defines the highest possible y value for a randomly generated world line.
- */
-
-#define GEN_MAX 110
+#define GROUND_HEIGHT_INITIAL 80
+#define GROUND_HEIGHT_MINIMUM 60
+#define GROUND_HEIGHT_MAXIMUM 110
+#define GROUND_HILLINESS 10
/**
* Defines how many game ticks it takes for a day to elapse.
@@ -44,7 +31,7 @@
typedef enum {
BG_FOREST, /**< A forest theme. */
- BG_WOODHOUSE /**< An indoor wooden house theme. */
+ BG_WOODHOUSE, /**< An indoor wooden house theme. */
} WORLD_BG_TYPE;
/**
@@ -74,12 +61,12 @@ typedef struct {
* lines. Dirt color and grass properties are also kept track of here.
*/
-typedef struct line_t {
- float y; /**< Height of this vertical line */
- bool gs; /**< Show grass */
- float gh[2]; /**< Height of glass (2 blades per line) */
- unsigned char color; /**< Lightness of dirt (brown) */
-} line_t;
+typedef struct {
+ bool grassUnpressed;
+ float grassHeight[2];
+ float groundHeight;
+ unsigned char groundColor;
+} WorldData;
class World;
@@ -151,7 +138,7 @@ protected:
* of elements provided by the function.
*/
- struct line_t *line;
+ std::vector<WorldData> worldData;
/**
* Starting x coordinate.
@@ -159,7 +146,7 @@ protected:
* calculate the width of the world.
*/
- int x_start;
+ int worldStart;
/**
* Handle physics for a single entity.
@@ -195,7 +182,7 @@ protected:
* An array of star coordinates.
*/
- vec2 *star;
+ std::vector<vec2> star;
/**
* The Texturec object that holds the background sprites for this world.
@@ -301,7 +288,7 @@ public:
* A vector of all light elements in this world.
*/
- std::vector<Light > light;
+ std::vector<Light> light;
/**
* Vector of all building textures for the current world style
@@ -315,7 +302,7 @@ public:
* generate().
*/
- World(void);
+ World( void );
/**
* Frees resources taken by the world.
@@ -397,14 +384,6 @@ public:
virtual void generate(unsigned int width);
/**
- * Generates a world of the provided width using the given function to
- * determine ground coordinates. The given y coordinates from the function
- * are limited to a certain range, most likely from GEN_MIN to 2000.
- */
-
- void generateFunc(unsigned int width,float(*func)(float));
-
- /**
* Sets the background theme, collecting the required textures into a
* Texturec object.
*/
@@ -486,12 +465,6 @@ public:
};
/*
- * Gets a good base y value for background rendering.
-*/
-
-float worldGetYBase(World *w);
-
-/*
* IndoorWorld - Indoor settings stored in a World class ;)
*/
@@ -516,7 +489,7 @@ public:
};
extern int worldShade;
-extern char *currentXML;
+extern std::string currentXML;
World *loadWorldFromXML(const char *path);
World *loadWorldFromXMLNoSave(const char *path);
diff --git a/main.cpp b/main.cpp
index fa833fb..abc4f3c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -78,12 +78,6 @@ World *currentWorld = NULL;
Player *player;
/**
- * Tells if player is currently inside a world entered through a Structure.
- */
-
-extern bool worldInside;
-
-/**
* TODO
*/
@@ -217,9 +211,11 @@ void mainLoop(void);
/*******************************************************************************
* MAIN ************************************************************************
*******************************************************************************/
-int main(/*int argc, char *argv[]*/){
- // *argv = (char *)argc;
- SDL_GLContext mainGLContext = NULL;
+int main(int argc, char *argv[]){
+ (void)argc;
+ (void)argv;
+
+ static SDL_GLContext mainGLContext = NULL;
gameRunning=false;
@@ -322,16 +318,7 @@ int main(/*int argc, char *argv[]*/){
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
- * if they have error.
- */
-
- //ui::initFonts();
- //ui::setFontFace("ttf/FreePixel.ttf"); // as in gamedev/ttf/<font>
+ }
/*
* Initialize the random number generator. At the moment, initRand is a macro pointing to libc's
@@ -476,7 +463,7 @@ void mainLoop(void){
currentTime = 0, //
prevPrevTime= 0; //
World *prev;
-
+
if(!currentTime) // Initialize currentTime if it hasn't been
currentTime=millis();
@@ -496,14 +483,15 @@ void mainLoop(void){
*/
prev = currentWorld;
- pool.Enqueue(ui::handleEvents);
- //ui::handleEvents();
+
+ //pool.Enqueue(ui::handleEvents);
+ ui::handleEvents();
if(prev != currentWorld){
currentWorld->bgmPlay(prev);
ui::dialogBoxExists = false;
}
-
+
if(prevPrevTime + MSEC_PER_TICK <= currentTime){
//pool.Enqueue(logic);
logic();
@@ -517,20 +505,21 @@ void mainLoop(void){
/*pool.Enqueue([](){
currentWorld->update(player,deltaTime);
});*/
- currentWorld->update(player,deltaTime);
+ currentWorld->update(player,deltaTime);
+
/*
* Update debug variables if necessary
*/
- if(++debugDiv==20)
+ if ( ++debugDiv == 20 ) {
debugDiv=0;
- if(deltaTime)
- fps=1000/deltaTime;
- else if(!(debugDiv%10))
- debugY = player->loc.y;
-
+ if ( deltaTime )
+ fps = 1000 / deltaTime;
+ else if(!(debugDiv%10))
+ debugY = player->loc.y;
+ }
MENU:
render();
}
@@ -552,7 +541,7 @@ void render(){
if(currentWorld->getTheWidth() < (int)SCREEN_WIDTH){
offset.x = 0;
- }else if(!worldInside){
+ }else{
if(player->loc.x - SCREEN_WIDTH/2 < currentWorld->getTheWidth() * -0.5f)
offset.x = ((currentWorld->getTheWidth() * -0.5f) + SCREEN_WIDTH / 2) + player->width / 2;
if(player->loc.x + player->width + SCREEN_WIDTH/2 > currentWorld->getTheWidth() * 0.5f)
@@ -659,11 +648,6 @@ void render(){
player->inv->draw();
/*
-<<<<<<< HEAD
- * Here we draw a black overlay if it's been requested.
- */
-
- /*
* Here we draw a black overlay if it's been requested.
*/
diff --git a/src/common.cpp b/src/common.cpp
index 01c8779..6dc2c46 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -95,6 +95,13 @@ const char *readFile(const char *path){
return buf;
}
+void
+UserError( std::string reason )
+{
+ std::cout << "User error: " << reason << "!" << std::endl;
+ abort();
+}
+
/*int strCreateFunc(const char *equ){
static unsigned int size;
static char *filebuf;
diff --git a/src/entities.cpp b/src/entities.cpp
index b0013d2..b97767d 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -613,7 +613,7 @@ void Player::save(void){
for(auto &i : inv->items)
data.append(std::to_string((int)i.count) + "\n" + std::to_string((int)i.id) + "\n");
- data.append((std::string)(currentXML+4) + "\n");
+ data.append((std::string)(currentXML.c_str() + 4) + "\n");
data.append("dOnE\0");
out.write(data.c_str(),data.size());
diff --git a/src/gameplay.cpp b/src/gameplay.cpp
index e16e892..3d2ea25 100644
--- a/src/gameplay.cpp
+++ b/src/gameplay.cpp
@@ -43,7 +43,7 @@ int commonAIFunc(NPC *speaker){
* Load the current world's XML file into memory for reading.
*/
- xml.LoadFile(currentXML);
+ xml.LoadFile(currentXML.c_str());
exml = xml.FirstChildElement("Dialog");
/*
@@ -221,7 +221,7 @@ void commonTriggerFunc(Mob *callee){
if(!lock){
lock = true;
- xml.LoadFile(currentXML);
+ xml.LoadFile(currentXML.c_str());
exml = xml.FirstChildElement("Trigger");
while(strcmp(exml->Attribute("id"),callee->heyid.c_str()))
@@ -282,12 +282,12 @@ void initEverything(void){
/*
* Read in the XML file.
*/
-
+
currentWorld = loadWorldFromXML(xmlFiles[i].c_str());
break;
}
}
-
+
pauseMenu.items.push_back(ui::createParentButton({-256/2,0},{256,75},{0.0f,0.0f,0.0f}, "Resume"));
pauseMenu.items.push_back(ui::createChildButton({-256/2,-100},{256,75},{0.0f,0.0f,0.0f}, "Options"));
pauseMenu.items.push_back(ui::createButton({-256/2,-200},{256,75},{0.0f,0.0f,0.0f}, "Save and Quit", ui::quitGame));
@@ -320,7 +320,7 @@ extern std::vector<NPC *> AIpreaddr;
void destroyEverything(void){
currentWorld->save();
delete currentWorld;
- delete[] currentXML;
+ //delete[] currentXML;
while(!AIpreload.empty())
AIpreload.pop_back();
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 92cce75..cd8bb71 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -415,6 +415,8 @@ int Inventory::useItem(void){
}
bool Inventory::detectCollision(vec2 one, vec2 two){
+ (void)one;
+ (void)two;
//float i = 0.0f;
/*if(items.empty() || !items[sel].count)
@@ -441,6 +443,6 @@ bool Inventory::detectCollision(vec2 one, vec2 two){
i+=HLINE;
}
}*/
- return !(one.x == two.y);
+ return false;
}
diff --git a/src/ui.cpp b/src/ui.cpp
index d5e2139..7aed916 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -1,51 +1,52 @@
#include <ui.h>
-/**
- * A macro for easier SDL key reading
- */
+/*
+ * Create a macro to easily access SDL keypresses
+*/
#define SDL_KEY e.key.keysym.sym
+extern std::vector<menuItem>optionsMenu;
+
+extern SDL_Window *window;
+
/*
- * Important to have..
- */
+ * External references for updating player coords / current world.
+*/
-extern SDL_Window *window;
-extern Player *player;
-extern World *currentWorld;
-extern bool gameRunning;
+extern Player *player;
+extern World *currentWorld;
/*
- * NPC AI functions are given to the NPCs within UI loops.
- */
+ * In the case of dialog, some NPC quests can be preloaded so that they aren't assigned until
+ * the dialog box closes. Reference variables for that here.
+*/
extern std::vector<int (*)(NPC *)> AIpreload;
extern std::vector<NPC *> AIpreaddr;
/*
- * Variables and objects used with the FreeType library and font rendering.
- */
-
-#define FT_CHAR_COUNT 93
+ * Pressing ESC or closing the window will set this to false.
+*/
-typedef struct {
- GLuint tex; /**< OpenGL texture object */
- ivec2 wh; /**< Width and height of the character */
- ivec2 bl; /**< Offset for drawing the character? */
- ivec2 ad; /**< Number of pixels to advance cursor. */
-} FT_Tex;
+extern bool gameRunning;
-static FT_Tex ftmap16[FT_CHAR_COUNT],
- ftmap24[FT_CHAR_COUNT],
- *ftmapptr;
+/*
+ * Freetype variables, and a GLuint for referencing rendered letters.
+*/
static FT_Library ftl;
static FT_Face ftf;
+static GLuint ftex[93];
+static vec2 ftexwh[93];
+static vec2 ftexbl[93];
+static vec2 ftexad[93];
+
static unsigned char fontColor[3] = {255,255,255};
/*
* Variables for dialog boxes / options.
- */
+*/
static char dialogBoxText[512];
static char *dialogOptText[4];
@@ -58,168 +59,109 @@ static bool typeOutDone = true;
* Menu-related objects
*/
-extern Menu *currentMenu;
+extern Menu* currentMenu;
extern Menu pauseMenu;
-/**
- * The sound made when displaying characters with dialogBox or importantText.
- */
static Mix_Chunk *dialogClick;
-/*
- * Other sounds
- */
-
-Mix_Chunk *battleStart;
-Mix_Chunk *sanic;
-
-/**
- * A reference to the main loop function for functions like waitForCover().
- */
-
extern void mainLoop(void);
/*
- * Overlay variables
- */
+ * Toggled by pressing 'q', disables some controls when true.
+*/
bool fadeEnable = false;
-bool fadeWhite = false;
-bool fadeFast = false;
-
+bool fadeWhite = false;
+bool fadeFast = false;
unsigned int fadeIntensity = 0;
-/**
- * Set to true when the player is in a battle area (i.e. currentWorld points to
- * an Arena).
- */
-
bool inBattle = false;
+Mix_Chunk *battleStart;
-
+Mix_Chunk *sanic;
void Menu::gotoParent(){
- if(!parent){
+ if(parent == NULL){
currentMenu = NULL;
updateConfig();
- }else
+ }else{
currentMenu = parent;
+ }
}
void Menu::gotoChild(){
- if(!child)
+ if(child == NULL){
currentMenu = NULL;
- else
+ }else{
currentMenu = child;
+ }
}
-static vec2 premouse={0,0};
-
namespace ui {
- /**
- * The current position of the mouse.
- */
+ /*
+ * Mouse coordinates.
+ */
vec2 mouse;
+ static vec2 premouse={0,0};
- /**
- * If true, debug information will be drawn to the screen.
- */
-
- bool debug = false;
-
- /**
- * If true, lines should be drawn to the player when the debug menu is open.
- */
+ /*
+ * Variety of keydown bools
+ */
+ bool edown;
+
+ /*
+ * Debugging flags.
+ */
+ bool debug=false;
bool posFlag=false;
-
- /**
- * If true, the player will be able to move when the current dialog box is
- * displayed.
- */
-
bool dialogPassive = false;
bool dialogMerchant = false;
std::vector<BuySell> *minv;
int dialogPassiveTime = 0;
- /**
- * When set to true the dialog box will attempt to display.
- */
-
- bool dialogBoxExists = false;
- /**
- * When set to true the text will display as 'important' text.
- */
+ /*
+ * Dialog stuff that needs to be 'public'.
+ */
+ bool dialogBoxExists = false;
bool dialogImportant = false;
-
- /**
- * Contains the last chosen dialog option.
- */
-
unsigned char dialogOptChosen = 0;
- /**
- * Determines how many characters can be displayed in a dialog box before
- * a new line is required.
- */
-
unsigned int textWrapLimit = 110;
- /**
- * The current font size.
- *
- * DO NOT change this directly, use setFontSize() instead.
- */
+ /*
+ * Current font size. Changing this WILL NOT change the font size, see setFontSize() for
+ * actual font size changing.
+ */
unsigned int fontSize;
- /**
- * Initializes the Freetype library, and other UI related variables.
- */
+ /*
+ * Initialises the Freetype library, and sets a font size.
+ */
void initFonts(void){
-
- // init the FreeType library
if(FT_Init_FreeType(&ftl)){
- std::cout<<"Error! Couldn't initialize the FreeType library."<<std::endl;
+ std::cout<<"Error! Couldn't initialize freetype."<<std::endl;
abort();
}
-
- fontSize = 16;
-
- //ftmap16 = new FT_Tex[FT_CHAR_COUNT];
- //ftmap24 = new FT_Tex[FT_CHAR_COUNT];
-
- memset(&ftmap16, 0, FT_CHAR_COUNT * sizeof(FT_Tex));
- memset(&ftmap24, 0, FT_CHAR_COUNT * sizeof(FT_Tex));
-
+ fontSize=0;
+ memset(&ftex,0,93*sizeof(GLuint));
#ifdef DEBUG
DEBUG_printf("Initialized FreeType2.\n",NULL);
#endif // DEBUG
-
- /*
- * Load UI related sounds.
- */
-
dialogClick = Mix_LoadWAV("assets/sounds/click.wav");
battleStart = Mix_LoadWAV("assets/sounds/frig.wav");
- sanic = Mix_LoadWAV("assets/sounds/sanic.wav");
+ sanic = Mix_LoadWAV("assets/sounds/sanic.wav");
+ //Mix_Volume(1,50);
}
- /**
- * Frees resources taken by the UI facilities
- */
-
void destroyFonts(void){
- //delete[] ftmap16;
- //delete[] ftmap24;
-
FT_Done_Face(ftf);
FT_Done_FreeType(ftl);
@@ -228,120 +170,92 @@ namespace ui {
Mix_FreeChunk(sanic);
}
- /**
- * Sets a new font face to use (*.ttf).
- */
+ /*
+ * Sets a new font family to use (*.ttf).
+ */
void setFontFace(const char *ttf){
- std::unique_ptr<uint8_t[]> rgbaBuf;
- size_t rgbaBufSize, ftsize;
- unsigned int i,j;
- FT_Error fte;
-
- if((fte = FT_New_Face(ftl,ttf,0,&ftf))){
- std::cout<<"Error! Couldn't open "<<ttf<<" (Error "<<fte<<")."<<std::endl;
+ if(FT_New_Face(ftl,ttf,0,&ftf)){
+ std::cout<<"Error! Couldn't open "<<ttf<<"."<<std::endl;
abort();
}
-
#ifdef DEBUG
DEBUG_printf("Using font %s\n",ttf);
#endif // DEBUG
-
+ }
+
+ /*
+ * Sets a new font size (default: 12).
+ */
+
+ void setFontSize(unsigned int size){
+ unsigned int i,j;
+ char *buf;
+
+ fontSize=size;
+ FT_Set_Pixel_Sizes(ftf,0,fontSize);
+
/*
- * Load the font in the two sizes we use, 16px and 24px.
- */
+ * Pre-render 'all' the characters.
+ */
- ftmapptr = ftmap16;
- ftsize = 16;
-
- do{
- FT_Set_Pixel_Sizes(ftf, 0, ftsize);
-
- // allocate texture space
- for(i=0; i < FT_CHAR_COUNT; i++)
- glGenTextures(1, &ftmapptr[i].tex);
-
- // Load all characters we expect to use
- for(i=33; i<126; i++){
-
- // Load the bitmap for the current character.
- if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){
- std::cout<<"Error! Unsupported character "<<(char)i<<" ("<<i<<")."<<std::endl;
- abort();
- }
-
- /*
- * Set up the OpenGL texture thing.
- */
-
- glBindTexture(GL_TEXTURE_2D, ftmapptr[i-33].tex);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR );
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR );
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- /*
- * Convert the bitmap font given to us from FreeType into an RGBA
- * format, for ease of drawing.
- */
-
- rgbaBuf.reset(new uint8_t [(rgbaBufSize = ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4)]);
- rgbaBufSize /= 4;
+ glDeleteTextures(93,ftex); // delete[] any already-rendered textures
+ glGenTextures(93,ftex); // Generate new texture name/locations?
+
+ for(i=33;i<126;i++){
+
+ /*
+ * Load the character from the font family file.
+ */
+
+ if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){
+ std::cout<<"Error! Unsupported character "<<(char)i<<" ("<<i<<")."<<std::endl;
+ abort();
+ }
- // populate the buffer
- for(j=0; j < rgbaBufSize; j++){
- rgbaBuf[j * 4] = rgbaBuf[j * 4 + 1] = rgbaBuf[j * 4 + 2] = 255;
- rgbaBuf[j * 4 + 3] = ftf->glyph->bitmap.buffer[j] ? 255 : 0;
- }
-
- // save important character information
- ftmapptr[i-33].wh = { (int)ftf->glyph->bitmap.width, (int)ftf->glyph->bitmap.rows };
- ftmapptr[i-33].bl = { ftf->glyph->bitmap_left, ftf->glyph->bitmap_top };
- ftmapptr[i-33].ad = { ftf->glyph->advance.x >> 6, ftf->glyph->advance.y >> 6 };
+ /*
+ * Transfer the character's bitmap (?) to a texture for rendering.
+ */
+
+ glBindTexture(GL_TEXTURE_2D,ftex[i-33]);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S ,GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T ,GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER ,GL_LINEAR );
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER ,GL_LINEAR );
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+
+ /*
+ * The just-created texture will render red-on-black if we don't do anything to it, so
+ * here we create a buffer 4 times the size and transform the texture into an RGBA array,
+ * making it white-on-black.
+ */
- // do the thing
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftf->glyph->bitmap.width, ftf->glyph->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf.get());
- rgbaBuf.reset();
- }
-
- // repeat for 24px, or exit
- if(ftmapptr == ftmap16){
- ftmapptr = ftmap24;
- ftsize = 24;
- }else{
- break;
+ buf = new char[ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4];
+
+ for(j=0;j<ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows;j++){
+ buf[j*4 ]=255;//fontColor[0];
+ buf[j*4+1]=255;//fontColor[1];
+ buf[j*4+2]=255;//fontColor[2];
+ buf[j*4+3]=ftf->glyph->bitmap.buffer[j] ? 255 : 0;
+ //buf[j*4+3]=ftf->glyph->bitmap.buffer[j];
}
- }while(1);
-
- setFontSize(16);
- }
-
- /**
- * Sets a new font size and renders the necessary characters (default font
- * size: 16; 24 for importantText).
- */
-
- void setFontSize(unsigned int size){
- mtx.lock();
- switch((fontSize = size)){
- case 24:
- ftmapptr = ftmap24;
- break;
- default:
- case 16:
- ftmapptr = ftmap16;
- break;
+ ftexwh[i-33].x=ftf->glyph->bitmap.width;
+ ftexwh[i-33].y=ftf->glyph->bitmap.rows;
+ ftexbl[i-33].x=ftf->glyph->bitmap_left;
+ ftexbl[i-33].y=ftf->glyph->bitmap_top;
+ ftexad[i-33].x=ftf->glyph->advance.x>>6;
+ ftexad[i-33].y=ftf->glyph->advance.y>>6;
+
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,ftf->glyph->bitmap.width,ftf->glyph->bitmap.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
+
+ delete[] buf; //free(buf);
}
- mtx.unlock();
}
- /**
- * Set a color for font rendering (default: white).
- */
+ /*
+ * Set a color for font rendering (default: white).
+ */
void setFontColor(unsigned char r,unsigned char g,unsigned char b){
fontColor[0]=r;
@@ -349,267 +263,264 @@ namespace ui {
fontColor[2]=b;
}
- /**
- * Draws a character at the specified coordinates, aborting if the character is undrawable.
- */
+ /*
+ * Draws a character at the specified coordinates, aborting if the character is unknown.
+ */
- ivec2 putChar(float x,float y,char c){
- ivec2 c1,c2;
+ vec2 putChar(float xx,float yy,char c){
+ vec2 c1,c2;
- // calculate coordinates
- c1 = { (int)floor(x) + ftmapptr[c-33].bl.x,
- (int)floor(y) + ftmapptr[c-33].bl.y };
- c2 = ftmapptr[c-33].wh;
+ int x = xx, y = yy;
+
+ /*
+ * Get the width and height of the rendered character.
+ */
+
+ c1={(float)floor(x)+ftexbl[c-33].x,
+ (float)floor(y)+ftexbl[c-33].y};
+ c2=ftexwh[c-33];
/*
- * Draw the character
- */
+ * Draw the character:
+ */
glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, ftmapptr[c-33].tex);
-
+ glBindTexture(GL_TEXTURE_2D,ftex[c-33]);
glPushMatrix();
glTranslatef(0,-c2.y,0);
-
glBegin(GL_QUADS);
- glColor3ub(fontColor[0], fontColor[1], fontColor[2]);
-
- glTexCoord2f(0, 1); glVertex2f(c1.x , c1.y );
- glTexCoord2f(1, 1); glVertex2f(c1.x + c2.x, c1.y );
- glTexCoord2f(1, 0); glVertex2f(c1.x + c2.x, c1.y + c2.y);
- glTexCoord2f(0, 0); glVertex2f(c1.x , c1.y + c2.y);
-
+ glColor3ub(fontColor[0],fontColor[1],fontColor[2]);
+ glTexCoord2f(0,1);glVertex2f(c1.x ,c1.y );
+ glTexCoord2f(1,1);glVertex2f(c1.x+c2.x,c1.y );
+ glTexCoord2f(1,0);glVertex2f(c1.x+c2.x,c1.y+c2.y);
+ glTexCoord2f(0,0);glVertex2f(c1.x ,c1.y+c2.y);
glEnd();
-
glPopMatrix();
glDisable(GL_TEXTURE_2D);
-
- // return the number of pixels the cursor should move
- return ftmapptr[c-33].ad;
+
+ /*
+ * return the width.
+ */
+
+ return ftexad[c-33];//(vec2){c2.x,ftexad[c-33].y};
}
- /**
- * Draw a string at the specified coordinates.
- */
+ /*
+ * Draw a string at the specified coordinates.
+ */
float putString(const float x,const float y,const char *s){
- unsigned int i = 0;
- ivec2 add;
- vec2 off = { (float)floor(x), (float)floor(y) };
+ unsigned int i=0;
+ float xo=x,yo=y;
+ vec2 add;
/*
* Loop on each character:
- */
+ */
do{
- // wrap text if necessary
- if(i && (i / (float)textWrapLimit == i / textWrapLimit)){
- off.y -= fontSize * 1.05;
- off.x = x;
-
- // skip a space if it's there since we just newline'd
+ if(i && ((i / 110.0) == (i / 110))){
+ yo-=fontSize*1.05;
+ xo=x;
if(s[i] == ' ')
i++;
}
-
- // handle newlines
if(s[i] == '\n'){
- off.y -= fontSize * 1.05;
- off.x = x;
-
- // (TODO) handle carriage returns and tabs
+ yo-=fontSize*1.05;
+ xo=x;
}else if(s[i] == '\r' || s[i] == '\t'){
-
- // handle spaces
- }else if(s[i]==' '){
- off.x += fontSize / 2;
-
- // handle backspaces
- }else if(s[i]=='\b'){
- off.x -= add.x;
-
- // handle everything else
+ /*if(s[i] == '\n'){
+ yo-=fontSize*1.05;
+ xo=x;
+ */}else if(s[i]==' '){ // Handle spaces
+ xo+=fontSize/2;
+ }else if(s[i]=='\b'){ // Handle backspaces?
+ xo-=add.x;
}else{
- add = putChar(off.x, off.y, s[i]);
- off.x += add.x;
- off.y += add.y;
+ add=putChar(floor(xo),floor(yo),s[i]);
+ xo+=add.x;
+ yo+=add.y;
}
-
}while(s[++i]);
- // return string width
- return off.x;
+ return xo; // i.e. the string width
}
- /**
- * Print a string center-aligned on the specified coordinate.
- */
-
float putStringCentered(const float x,const float y,const char *s){
unsigned int i = 0;
float width = 0;
- /*
- * Calculate the string's width by cycling through each character.
- */
-
do{
- // handle newlines
- if(s[i]=='\n'){
-
- // handle spaces
- }else if(s[i]==' '){
- width += fontSize / 2;
-
- // handle backspaces
- }else if(s[i]=='\b'){
-
- // handle everything else
- }else
- width += ftmapptr[i].wh.x + fontSize * .1;
-
+ if(s[i]=='\n'){ // Handle newlines
+ // TODO
+ }else if(s[i]==' '){ // Handle spaces
+ width+=fontSize/2;
+ }else if(s[i]=='\b'){ // Handle backspaces?
+ // Why?
+ // Cuz
+ }else{
+ width+=ftexwh[i].x+fontSize*.1;
+ }
}while(s[++i]);
-
- // print the string
- return putString(floor(x - width / 2), y, s);
+
+ putString(floor(x-width/2),y,s);
+ return width;
}
- /**
- * Draw a string in a typewriter-esque fashion.
- *
- * This function is expected to be called as it is rendered, slowly allowing
- * more characters to be drawn as it is looped on. Only one call to this
- * function can be handled at a time.
- */
+ /*
+ * Draw a string in a typewriter-esque fashion. Each letter is rendered as calls are made
+ * to this function. Passing a different string to the function will reset the counters.
+ */
- static char *typeOutStr = NULL;
+ static char *ret = NULL;
char *typeOut(char *str){
- static unsigned int sinc=0, // Acts as a delayer for the space between each character.
+ static unsigned int sinc, // Acts as a delayer for the space between each character.
linc=0, // Contains the number of letters that should be drawn.
size=0; // Contains the full size of the current string.
-
- // allocate memory for the string if necessary
- if(!typeOutStr){
- typeOutStr = new char[512];
- memset(typeOutStr, 0, 512 * sizeof(char));
+ //static char *ret = NULL;
+
+ /*
+ * Create a well-sized buffer if we haven't yet.
+ */
+
+ if(!ret){
+ ret = new char[512]; //(char *)calloc(512,sizeof(char));
+ memset(ret,0,512*sizeof(char));
}
/*
* Reset values if a new string is being passed.
- */
+ */
- if(strncmp(typeOutStr, str, linc - 1)){
- memset(typeOutStr, 0, 512); // Zero the buffer
- size = strlen(str); // Set the new target string size
- linc = 0; // Reset the incrementers
- sinc = 1; //
+ if(strncmp(ret,str,linc-1)){
+ memset(ret,0,512); // Zero the buffer
+ size=strlen(str); // Set the new target string size
+ linc=0; // Reset the incrementers
+ sinc=1;
typeOutDone = false;
}
/*
* Draw the next letter if necessary.
- */
+ */
if(typeOutDone)
return str;
- else if(++sinc == 2){
- sinc = 0;
+ else if(++sinc==2){
+ sinc=0;
- // add next character to output string
- strncpy(typeOutStr + linc,str + linc, 1);
+ strncpy(ret+linc,str+linc,1); // Get next character
- if(linc < size)
+ if(linc<size)
linc++;
else
typeOutDone = true;
}
-
- // return the string
- return typeOutStr;
+
+ return ret; // The buffered string.
}
- /**
- * Draw a formatted string to the specified coordinates.
- */
+ /*
+ * Draw a formatted string to the specified coordinates.
+ */
float putText(const float x,const float y,const char *str,...){
va_list args;
- std::unique_ptr<char[]> buf (new char[512]);
+ char *buf;
+ float width;
- // create the formatted string
- va_start(args, str);
- vsnprintf(buf.get(), 512, str, args);
+ /*
+ * Create a wimpy buffer.
+ */
+
+ buf = new char[512]; //(char *)calloc(128,sizeof(char));
+ memset(buf,0,512*sizeof(char));
+
+ /*
+ * Handle the formatted string, printing it to the buffer.
+ */
+
+ va_start(args,str);
+ vsnprintf(buf,512,str,args);
va_end(args);
- return putString(x, y, buf.get());
+ /*
+ * Draw the string, free resources, return the width of the string.
+ */
+
+ width=putString(x,y,buf);
+ delete[] buf; //free(buf);
+
+ return width;
}
-
- /**
- * Prints a character dialog box.
- *
- * This function sets up the variables necessary to draw a dialog box. If
- * `opt` contains a valid string, options will be printed with the dialog
- * box. If the box is passive, the player will be allowed to move while it
- * is being displayed.
- */
-
void dialogBox(const char *name,const char *opt,bool passive,const char *text,...){
textWrapLimit = 110;
va_list dialogArgs;
- size_t len;
+ unsigned int len;
+ char *sopt,*soptbuf;
dialogPassive = passive;
- // clear the buffer
- memset(dialogBoxText, '\0', 512);
+ /*
+ * Set up the text buffer.
+ */
- // create the string
- strcpy(dialogBoxText, name);
- strcat(dialogBoxText, ": ");
+ memset(dialogBoxText,0,512);
+
+ /*
+ * Get the text ready for rendering.
+ */
+
+ len=strlen(name);
+ strcpy(dialogBoxText ,name);
+ strcpy(dialogBoxText+len,": ");
+ len+=2;
- len=strlen(dialogBoxText);
va_start(dialogArgs,text);
- vsnprintf(dialogBoxText + len, 512 - len, text, dialogArgs);
+ vsnprintf(dialogBoxText+len,512-len,text,dialogArgs);
va_end(dialogArgs);
- // free old option text
+ /*
+ * Set up option text.
+ */
+
while(dialogOptCount){
if(dialogOptText[dialogOptCount]){
- delete[] dialogOptText[dialogOptCount];
+ delete[] dialogOptText[dialogOptCount]; //free(dialogOptText[dialogOptCount]);
dialogOptText[dialogOptCount] = NULL;
}
-
dialogOptCount--;
};
+ dialogOptCount = 0;
dialogOptChosen = 0;
- memset(&dialogOptLoc, 0, sizeof(float) * 12);
- //char *sopt = (char*)malloc(255);
- //dialogOptCount = 4;
+ memset(&dialogOptLoc,0,sizeof(float)*12);
- // handle options if desired
- if(opt){
- //std::vector<char*> soptbuf (new char[strlen(opt) + 1]);
- //std::unique_ptr<char[]> soptbuf (new char[strlen(opt) + 1]);
- char soptbuf[255];
- strcpy(soptbuf, opt);
- char *sopt = strtok(soptbuf, ":");
-
- // cycle through options
- while(sopt){
- printf("%s",sopt);
- strcpy( (dialogOptText[dialogOptCount++] = new char[strlen(sopt) + 1]), sopt);
- sopt = strtok(NULL,":");
+ if(opt != NULL){
+
+ soptbuf = new char[strlen(opt)+1];
+ strcpy(soptbuf,opt);
+
+ sopt=strtok(soptbuf,":");
+ while(sopt != NULL){
+ dialogOptText[dialogOptCount] = new char[strlen(sopt)+1]; //(char *)malloc(strlen(sopt));
+ strcpy(dialogOptText[dialogOptCount++],sopt);
+ sopt=strtok(NULL,":");
}
+
+ delete[] soptbuf;
+
}
- // allow box to be displayed
+ /*
+ * Tell draw() that the box is ready.
+ */
+
dialogBoxExists = true;
dialogImportant = false;
- // kill the string created by typeOut if it contains something
- if(typeOutStr)
- *typeOutStr = '\0';
+ if(ret)
+ ret[0] = '\0';
}
void merchantBox(const char *name,std::vector<BuySell> *bsinv,const char *opt,bool passive,const char *text,...){
@@ -666,8 +577,8 @@ namespace ui {
textWrapLimit = 50;
// kill the string created by typeOut if it contains something
- if(typeOutStr)
- *typeOutStr = '\0';
+ if(ret)
+ *ret = '\0';
}
void merchantBox(){
@@ -684,92 +595,73 @@ namespace ui {
mainLoop();
}while(ui::dialogBoxExists);
}
-
- /**
- * Wait for the screen to be fully covered through toggle___().
- */
-
void waitForCover(void){
do{
mainLoop();
}while(fadeIntensity < 255);
fadeIntensity = 255;
}
-
- /**
- * Prepare formatted 'important' string for drawing.
- *
- * "Important" text will display in a bigger font size at the center of the
- * screen. Usually accompanied by a cover from toggle___() and limits on
- * player controls.
- */
-
+ void waitForNothing(unsigned int ms){
+ unsigned int target = millis() + ms;
+ do{
+ mainLoop();
+ }while(millis() < target);
+ }
void importantText(const char *text,...){
va_list textArgs;
- // clear dialog buffer (we share the same)
- memset(dialogBoxText, '\0', 512);
+ //if(!player->ground)return;
+
+ memset(dialogBoxText,0,512);
- // format the string
va_start(textArgs,text);
- vsnprintf(dialogBoxText, 512, text, textArgs);
+ vsnprintf(dialogBoxText,512,text,textArgs);
va_end(textArgs);
- // set draw flags
dialogBoxExists = true;
dialogImportant = true;
+ //toggleBlack();
}
-
- /**
- * Draw a passive 'important' text for a certain duration.
- */
-
void passiveImportantText(int duration, const char *text,...){
va_list textArgs;
- // clear buffer
- memset(dialogBoxText, '\0', 512);
+ //if(!player->ground)return;
+
+ memset(dialogBoxText,0,512);
- // format the string
va_start(textArgs,text);
- vsnprintf(dialogBoxText, 512, text, textArgs);
+ vsnprintf(dialogBoxText,512,text,textArgs);
va_end(textArgs);
- // set draw flags
dialogBoxExists = true;
dialogImportant = true;
dialogPassive = true;
dialogPassiveTime = duration;
}
- /**
- * Draws all UI-related elements to the screen.
- */
void draw(void){
unsigned char i;
float x,y,tmp;
char *rtext;
- // handle dialog box / important text
if(dialogBoxExists){
- rtext = typeOut(dialogBoxText);
+ rtext=typeOut(dialogBoxText);
if(dialogImportant){
- setFontColor(255, 255, 255);
-
- // handle timeout
- if(dialogPassive && (dialogPassiveTime -= deltaTime) <= 0){
- dialogPassive = false;
- dialogImportant = false;
- dialogBoxExists = false;
+ setFontColor(255,255,255);
+ if(dialogPassive){
+ dialogPassiveTime -= deltaTime;
+ if(dialogPassiveTime < 0){
+ dialogPassive = false;
+ dialogImportant = false;
+ dialogBoxExists = false;
+ }
}
-
- // draw text
if(fadeIntensity == 255 || dialogPassive){
setFontSize(24);
- putStringCentered(offset.x, offset.y, rtext);
+ putStringCentered(offset.x,offset.y,rtext);
setFontSize(16);
}
}else if(dialogMerchant){
@@ -849,113 +741,91 @@ namespace ui {
// draw white border
glColor3ub(255, 255, 255);
+
glBegin(GL_LINE_STRIP);
- glVertex2f(x - 1 , y + 1 );
- glVertex2f(x + 1 + SCREEN_WIDTH - HLINE * 16, y + 1 );
- glVertex2f(x + 1 + SCREEN_WIDTH - HLINE * 16, y - 1 - SCREEN_HEIGHT / 4 );
- glVertex2f(x - 1 , y - 1 - SCREEN_HEIGHT / 4 );
- glVertex2f(x , y + 1 );
+ glVertex2f(x-1 ,y+1);
+ glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y+1);
+ glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y-1-SCREEN_HEIGHT/4);
+ glVertex2f(x-1 ,y-1-SCREEN_HEIGHT/4);
+ glVertex2f(x ,y+1);
glEnd();
- // draw black box
- glColor3ub(0, 0, 0);
- glRectf(x, y, x + SCREEN_WIDTH - HLINE * 16, y - SCREEN_HEIGHT / 4);
+ glColor3ub(0,0,0);
+ glRectf(x,y,x+SCREEN_WIDTH-HLINE*16,y-SCREEN_HEIGHT/4);
- // draw typeOut'd text
- putString(x + HLINE, y - fontSize - HLINE, (rtext = typeOut(dialogBoxText)));
+ rtext=typeOut(dialogBoxText);
- // draw / handle dialog options if they exist
- for(i = 0; i < dialogOptCount; i++){
- setFontColor(255, 255, 255);
-
- // draw option
- tmp = putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]);
-
- // get coordinate information on option
+ putString(x+HLINE,y-fontSize-HLINE,rtext);
+
+ for(i=0;i<dialogOptCount;i++){
+ setFontColor(255,255,255);
+ tmp = putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]);
dialogOptLoc[i][2] = offset.x + tmp;
dialogOptLoc[i][0] = offset.x - tmp;
dialogOptLoc[i][1] = y - SCREEN_HEIGHT / 4 + (fontSize + HLINE) * (i + 1);
-
- // make text yellow if the mouse hovers over the text
- if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] &&
- mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){
- setFontColor(255, 255, 0);
- putStringCentered(offset.x, dialogOptLoc[i][1], dialogOptText[i]);
+ if(mouse.x > dialogOptLoc[i][0] &&
+ mouse.x < dialogOptLoc[i][2] &&
+ mouse.y > dialogOptLoc[i][1] &&
+ mouse.y < dialogOptLoc[i][1] + 16 ){ // fontSize
+ setFontColor(255,255,0);
+ putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]);
}
}
-
- setFontColor(255, 255, 255);
+ setFontColor(255,255,255);
}
- // make click for each character update
- if(strcmp(rtext, dialogBoxText))
- Mix_PlayChannel(1, dialogClick, 0);
-
- }
-
- // draw information stuffs
- if(!fadeIntensity){
+ if(strcmp(rtext,dialogBoxText)){
+ Mix_PlayChannel(1,dialogClick,0);
+ }
+ }if(!fadeIntensity){
vec2 hub = {
- (offset.x + SCREEN_WIDTH / 2) - fontSize * 10,
- (offset.y + SCREEN_HEIGHT / 2) - fontSize
+ (SCREEN_WIDTH/2+offset.x)-fontSize*10,
+ (offset.y+SCREEN_HEIGHT/2)-fontSize
};
- // health text
- putText(hub.x,
- hub.y,
- "Health: %.0f/%.0f",
- player->health > 0 ? player->health : 0,
- player->maxHealth
- );
-
- // health bar
+ putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0,
+ (unsigned)player->maxHealth
+ );
if(player->alive){
- hub.y -= fontSize * 1.15;
-
- glColor3ub(150, 0, 0);
+ glColor3ub(150,0,0);
+ hub.y-=fontSize*1.15;
glRectf(hub.x,
hub.y,
- hub.x + 150,
- hub.y + 12
- );
-
+ hub.x+150,
+ hub.y+12);
glColor3ub(255,0,0);
glRectf(hub.x,
hub.y,
- hub.x + (player->health / player->maxHealth * 150),
- hub.y + 12
- );
+ hub.x+(player->health/player->maxHealth * 150),
+ hub.y+12);
}
- // inventory
+ /*
+ * Lists all of the quests the player is currently taking.
+ */
+
if(player->inv->invOpen){
hub.y = player->loc.y + fontSize * 8;
- hub.x = player->loc.x;
+ hub.x = player->loc.x;// + player->width / 2;
- putStringCentered(hub.x, hub.y, "Current Quests:");
+ putStringCentered(hub.x,hub.y,"Current Quests:");
- for(auto &q : player->qh.current)
- putStringCentered(hub.x, (hub.y -= fontSize * 1.15), q.title.c_str());
+ for(auto &c : player->qh.current){
+ hub.y -= fontSize * 1.15;
+ putStringCentered(hub.x,hub.y,c.title.c_str());
+ }
}
}
}
- /**
- * Safely exits the game.
- */
-
void quitGame(){
- // clean menu stuff
+ dialogBoxExists = false;
currentMenu = NULL;
delete[] currentMenu;
-
- // save options
+ gameRunning = false;
updateConfig();
saveConfig();
-
- // tell main loop to exit
- gameRunning = false;
}
menuItem createButton(vec2 l, dim2 d, Color c, const char* t, menuFunc f){
@@ -1282,32 +1152,24 @@ namespace ui {
fclose(bmp);
}
- /**
- * Handles dialog box closing, option selecting and stuff.
- */
-
void dialogAdvance(void){
unsigned char i;
-
- // if typeOut hasn't finished, tell it to then try again
if(!typeOutDone){
typeOutDone = true;
return;
}
- // check for selected option
- for(i = 0; i < dialogOptCount; i++){
- if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] &&
- mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){
+ for(i=0;i<dialogOptCount;i++){
+ if(mouse.x > dialogOptLoc[i][0] &&
+ mouse.x < dialogOptLoc[i][2] &&
+ mouse.y > dialogOptLoc[i][1] &&
+ mouse.y < dialogOptLoc[i][1] + 16 ){ // fontSize
dialogOptChosen = i + 1;
- break;
+ goto DONE;
}
}
+DONE:
- if(dialogMerchant){
- for(i = 0; i < 2; i++){
- }
- }
// handle important text
if(dialogImportant){
@@ -1326,42 +1188,48 @@ namespace ui {
vec2 oldpos,tmppos;
SDL_Event e;
- mouse.x=premouse.x+offset.x-(SCREEN_WIDTH/2);
- mouse.y=(offset.y+SCREEN_HEIGHT/2)-premouse.y;
+ // update mouse coords
+ mouse.x = premouse.x + offset.x - ( SCREEN_WIDTH / 2 );
+ mouse.y = ( offset.y + SCREEN_HEIGHT / 2 ) - premouse.y;
while(SDL_PollEvent(&e)){
switch(e.type){
+
+ // escape - quit game
case SDL_QUIT:
gameRunning=false;
break;
+
+ // mouse movement - update mouse vector
case SDL_MOUSEMOTION:
premouse.x=e.motion.x;
premouse.y=e.motion.y;
break;
+
+ // mouse clicks
case SDL_MOUSEBUTTONDOWN:
- if((e.button.button & SDL_BUTTON_RIGHT) && dialogBoxExists)
+ // right click advances dialog
+ if ( ( e.button.button & SDL_BUTTON_RIGHT ) && dialogBoxExists )
dialogAdvance();
- if((e.button.button & SDL_BUTTON_LEFT) && !dialogBoxExists)
+ // left click uses item
+ if ( ( e.button.button & SDL_BUTTON_LEFT ) && !dialogBoxExists )
player->inv->usingi = true;
break;
- /*
- KEYDOWN
- */
+
+ // key presses
case SDL_KEYDOWN:
- /*if(SDL_KEY == SDLK_ESCAPE){
- //gameRunning = false;
- pMenu = true;
- return;
- }else */if(SDL_KEY == SDLK_SPACE){
- /*if(dialogBoxExists)
- dialogAdvance();
- else */if(player->ground){
- player->vel.y=.4;
- player->loc.y+=HLINE*2;
- player->ground=false;
+
+ // space - make player jump
+ if ( SDL_KEY == SDLK_SPACE ) {
+ if ( player->ground ) {
+ player->loc.y += HLINE * 2;
+ player->vel.y = .4;
+ player->ground = false;
}
break;
- }else if(!dialogBoxExists || dialogPassive){
+
+ // only let other keys be handled if dialog allows it
+ } else if ( !dialogBoxExists || dialogPassive ) {
tmp = currentWorld;
switch(SDL_KEY){
case SDLK_a:
@@ -1459,6 +1327,7 @@ namespace ui {
if(debug)posFlag ^= true;
break;
case SDLK_e:
+ edown=true;
if(!heyOhLetsGo){
heyOhLetsGo = loops;
player->inv->mouseSel = false;
@@ -1506,6 +1375,7 @@ namespace ui {
player->speed = 1;
break;
case SDLK_e:
+ edown=false;
if(player->inv->invHover){
player->inv->invHover = false;
}else{
@@ -1578,46 +1448,25 @@ namespace ui {
}
}
- /**
- * Toggle a slow fade to/from black.
- */
-
void toggleBlack(void){
fadeEnable ^= true;
fadeWhite = false;
fadeFast = false;
}
-
- /**
- * Toggle a fast fade to/from black.
- */
-
void toggleBlackFast(void){
fadeEnable ^= true;
fadeWhite = false;
fadeFast = true;
}
-
- /**
- * Toggle a slow fade to/from white.
- */
-
void toggleWhite(void){
fadeEnable ^= true;
fadeWhite = true;
fadeFast = false;
}
-
- /**
- * Toggle a fast fade to/from white. This should only be used for battle
- * initiations, so the 'battle start' sound is played as well.
- */
-
void toggleWhiteFast(void){
fadeEnable ^= true;
fadeWhite = true;
fadeFast = true;
-
- Mix_PlayChannel(1, battleStart, 0);
+ Mix_PlayChannel(1,battleStart,0);
}
}
diff --git a/src/world.cpp b/src/world.cpp
index 9e891fb..80ddc5a 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -1,123 +1,154 @@
#include <world.h>
#include <ui.h>
-#define getWidth(w) ((w->lineCount-GEN_INC)*HLINE) // Calculates the width of world 'w'
+/**
+ * Defines how many HLINEs tall a blade of grass can be.
+ */
-#define GEN_INIT 60
+#define GRASS_HEIGHT 4
-#define GRASS_HEIGHT 4 // Defines how long the grass layer of a line should be in multiples of HLINE.
+/**
+ * Defines the height of the floor in an IndoorWorld.
+ */
+#define INDOOR_FLOOR_HEIGHT 100
-#define DRAW_Y_OFFSET 50 // Defines how many pixels each layer should be offset from each other on the y axis when drawn.
-#define DRAW_SHADE 30 // Defines a shade increment for draw()
-
-#define INDOOR_FLOOR_HEIGHT 100 // Defines how high the base floor of an IndoorWorld should be
-
-bool worldInside = false; // True if player is inside a structure
+/**
+ * Contains the current weather, used in many other places/files.
+ */
WEATHER weather = SUNNY;
-
const std::string bgPaths[2][9]={
- {"bg.png", // Daytime background
- "bgn.png", // Nighttime background
- "bgFarMountain.png", // Furthest layer
- "forestTileFar.png", // Furthest away Tree Layer
- "forestTileBack.png", // Closer layer
- "forestTileMid.png", // Near layer
- "forestTileFront.png", // Closest layer
- "dirt.png", // Dirt
- "grass.png"}, // Grass
- {"bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png",
- "bgWoodTile.png"}
+ {"bg.png", // Daytime background
+ "bgn.png", // Nighttime background
+ "bgFarMountain.png", // Furthest layer
+ "forestTileFar.png", // Furthest away Tree Layer
+ "forestTileBack.png", // Closer layer
+ "forestTileMid.png", // Near layer
+ "forestTileFront.png", // Closest layer
+ "dirt.png", // Dirt
+ "grass.png"}, // Grass
+ {"bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png",
+ "bgWoodTile.png"}
};
-const std::string buildPaths[] = { "townhall.png",
- "house1.png",
- "house2.png",
- "house1.png",
- "house1.png",
- "fountain1.png",
- "lampPost1.png",
- "brazzier.png"};
+const std::string buildPaths[] = {
+ "townhall.png",
+ "house1.png",
+ "house2.png",
+ "house1.png",
+ "house1.png",
+ "fountain1.png",
+ "lampPost1.png",
+ "brazzier.png"
+};
+
+/**
+ * Constants used for layer drawing in World::draw(), releated to transparency.
+ */
const float bgDraw[4][3]={
- {100,240,.6 },
- {150,250,.4 },
- {200,255,.25},
- {255,255,.1}
+ { 100, 240, 0.6 },
+ { 150, 250, 0.4 },
+ { 200, 255, 0.25 },
+ { 255, 255, 0.1 }
};
-float worldGetYBase(World *w){
-// World *tmp = w;
- float base = GEN_MIN;
-/* while(tmp->infront){
- tmp = tmp->infront;
- base -= DRAW_Y_OFFSET;
- }*/
- if(!w)return 0;
- return base;
-}
-
-void World::setBackground(WORLD_BG_TYPE bgt){
- bgType = bgt;
- switch(bgt){
+/**
+ * Sets the desired theme for the world's background.
+ *
+ * The images chosen for the background layers are selected depending on the
+ * world's background type.
+ */
+
+void World::
+setBackground( WORLD_BG_TYPE bgt )
+{
+ // load textures with a limit check
+ switch ( (bgType = bgt) ) {
case BG_FOREST:
- bgTex = new Texturec(bgFiles);
+ bgTex = new Texturec( bgFiles );
break;
+
case BG_WOODHOUSE:
- bgTex = new Texturec(bgFilesIndoors);
+ bgTex = new Texturec( bgFilesIndoors );
break;
+
+ default:
+ UserError( "Invalid world background type" );
+ break;
}
}
-void World::setStyle(const char* pre){
+/**
+ * Sets the world's style.
+ *
+ * The world's style will determine what sprites are used for things like\
+ * generic structures.
+ */
+
+void World::
+setStyle( const char *pre )
+{
+ unsigned int i;
+
+ // get folder prefix
std::string prefix = pre ? pre : "assets/style/classic/";
- for(uint i = 0; i < arrAmt(buildPaths);i++){
- sTexLoc.push_back(prefix);
- sTexLoc.back() += buildPaths[i];
- //std::cout << sTexLoc.back() << std::endl;
- }
+
+ for ( i = 0; i < arrAmt(buildPaths); i++ )
+ sTexLoc.push_back( prefix + buildPaths[i] );
+
prefix += "bg/";
- for(uint i = 0; i < arrAmt(bgPaths[0]);i++){
- bgFiles.push_back(prefix);
- bgFiles.back() += bgPaths[0][i];
- //std::cout << bgFiles.back() << std::endl;
- }
- for(uint i = 0; i < arrAmt(bgPaths[1]);i++){
- bgFilesIndoors.push_back(prefix);
- bgFilesIndoors.back() += bgPaths[1][i];
- //std::cout << bgFilesIndoors.back() << std::endl;
- }
+
+ for ( i = 0; i < arrAmt(bgPaths[0]); i++ )
+ bgFiles.push_back( prefix + bgPaths[0][i] );
+
+ for ( i = 0; i < arrAmt(bgPaths[1]); i++ )
+ bgFilesIndoors.push_back( prefix + bgPaths[1][i] );
}
-World::World(void){
-
+/**
+ * Creates a world object.
+ *
+ * Note that all this does is nullify pointers, to prevent as much disaster as
+ * possible. Functions like setBGM(), setStyle() and generate() should be called
+ * before the World is actually put into use.
+ */
+
+World::
+World( void )
+{
+ // nullify strings
bgm = NULL;
bgmObj = NULL;
-
- toLeft =
- toRight = NULL;
-
- /*
- * Allocate and clear an array for star coordinates.
- */
-
- star = new vec2[100];
- memset(star,0,100 * sizeof(vec2));
+
+ toLeft = NULL;
+ toRight = NULL;
}
-void World::deleteEntities(void){
- while(!mob.empty()){
+/**
+ * The entity vector destroyer.
+ *
+ * This function will free all memory used by all entities, and then empty the
+ * vectors they were stored in.
+ */
+
+void World::
+deleteEntities( void )
+{
+ // free mobs
+ while ( !mob.empty() ) {
delete mob.back();
mob.pop_back();
}
+
while(!merchant.empty()){
merchant.pop_back();
}
@@ -125,41 +156,60 @@ void World::deleteEntities(void){
delete npc.back();
npc.pop_back();
}
- while(!build.empty()){
+
+ // free structures
+ while ( !build.empty() ) {
delete build.back();
build.pop_back();
}
- while(!object.empty()){
+
+ // free objects
+ while ( !object.empty() ) {
delete object.back();
object.pop_back();
}
- while(!entity.empty()){
+
+ // clear entity array
+ while ( !entity.empty() ) {
entity.pop_back();
}
- while(!particles.empty()){
+
+ // free particles
+ while ( !particles.empty() ) {
delete particles.back();
particles.pop_back();
}
- while(!light.empty()){
+
+ // clear light array
+ while ( !light.empty() )
light.pop_back();
- }
- while(!village.empty()){
+
+ // free villages
+ while ( !village.empty() ) {
delete village.back();
village.pop_back();
}
}
-World::~World(void){
- /*if(behind != NULL)
- delete behind;*/
-
+/**
+ * The world destructor.
+ *
+ * This will free objects used by the world itself, then free the vectors of
+ * entity-related objects.
+ */
+
+World::
+~World( void )
+{
+ // sdl2_mixer's object
if(bgmObj)
Mix_FreeMusic(bgmObj);
+
+ // bgm path
if(bgm)
delete[] bgm;
+
delete bgTex;
- delete[] star;
- delete[] line;
delete[] toLeft;
delete[] toRight;
@@ -167,179 +217,101 @@ World::~World(void){
deleteEntities();
}
-void World::generate(unsigned int width){ // Generates the world and sets all variables contained in the World class.
- unsigned int i;
- float inc;
-
- /*
- * Calculate the world's real width. The current form of generation fails to generate
- * the last GEN_INC lines, so we offset those making the real real width what was passed
- * to this function.
- *
- * Abort if the width is invalid.
- *
- */
-
- if(width <= 0)
- abort();
+/**
+ * Generates a world of the specified width.
+ *
+ * This will mainly populate the WorldData array, mostly preparing the World
+ * object for usage.
+ */
+
+void World::
+generate( unsigned int width )
+{
+ // iterator for `for` loops
+ std::vector<WorldData>::iterator wditer;
+
+ // see below for description
+ float geninc = 0;
+
+ // check for valid width
+ if ( (int)width <= 0 )
+ UserError("Invalid world dimensions");
+
+ // allocate space for world
+ worldData = std::vector<WorldData> (width + GROUND_HILLINESS, (WorldData) { false, {0,0}, 0, 0 });
+ lineCount = worldData.size();
+
+ // prepare for generation
+ worldData.front().groundHeight = GROUND_HEIGHT_INITIAL;
+ wditer = worldData.begin();
+
+ // give every GROUND_HILLINESSth entry a groundHeight value
+ for(unsigned int i = GROUND_HILLINESS; i < worldData.size(); i += GROUND_HILLINESS, wditer += GROUND_HILLINESS)
+ worldData[i].groundHeight = (*wditer).groundHeight + (randGet() % 8 - 4);
+
+ // create slopes from the points that were just defined, populate the rest of the WorldData structure
+
+ for(wditer = worldData.begin(); wditer != worldData.end(); wditer++){
+ if ((*wditer).groundHeight)
+ // wditer + GROUND_HILLINESS can go out of bounds (invalid read)
+ geninc = ( (*(wditer + GROUND_HILLINESS)).groundHeight - (*wditer).groundHeight ) / (float)GROUND_HILLINESS;
+ else
+ (*wditer).groundHeight = (*(wditer - 1)).groundHeight + geninc;
+
+ (*wditer).groundColor = randGet() % 32 / 8;
+ (*wditer).grassUnpressed = true;
+ (*wditer).grassHeight[0] = (randGet() % 16) / 3 + 2;
+ (*wditer).grassHeight[1] = (randGet() % 16) / 3 + 2;
+
+ // bound checks
+ if ( (*wditer).groundHeight < GROUND_HEIGHT_MINIMUM )
+ (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
+ else if ( (*wditer).groundHeight > GROUND_HEIGHT_MAXIMUM )
+ (*wditer).groundHeight = GROUND_HEIGHT_MAXIMUM;
- lineCount = (width + GEN_INC) / HLINE;
-
- /*
- * Allocate enough memory for the world to be stored.
- */
-
- line = new struct line_t[lineCount];
- memset(line,0,lineCount * sizeof(struct line_t));
-
- /*
- * Set an initial y to base generation off of, as generation references previous lines.
- */
-
- line[0].y = GEN_INIT;
-
- /*
- * Populate every GEN_INCth line structure. The remaining lines will be based off of these.
- */
-
- for(i = GEN_INC;i < lineCount;i += GEN_INC){
-
- /*
- * Generate a y value, ensuring it stays within a reasonable range.
- */
-
- line[i].y = rand() % 8 - 4 + line[i - GEN_INC].y; // Add +/- 4 to the previous line
-
- if(line[i].y < GEN_MIN)line[i].y = GEN_MIN; // Minimum bound
- else if(line[i].y > GEN_MAX)line[i].y = GEN_MAX; // Maximum bound
-
- }
-
- /*
- * Generate values for the remaining lines here.
- */
-
- for(i = 0;i < lineCount - GEN_INC;i++){
-
- /*
- * Every GEN_INCth line calculate the slope between the current line and the one
- * GEN_INC lines before it. This value is then divided into an increment that is
- * added to lines between these two points resulting in a smooth slope.
- *
- */
-
- if(!(i % GEN_INC))
-
- inc = (line[i + GEN_INC].y - line[i].y) / (float)GEN_INC;
-
- /*
- * Add the increment to create the smooth slope.
- */
-
- else line[i].y = line[i - 1].y + inc;
-
- /*
- * Generate a color value for the line. This will be referenced in World->draw(),
- * by setting an RGB value of color (red), color - 50 (green), color - 100 (blue).
- */
-
- line[i].color = rand() % 32 / 8; // 100 to 120
+ if( (*wditer).groundHeight <= 0 )
+ (*wditer).groundHeight = GROUND_HEIGHT_MINIMUM;
- /*
- * Each line has two 'blades' of grass, here we generate random heights for them.
- */
-
- line[i].gh[0] = (getRand() % 16) / 3.5 + 2; // Not sure what the range resolves to here...
- line[i].gh[1] = (getRand() % 16) / 3.5 + 2; //
-
- line[i].gs = true; // Show the blades of grass (modified by the player)
-
- }
-
- /*
- * Calculate the x coordinate to start drawing this world from so that it is centered at (0,0).
- */
-
- x_start = 0 - getWidth(this) / 2;
+ }
+
+ // define x-coordinate of world's leftmost 'line'
+ worldStart = (width - GROUND_HILLINESS) * HLINE / 2 * -1;
- /*
- * Assign coordinates for the stars, seen at nighttime.
- */
-
- for(i = 0;i < 100;i++){
- star[i].x = getRand() % getTheWidth() - getTheWidth() / 2;
- star[i].y = getRand() % SCREEN_HEIGHT + 100;
- }
+ // create empty star array, should be filled here as well...
+ star = std::vector<vec2> (100, (vec2) { 0, 0 } );
}
-void World::generateFunc(unsigned int width,float(*func)(float)){
- unsigned int i;
-
- /*
- * Check for a valid width.
- */
-
- if((lineCount = width) <= 0)
- abort();
-
- /*
- * Allocate memory for the line array.
- */
-
- line = new struct line_t[lineCount];
- memset(line,0,lineCount*sizeof(struct line_t));
-
- /*
- * Populate entries in the line array, using `func` to get y values.
- */
-
- for(i = 0;i < lineCount;i++){
- line[i].y = func(i);
-
- if(line[i].y < 0)line[i].y = 0; // Minimum bound
- if(line[i].y > 2000)line[i].y = 2000; // Maximum bound
-
- line[i].color = rand() % 20 + 100;
-
- line[i].gh[0] = (getRand() % 16) / 3.5 + 2;
- line[i].gh[1] = (getRand() % 16) / 3.5 + 2;
-
- line[i].gs = true;
- }
-
- x_start = 0 - getWidth(this) / 2;
-
- for(i = 0;i < 100;i++){
- star[i].x = getRand() % getTheWidth() - getTheWidth() / 2;
- star[i].y = getRand() % SCREEN_HEIGHT + 100;
- }
-}
+/**
+ * Updates all entity and player coordinates with their velocities.
+ *
+ * Also handles music fading, although that could probably be placed elsewhere.
+ */
-void World::update(Player *p,unsigned int delta){
-
- /*
- * Update the player's coordinates.
- */
-
+void World::
+update( Player *p, unsigned int delta )
+{
+ // update player coords
p->loc.y += p->vel.y * delta;
p->loc.x +=(p->vel.x * p->speed) * delta;
- /*
- * Update coordinates of all entities except for structures.
- */
-
- for(auto &e : entity){
+ // update entity coords
+ for ( auto &e : entity ) {
e->loc.y += e->vel.y * delta;
- if(e->type != STRUCTURET && e->canMove){
+ // dont let structures move?
+ if ( e->type != STRUCTURET && e->canMove ) {
e->loc.x += e->vel.x * delta;
- if(e->vel.x < 0)e->left = true;
- else if(e->vel.x > 0)e->left = false;
+ // update boolean directions
+ if ( e->vel.x < 0 )
+ e->left = true;
+ else if ( e->vel.x > 0 )
+ e->left = false;
}
}
- for(unsigned int i=0;i<particles.size();i++){
+ // iterate through particles
+ for(unsigned int i=0;i<particles.size();i++){
if(particles[i]->kill(deltaTime)){
delete particles[i];
particles.erase(particles.begin()+i);
@@ -360,441 +332,362 @@ void World::update(Player *p,unsigned int delta){
}
}
- if(ui::dialogImportant){
+ // handle music fades
+ if ( ui::dialogImportant )
Mix_FadeOutMusic(2000);
- }else if(!Mix_PlayingMusic()){
+ else if( !Mix_PlayingMusic() )
Mix_FadeInMusic(bgmObj,-1,2000);
- }
}
-void World::setBGM(std::string path){
- bgm = new char[path.size() + 1];
- strcpy(bgm,path.c_str());
- bgmObj = Mix_LoadMUS(bgm);
+/**
+ * Set the world's BGM.
+ *
+ * This will load a sound file to be played while the player is in this world.
+ * If no file is found, no music should play.
+ */
+
+void World::
+setBGM( std::string path )
+{
+ bgmObj = Mix_LoadMUS( strcpy( (bgm = new char[ path.size() + 1 ]), path.c_str()) );
}
-void World::bgmPlay(World *prev){
- if(prev){
- if(bgm != prev->bgm){
- Mix_FadeOutMusic(800);
- //Mix_VolumeMusic(50);
- Mix_PlayMusic(bgmObj,-1); // Loop infinitely
+/**
+ * Toggle play/stop of the background music.
+ *
+ * If new music is to be played a crossfade will occur, otherwise... uhm.
+ */
+
+void World::
+bgmPlay( World *prev )
+{
+ if ( prev ) {
+ if ( bgm != prev->bgm ) {
+ // new world, new music
+ Mix_FadeOutMusic( 800 );
+ Mix_PlayMusic( bgmObj, -1 );
}
- }else{
- Mix_FadeOutMusic(800);
- //Mix_VolumeMusic(50);
- Mix_PlayMusic(bgmObj,-1); // Loop infinitely
+ } else {
+ // first call
+ Mix_FadeOutMusic( 800 );
+ Mix_PlayMusic( bgmObj, -1 );
}
}
-int worldShade = 0;
+/**
+ * Variables used by World::draw().
+ * @{
+ */
extern vec2 offset;
extern unsigned int tickCount;
-void World::draw(Player *p){
- static float yoff=DRAW_Y_OFFSET; // Initialize stuff
- static int shade,bgshade;
- static World *current=this;
- unsigned int i;
- int is,ie,v_offset,cx_start,width;
- struct line_t *cline;
- float base;
-
- bgshade = worldShade << 1; // *2
- base = worldGetYBase(this);
+int worldShade = 0;
+
+/**
+ * @}
+ */
+
+/**
+ * The world draw function.
+ *
+ * This function will draw the background layers, entities, and player to the
+ * screen.
+ */
+
+void World::
+draw( Player *p )
+{
+ // iterators
+ int i, iStart, iEnd;
+
+ // shade value for draws -- may be unnecessary
+ int shadeBackground = 0;
+
+ // player's offset in worldData[]
+ int pOffset;
+
+ // world width in pixels
+ int width = worldData.size() * HLINE;
/*
- * Draw the background images in the appropriate order.
- */
+ * Draw background images.
+ */
-//LLLOOP:
- /*if(current->infront){
- current=current->infront;
- goto LLLOOP;
- }*/
+ glEnable( GL_TEXTURE_2D );
- if(current->x_start < SCREEN_WIDTH * -.5 )
- cx_start = current->x_start * 1.5;
- else
- cx_start = (int)(SCREEN_WIDTH * -.5);
-
- width = (-cx_start) << 1;
+ // the sunny wallpaper is faded with the night depending on tickCount
- glEnable(GL_TEXTURE_2D);
-
- bgTex->bind(0);
- safeSetColorA(255,255,255,255 - worldShade * 4);
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i( cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,0);glVertex2i(-cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,1);glVertex2i(-cx_start,0);
- glTexCoord2i(0,1);glVertex2i( cx_start,0);
+ bgTex->bind( 0 );
+ safeSetColorA( 255, 255, 255, 255 - worldShade * 4 );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 0 ); glVertex2i( -worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 1 ); glVertex2i( -worldStart, 0 );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart, 0 );
glEnd();
bgTex->bindNext();
- safeSetColorA(255,255,255,worldShade * 4);
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i( cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,0);glVertex2i(-cx_start,SCREEN_HEIGHT);
- glTexCoord2i(1,1);glVertex2i(-cx_start,0);
- glTexCoord2i(0,1);glVertex2i( cx_start,0);
+ safeSetColorA( 255, 255, 255, worldShade * 4 );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 0 ); glVertex2i( -worldStart, SCREEN_HEIGHT );
+ glTexCoord2i( 1, 1 ); glVertex2i( -worldStart, 0 );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart, 0 );
glEnd();
- glDisable(GL_TEXTURE_2D);
-
- /*
- * Draws stars if it is an appropriate time of day for them.
- */
+
+ glDisable( GL_TEXTURE_2D );
+
+ // draw the stars if the time deems it appropriate
+
+ if (((( weather == DARK ) & ( tickCount % DAY_CYCLE )) < DAY_CYCLE / 2) ||
+ ((( weather == SUNNY ) & ( tickCount % DAY_CYCLE )) > DAY_CYCLE * .75) ){
- if((((weather==DARK )&(tickCount%DAY_CYCLE))<DAY_CYCLE/2) ||
- (((weather==SUNNY)&(tickCount%DAY_CYCLE))>DAY_CYCLE*.75) ){
-
- if(tickCount % DAY_CYCLE){ // The above if statement doesn't check for exact midnight.
+ if (tickCount % DAY_CYCLE) { // The above if statement doesn't check for exact midnight.
- safeSetColorA(255,255,255,bgshade + getRand() % 30 - 15);
- for(i = 0; i < 100; i++){
- glRectf(star[i].x+offset.x*.9,
+ safeSetColorA( 255, 255, 255, shadeBackground + getRand() % 30 - 15 );
+
+ for ( i = 0; i < 100; i++ ) {
+ glRectf(star[i].x + offset.x * .9,
star[i].y,
- star[i].x+offset.x*.9+HLINE,
- star[i].y+HLINE
+ star[i].x + offset.x * .9 + HLINE,
+ star[i].y + HLINE
);
}
-
}
}
-
- glEnable(GL_TEXTURE_2D);
-
- /*
- * Draw the mountains.
- */
- bgTex->bindNext();
- safeSetColorA(150-bgshade,150-bgshade,150-bgshade,220);
+ // draw remaining background items
- glBegin(GL_QUADS);
- for(int i = 0; i <= width/1920; i++){
- glTexCoord2i(0,1);glVertex2i(width/-2+(1920*i )+offset.x*.85,base);
- glTexCoord2i(1,1);glVertex2i(width/-2+(1920*(i+1))+offset.x*.85,base);
- glTexCoord2i(1,0);glVertex2i(width/-2+(1920*(i+1))+offset.x*.85,base+1080);
- glTexCoord2i(0,0);glVertex2i(width/-2+(1920*i )+offset.x*.85,base+1080);
+ glEnable( GL_TEXTURE_2D );
+
+ bgTex->bindNext();
+ safeSetColorA( 150 - shadeBackground, 150 - shadeBackground, 150 - shadeBackground, 220 );
+
+ glBegin( GL_QUADS );
+ for ( i = 0; i <= (int)(worldData.size() * HLINE / 1920); i++ ) {
+ glTexCoord2i( 0, 1 ); glVertex2i( width / 2 * -1 + (1920 * i ) + offset.x * .85, GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 1 ); glVertex2i( width / 2 * -1 + (1920 * (i + 1)) + offset.x * .85, GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 0 ); glVertex2i( width / 2 * -1 + (1920 * (i + 1)) + offset.x * .85, GROUND_HEIGHT_MINIMUM + 1080 );
+ glTexCoord2i( 0, 0 ); glVertex2i( width / 2 * -1 + (1920 * i ) + offset.x * .85, GROUND_HEIGHT_MINIMUM + 1080 );
}
glEnd();
- /*
- * Draw four layers of trees.
- */
-
- for(i = 0; i < 4; i++){
+ for ( i = 0; i < 4; i++ ) {
bgTex->bindNext();
- safeSetColorA(bgDraw[i][0]-bgshade,bgDraw[i][0]-bgshade,bgDraw[i][0]-bgshade,bgDraw[i][1]);
-
- glBegin(GL_QUADS);
- for(int j = cx_start; j <= -cx_start; j += 600){
- glTexCoord2i(0,1);glVertex2i( j +offset.x*bgDraw[i][2],base);
- glTexCoord2i(1,1);glVertex2i((j+600)+offset.x*bgDraw[i][2],base);
- glTexCoord2i(1,0);glVertex2i((j+600)+offset.x*bgDraw[i][2],base+400);
- glTexCoord2i(0,0);glVertex2i( j +offset.x*bgDraw[i][2],base+400);
+ safeSetColorA( bgDraw[i][0] - shadeBackground, bgDraw[i][0] - shadeBackground, bgDraw[i][0] - shadeBackground, bgDraw[i][1] );
+
+ glBegin( GL_QUADS );
+ for( int j = worldStart; j <= -worldStart; j += 600 ){
+ glTexCoord2i( 0, 1 ); glVertex2i( j + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 1 ); glVertex2i( (j + 600) + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM );
+ glTexCoord2i( 1, 0 ); glVertex2i( (j + 600) + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM + 400 );
+ glTexCoord2i( 0, 0 ); glVertex2i( j + offset.x * bgDraw[i][2], GROUND_HEIGHT_MINIMUM + 400 );
}
glEnd();
}
- glDisable(GL_TEXTURE_2D);
+ glDisable( GL_TEXTURE_2D );
- glColor3ub(0,0,0);
- glRectf(cx_start,GEN_MIN,-cx_start,0);
+ // draw black under backgrounds
- /*
- * 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.
- *
- */
+ glColor3ub( 0, 0, 0 );
+ glRectf( worldStart, GROUND_HEIGHT_MINIMUM, -worldStart, 0 );
- current=this;
- shade=worldShade;
+ pOffset = (offset.x + p->width / 2 - worldStart) / HLINE;
-//LOOP1:
+ /*
+ * Prepare for world ground drawing.
+ */
+
+ // only draw world within player vision
+
+ if ((iStart = pOffset - (SCREEN_WIDTH / 2 / HLINE) - GROUND_HILLINESS) < 0)
+ iStart = 0;
- //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;
- }*/
+ if ((iEnd = pOffset + (SCREEN_WIDTH / 2 / HLINE) + GROUND_HILLINESS + HLINE) > (int)worldData.size())
+ iEnd = worldData.size();
+ else if (iEnd < GROUND_HILLINESS)
+ iEnd = GROUND_HILLINESS;
+
+ // draw particles and buildings
- /*
- * 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.
- */
+ for ( auto &part : particles ) {
+ if ( part->behind )
+ part->draw();
+ }
-//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.
- */
+ for ( auto &b : build )
+ b->draw();
- v_offset=(offset.x + p->width / 2 - current->x_start) / HLINE;
+ // draw light elements?
- // is -> i start
+ glEnable( GL_TEXTURE_2D );
+
+ glActiveTexture( GL_TEXTURE0 );
+ bgTex->bindNext();
- is=v_offset - (SCREEN_WIDTH / 2 / HLINE) - GEN_INC;
- if(is<0)is=0; // Minimum bound
+ GLfloat pointArray[ light.size() + (int)p->light ][2];
- // ie -> i end
+ for ( i = 0; i < (int)light.size(); i++ ) {
+ pointArray[i][0] = light[i].loc.x - offset.x;
+ pointArray[i][1] = light[i].loc.y;
+ }
- ie=v_offset + (SCREEN_WIDTH / 2 / HLINE) + GEN_INC + HLINE;
- if(ie>(int)current->lineCount)ie=current->lineCount; // Maximum bound
- else if(ie < GEN_INC)ie = GEN_INC;
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- /*
- * Make more direct variables for quicker referencing.
- */
+ glUseProgram( shaderProgram );
+ glUniform1i( glGetUniformLocation( shaderProgram, "sampler"), 0 );
+ glUniform1f( glGetUniformLocation( shaderProgram, "amb" ), 1 );
- cline =current->line;
- cx_start=current->x_start;
+ if ( p->light ) {
+ pointArray[light.size() + 1][0] = (float)( p->loc.x + SCREEN_WIDTH / 2 );
+ pointArray[light.size() + 1][1] = (float)( p->loc.y );
+ }
- /*
- * Invert shading if desired.
- */
+ if ( light.size() + (int)p->light == 0)
+ glUniform1i( glGetUniformLocation( shaderProgram, "numLight"), 0);
+ else {
+ glUniform1i ( glGetUniformLocation( shaderProgram, "numLight" ), light.size() + (int)p->light );
+ glUniform2fv( glGetUniformLocation( shaderProgram, "lightLocation"), light.size() + (int)p->light, (GLfloat *)&pointArray );
+ glUniform3f ( glGetUniformLocation( shaderProgram, "lightColor" ), 1.0f, 1.0f, 1.0f );
+ }
- shade*=-1;
+ /*
+ * Draw the dirt?
+ */
+
+ glBegin( GL_QUADS );
- /*
- * Draw structures. We draw structures behind the dirt/grass so that the building's
- * corners don't stick out.
- */
-
- for(auto &part : particles){
- if(part->behind)
- part->draw();
- }
- for(auto &b : current->build){
- b->draw();
- }
- /*
- * Draw the layer up until the grass portion, which is done later.
- */
+ // faulty
+ /*glTexCoord2i(0 ,0);glVertex2i(pOffset - (SCREEN_WIDTH / 1.5),0);
+ glTexCoord2i(64,0);glVertex2i(pOffset + (SCREEN_WIDTH / 1.5),0);
+ glTexCoord2i(64,1);glVertex2i(pOffset + (SCREEN_WIDTH / 1.5),GROUND_HEIGHT_MINIMUM);
+ glTexCoord2i(0 ,1);glVertex2i(pOffset - (SCREEN_WIDTH / 1.5),GROUND_HEIGHT_MINIMUM);*/
- bool hey=false;
- glEnable(GL_TEXTURE_2D);
- glActiveTexture(GL_TEXTURE0);
- bgTex->bindNext();
+ for ( i = iStart; i < iEnd; i++ ) {
+ if ( worldData[i].groundHeight <= 0 ) {
+ worldData[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1;
+ glColor4ub( 0, 0, 0, 255 );
+ } else
+ safeSetColorA( 150, 150, 150, 255 );
- GLfloat pointArray[light.size() + (int)p->light][2];
- for(uint w = 0; w < light.size(); w++){
- pointArray[w][0] = light[w].loc.x - offset.x;
- pointArray[w][1] = light[w].loc.y;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //for the s direction
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //for the t direction
- glUseProgram(shaderProgram);
- glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
- glUniform1f(glGetUniformLocation(shaderProgram, "amb"), float(shade+50.0f)/100.0f);
- if(p->light){
- //glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 1);
- //glUniform2f(glGetUniformLocation(shaderProgram, "lightLocation"), p->loc.x - offset.x+SCREEN_WIDTH/2, p->loc.y);
- //glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1.0f,1.0f,1.0f);
- pointArray[light.size()+1][0] = (float)(p->loc.x + SCREEN_WIDTH/2);
- pointArray[light.size()+1][1] = (float)(p->loc.y);
- }
- if(light.size()+(int)p->light == 0){
- glUniform1i(glGetUniformLocation(shaderProgram, "numLight"), 0);
- }else{
- glUniform1i (glGetUniformLocation(shaderProgram, "numLight"), light.size()+(int)p->light);
- glUniform2fv(glGetUniformLocation(shaderProgram, "lightLocation"), light.size()+(int)p->light, (GLfloat *)&pointArray);
- glUniform3f (glGetUniformLocation(shaderProgram, "lightColor"), 1.0f,1.0f,1.0f);
- }
-
- glBegin(GL_QUADS);
+ glTexCoord2i( 0, 0 ); glVertex2i(worldStart + i * HLINE , worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 1, 0 ); glVertex2i(worldStart + i * HLINE + HLINE , worldData[i].groundHeight - GRASS_HEIGHT );
+
+ glTexCoord2i( 1, (int)(worldData[i].groundHeight / 64) + worldData[i].groundColor ); glVertex2i(worldStart + i * HLINE + HLINE, 0 );
+ glTexCoord2i( 0, (int)(worldData[i].groundHeight / 64) + worldData[i].groundColor ); glVertex2i(worldStart + i * HLINE , 0 );
+
+ if ( worldData[i].groundHeight == GROUND_HEIGHT_MINIMUM - 1 )
+ worldData[i].groundHeight = 0;
+ }
- glTexCoord2i(0 ,0);glVertex2i(v_offset - (SCREEN_WIDTH / 1.5),0);
- glTexCoord2i(64,0);glVertex2i(v_offset + (SCREEN_WIDTH / 1.5),0);
- glTexCoord2i(64,1);glVertex2i(v_offset + (SCREEN_WIDTH / 1.5),base);
- glTexCoord2i(0 ,1);glVertex2i(v_offset - (SCREEN_WIDTH / 1.5),base);
-
- for(i=is;i<(unsigned)ie-GEN_INC;i++){
- cline[i].y+=(yoff-DRAW_Y_OFFSET); // Add the y offset
- if(!cline[i].y){
- cline[i].y=base;
- hey=true;
- glColor4ub(0,0,0,255);
- }else safeSetColorA(150+shade*2,150+shade*2,150+shade*2,255);
- glTexCoord2i(0,0); glVertex2i(cx_start+i*HLINE ,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(1,0); glVertex2i(cx_start+i*HLINE+HLINE,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(1,(int)(cline[i].y/64)+cline[i].color);glVertex2i(cx_start+i*HLINE+HLINE,0);
- glTexCoord2i(0,(int)(cline[i].y/64)+cline[i].color);glVertex2i(cx_start+i*HLINE ,0);
- cline[i].y-=(yoff-DRAW_Y_OFFSET); // Restore the line's y value
- if(hey){
- hey=false;
- cline[i].y=0;
- }
- }
glEnd();
+
glUseProgram(0);
glDisable(GL_TEXTURE_2D);
- /*
- * Draw grass on every line.
- */
- float cgh[2];
+ /*
+ * Draw the grass/the top of the ground.
+ */
- glEnable(GL_TEXTURE_2D);
- glActiveTexture(GL_TEXTURE0);
+ glEnable( GL_TEXTURE_2D );
+
+ glActiveTexture( GL_TEXTURE0 );
bgTex->bindNext();
- glUseProgram(shaderProgram);
- glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //for the s direction
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //for the t direction
- //glBegin(GL_QUADS);
+
+ glUseProgram( shaderProgram );
+ glUniform1i( glGetUniformLocation( shaderProgram, "sampler"), 0);
- for(i=is;i<(unsigned)ie-GEN_INC;i++){
-
- /*
- * Load the current line's grass values
- */
-
- if(cline[i].y)memcpy(cgh,cline[i].gh,2*sizeof(float));
- else memset(cgh,0 ,2*sizeof(float));
-
-
-
- /*
- * Flatten the grass if the player is standing on it.
- */
+ float cgh[2];
+ for ( i = iStart; i < iEnd - GROUND_HILLINESS; i++ ) {
- if(!cline[i].gs){
- cgh[0]/=4;
- cgh[1]/=4;
+ // load the current line's grass values
+ if ( worldData[i].groundHeight )
+ memcpy( cgh, worldData[i].grassHeight, 2 * sizeof( float ));
+ else
+ memset( cgh, 0 , 2 * sizeof( float ));
+
+ // flatten the grass if the player is standing on it.
+ if( !worldData[i].grassUnpressed ){
+ cgh[0] /= 4;
+ cgh[1] /= 4;
}
- /*
- * Actually draw the grass.
- */
+ // actually draw the grass.
- cline[i].y+=(yoff-DRAW_Y_OFFSET);
- safeSetColorA(255,255,255,255);
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i(cx_start+i*HLINE ,cline[i].y+cgh[0]);
- glTexCoord2i(1,0);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y+cgh[0]);
- glTexCoord2i(1,1);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(0,1);glVertex2i(cx_start+i*HLINE ,cline[i].y-GRASS_HEIGHT);
- glEnd();
-
- glBegin(GL_QUADS);
- glTexCoord2i(0,0);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y+cgh[1]);
- glTexCoord2i(1,0);glVertex2i(cx_start+i*HLINE+HLINE ,cline[i].y+cgh[1]);
- glTexCoord2i(1,1);glVertex2i(cx_start+i*HLINE+HLINE ,cline[i].y-GRASS_HEIGHT);
- glTexCoord2i(0,1);glVertex2i(cx_start+i*HLINE+HLINE/2,cline[i].y-GRASS_HEIGHT);
+ safeSetColorA( 255, 255, 255, 255 );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart + i * HLINE , worldData[i].groundHeight + cgh[0] );
+ glTexCoord2i( 1, 0 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight + cgh[0] );
+ glTexCoord2i( 1, 1 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart + i * HLINE , worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 0, 0 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight + cgh[1] );
+ glTexCoord2i( 1, 0 ); glVertex2i( worldStart + i * HLINE + HLINE , worldData[i].groundHeight + cgh[1] );
+ glTexCoord2i( 1, 1 ); glVertex2i( worldStart + i * HLINE + HLINE , worldData[i].groundHeight - GRASS_HEIGHT );
+ glTexCoord2i( 0, 1 ); glVertex2i( worldStart + i * HLINE + HLINE / 2, worldData[i].groundHeight - GRASS_HEIGHT );
glEnd();
-
- cline[i].y-=(yoff-DRAW_Y_OFFSET);
}
- //glEnd();
+
glUseProgram(0);
glDisable(GL_TEXTURE_2D);
/*
- * Draw non-structure entities.
- */
- for(auto &part : particles){if(!part->behind)part->draw();}
- for(auto &n : current->npc){
- n->loc.y+=(yoff-DRAW_Y_OFFSET);
- n->draw();
- n->loc.y-=(yoff-DRAW_Y_OFFSET);
- }
- for(auto &m : current->mob){
- m->loc.y+=(yoff-DRAW_Y_OFFSET);
- m->draw();
- m->loc.y-=(yoff-DRAW_Y_OFFSET);
- }
- for(auto &o : current->object){
- if(o->alive){
- o->loc.y+=(yoff-DRAW_Y_OFFSET);
- o->draw();
- o->loc.y-=(yoff-DRAW_Y_OFFSET);
- }
- }
-
- /*
- * If we're drawing the closest/last world, handle and draw the player.
- */
+ * Draw remaining entities.
+ */
- if(current==this){
-
- /*
- * Calculate the line that the player is on
- */
-
- unsigned int ph = (p->loc.x + p->width / 2 - x_start) / HLINE;
-
- /*
- * If the player is on the ground, flatten the grass where the player is standing
- * by setting line.gs to false.
- */
-
- if(p->ground==1){
- for(i=0;i<lineCount-GEN_INC;i++){
- if(i < ph + 6 &&
- i > ph - 6 )
- cline[i].gs=false;
- else cline[i].gs=true;
- }
- }else{
- for(i=0;i<lineCount-GEN_INC;i++){
- cline[i].gs=true;
- }
- }
-
- /*
- * Draw the player.
- */
-
- p->draw();
-
+ for ( auto &part : particles ) {
+ if( !part->behind )
+ part->draw();
}
- /*
- * Restore the inverted shading if it was inverted above.
- */
-
- shade*=-1;
+ for ( auto &n : npc )
+ n->draw();
+
+ for ( auto &m : mob )
+ m->draw();
+
+ for ( auto &o : object )
+ o->draw();
+ /*
+ * Handle grass-squishing.
+ */
+
+ // calculate the line that the player is on
+ int ph = ( p->loc.x + p->width / 2 - worldStart ) / HLINE;
+
+ // flatten grass under the player if the player is on the ground
+ if ( p->ground ) {
+ for ( i = 0; i < (int)(worldData.size() - GROUND_HILLINESS); i++ )
+ worldData[i].grassUnpressed = !( i < ph + 6 && i > ph - 6 );
+ } else {
+ for ( i = 0; i < (int)(worldData.size() - GROUND_HILLINESS); i++ )
+ worldData[i].grassUnpressed = true;
+ }
+
/*
- * Draw the next closest world if it exists.
- */
-
- /*if(current->infront){
- yoff -= DRAW_Y_OFFSET;
- shade -= DRAW_SHADE;
-
- current=current->infront;
- goto LOOP2;
-
- }else{*/
-
- /*
- * If finished, reset the yoff and shade variables for the next call.
- */
-
- yoff=DRAW_Y_OFFSET;
- shade=0;
- //}
+ * Draw the player.
+ */
+
+ p->draw();
}
-void World::singleDetect(Entity *e){
+/**
+ * Handles physics and such for a single entity.
+ *
+ * This function is kept private, as World::detect() should be used instead to
+ * handle stuffs for all entities at once.
+ */
+
+void World::
+singleDetect( Entity *e )
+{
+ std::string killed;
unsigned int i,j;
int l;
@@ -802,12 +695,12 @@ void World::singleDetect(Entity *e){
* Kill any dead entities.
*/
- if(!e->alive||e->health<=0){
- for(i=0;i<entity.size();i++){
- if(entity[i]==e){
- switch(e->type){
+ if ( !e->alive || e->health <= 0 ) {
+ for ( i = 0; i < entity.size(); i++) {
+ if ( entity[i] == e ){
+ switch ( e->type ) {
case STRUCTURET:
- std::cout<<"Killed a building..."<<std::endl;
+ killed = "structure";
for(j=0;j<build.size();j++){
if(build[j]==e){
delete build[j];
@@ -817,7 +710,7 @@ void World::singleDetect(Entity *e){
}
break;
case NPCT:
- std::cout<<"Killed an NPC..."<<std::endl;
+ killed = "NPC";
for(j=0;j<npc.size();j++){
if(npc[j]==e){
delete npc[j];
@@ -827,7 +720,7 @@ void World::singleDetect(Entity *e){
}
break;
case MOBT:
- std::cout<<"Killed a mob..."<<std::endl;
+ killed = "mob";
/*for(j=0;j<mob.size();j++){
if(mob[j]==e){
delete mob[j];
@@ -837,7 +730,7 @@ void World::singleDetect(Entity *e){
}*/
break;
case OBJECTT:
- std::cout<<"Killed an object..."<<std::endl;
+ killed = "object";
for(j=0;j<object.size();j++){
if(object[j]==e){
delete object[j];
@@ -849,6 +742,7 @@ void World::singleDetect(Entity *e){
default:
break;
}
+ std::cout << "Killed a " << killed << "..." << std::endl;
entity.erase(entity.begin()+i);
return;
}
@@ -860,7 +754,7 @@ void World::singleDetect(Entity *e){
/*
* Handle only living entities.
*/
-
+
if(e->alive){
if(e->type == MOBT && Mobp(e)->subtype == MS_TRIGGER)return;
@@ -869,7 +763,7 @@ void World::singleDetect(Entity *e){
* Calculate the line that this entity is currently standing on.
*/
- l=(e->loc.x + e->width / 2 - x_start) / HLINE;
+ l=(e->loc.x + e->width / 2 - worldStart) / HLINE;
if(l < 0) l=0;
i = l;
if(i > lineCount-1) i=lineCount-1;
@@ -878,39 +772,11 @@ void World::singleDetect(Entity *e){
* If the entity is under the world/line, pop it back to the surface.
*/
- if(e->loc.y < line[i].y){
-
- /*
- * Check that the entity isn't trying to run through a wall.
- */
-
- //if(e->loc.y + e->height > line[i-(int)e->width/2/HLINE].y &&
- // e->loc.y + e->height > line[i+(int)e->width/2/HLINE].y ){
-
- e->loc.y=line[i].y - .001 * deltaTime;
- e->ground=true;
- e->vel.y=0;
-
- //}else{
-
- /*
- * Push the entity out of the wall if it's trying to go through it.
- */
-
- /*do{
- e->loc.x+=.001 * e->vel.x>0?-1:1;
-
- l=(e->loc.x - e->width / 2 - x_start) / HLINE;
- if(l < 0){
- std::cout<<"push kill lol "<<e->type<<std::endl;
- e->alive = false; return; }
- i = l;
- if(i > lineCount-1){
- std::cout<<"push kill lol "<<e->type<<std::endl;
- e->alive = false; return; }
- }while(line[i].y>e->loc.y+ e->height);
-
- }*/
+ if ( e->loc.y < worldData[i].groundHeight ) {
+
+ e->loc.y= worldData[i].groundHeight - .001 * deltaTime;
+ e->ground=true;
+ e->vel.y=0;
/*
* Handle gravity if the entity is above the line.
@@ -919,7 +785,7 @@ void World::singleDetect(Entity *e){
}else{
if(e->type == STRUCTURET && e->loc.y > 2000){
- e->loc.y = line[i].y;
+ e->loc.y = worldData[i].groundHeight;
e->vel.y = 0;
e->ground = true;
return;
@@ -931,47 +797,40 @@ void World::singleDetect(Entity *e){
* Insure that the entity doesn't fall off either edge of the world.
*/
- if(e->loc.x < x_start){ // Left bound
+ if(e->loc.x < worldStart){ // Left bound
e->vel.x=0;
- e->loc.x=(float)x_start + HLINE / 2;
+ e->loc.x=(float)worldStart + HLINE / 2;
- }else if(e->loc.x + e->width + HLINE > x_start + getWidth(this)){ // Right bound
+ }else if(e->loc.x + e->width + HLINE > worldStart + worldStart * -2){ // Right bound
e->vel.x=0;
- e->loc.x=x_start + getWidth(this) - e->width - HLINE;
+ e->loc.x=worldStart + worldStart * -2 - e->width - HLINE;
}
}
}
-void World::detect(Player *p){
-
- /*
- * Handle the player.
- */
-
- //auto pl = std::async(&World::singleDetect,this,p);
- //std::thread(&World::singleDetect,this, p).detach();
- singleDetect(p);
+void World::
+detect( Player *p )
+{
+ // handle the player
+ std::thread( &World::singleDetect, this, p).detach();
- /*
- * Handle all remaining entities in this world.
- */
-
-//LOOOOP:
- for(auto &e : entity)
- //std::thread(&World::singleDetect,this,e).detach();
- singleDetect(e);
- for(auto &part : particles){
+ // handle other entities
+ for ( auto &e : entity )
+ std::thread(&World::singleDetect,this,e).detach();
+
+ // handle particles
+ for ( auto &part : particles ) {
int l;
unsigned int i;
- l=(part->loc.x + part->width / 2 - x_start) / HLINE;
+ l=(part->loc.x + part->width / 2 - worldStart) / HLINE;
if(l < 0) l=0;
i = l;
if(i > lineCount-1) i=lineCount-1;
- if(part->loc.y < line[i].y){
- part->loc.y = line[i].y;
+ if(part->loc.y < worldData[i].groundHeight){
+ part->loc.y = worldData[i].groundHeight;
part->vely = 0;
part->velx = 0;
part->canMove = false;
@@ -1034,8 +893,6 @@ void World::addStructure(BUILD_SUB sub, float x,float y, char *tex, const char *
else
strcpy((build.back()->inside = new char[1]),"\0");
- //strcpy((build.back()->outside = new char[1 + strlen((char *)(currentXML+4))]),(char *)(currentXML+4));
-
entity.push_back(build.back());
}
@@ -1106,27 +963,6 @@ void World::addLight(vec2 loc, Color color){
}
}
-/*void World::removeObject(Object i){
- object.delete[](i);
-}*/
-
-/*
- * The rest of these functions are explained well enough in world.h ;)
-*/
-
-/*void World::addLayer(unsigned int width){
- if(behind){
- behind->addLayer(width);
- return;
- }
- behind=new World();
- behind->generate(width);
- behind->infront=this;
- behind->star=star;
- behind->bgmObj=bgmObj;
- behind->bgTex=bgTex;
-}*/
-
NPC *World::getAvailableNPC(void){
for(auto &n : npc){
if(n->aiFunc.empty())
@@ -1154,13 +990,20 @@ char *World::setToRight(const char *file){
return toRight;
}
-World *World::goWorldLeft(Player *p){
+World *World::
+goWorldLeft( Player *p )
+{
World *tmp;
- if(toLeft && p->loc.x < x_start + (int)HLINE * 15){
+
+ // check if player is at world edge
+ if(toLeft && p->loc.x < worldStart + HLINE * 15.0f){
+
+ // load world (`toLeft` conditional confirms existance)
tmp = loadWorldFromXML(toLeft);
- p->loc.x = -tmp->x_start - HLINE * 10;
- p->loc.y = tmp->line[tmp->lineCount - 1].y;
+ // adjust player location
+ p->loc.x = tmp->worldStart - HLINE * -10.0f;
+ p->loc.y = tmp->worldData[tmp->lineCount - 1].groundHeight;
return tmp;
}
@@ -1170,41 +1013,29 @@ World *World::goWorldLeft(Player *p){
World *World::goWorldRight(Player *p){
World *tmp;
- if(toRight && p->loc.x + p->width > -x_start - HLINE * 15){
+ if(toRight && p->loc.x + p->width > -worldStart - HLINE * 15){
tmp = loadWorldFromXML(toRight);
- p->loc.x = tmp->x_start + (int)HLINE * 10;
- p->loc.y = tmp->line[0].y;
+ p->loc.x = tmp->worldStart + HLINE * 10;
+ p->loc.y = GROUND_HEIGHT_MINIMUM;
return tmp;
}
return this;
}
-/*World *World::goWorldBack(Player *p){
- if(behind&&p->loc.x>(int)(0-getWidth(behind)/2)&&p->loc.x<getWidth(behind)/2){
- return behind;
- }
- return this;
-}
-
-World *World::goWorldFront(Player *p){
- if(infront&&p->loc.x>(int)(0-getWidth(infront)/2)&&p->loc.x<getWidth(infront)/2){
- return infront;
- }
- return this;
-}*/
+std::vector<std::string> inside;
-std::vector<char *>inside;
-World *World::goInsideStructure(Player *p){
+World *World::
+goInsideStructure( Player *p )
+{
World *tmp;
char *current;
if(inside.empty()){
for(auto &b : build){
if(p->loc.x > b->loc.x &&
p->loc.x + p->width < b->loc.x + b->width ){
- inside.push_back(new char[1 + strlen(currentXML)]);
- strcpy(inside.back(),(char *)(currentXML+4));
+ inside.push_back((std::string)(currentXML.c_str() + 4));
tmp = loadWorldFromXML(b->inside);
@@ -1216,16 +1047,17 @@ World *World::goInsideStructure(Player *p){
}
}
}else{
- strcpy((current = new char[strlen((char *)(currentXML + 4)) + 1]),(char *)(currentXML + 4));
- tmp = loadWorldFromXML(inside.back());
+ strcpy((current = new char[strlen((const char *)(currentXML.c_str() + 4)) + 1]),(const char *)(currentXML.c_str() + 4));
+ tmp = loadWorldFromXML(inside.back().c_str());
for(auto &b : tmp->build){
if(!strcmp(current,b->inside)){
- p->loc.x = b->loc.x + (b->width / 2);
- delete[] inside.back();
inside.pop_back();
ui::toggleBlackFast();
ui::waitForCover();
+
+ p->loc.x = b->loc.x + (b->width / 2);
+
ui::toggleBlackFast();
return tmp;
@@ -1239,18 +1071,12 @@ World *World::goInsideStructure(Player *p){
void World::addHole(unsigned int start,unsigned int end){
unsigned int i;
for(i=start;i<end;i++){
- line[i].y=0;
+ worldData[i].groundHeight = 0;
}
}
int World::getTheWidth(void){
- World *hey=this;
-/*LOOP:
- if(hey->infront){
- hey=hey->infront;
- goto LOOP;
- }*/
- return -hey->x_start*2;
+ return worldStart * -2;
}
void World::save(void){
@@ -1347,26 +1173,17 @@ IndoorWorld::IndoorWorld(void){
IndoorWorld::~IndoorWorld(void){
delete bgTex;
- delete[] star;
- delete[] line;
deleteEntities();
}
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.
+ lineCount=width+GROUND_HILLINESS; // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
if(lineCount<=0)abort();
- line = new struct line_t[lineCount]; //(struct line_t *)calloc(lineCount,sizeof(struct line_t)); // Allocate memory for the array 'line'
- memset(line,0,lineCount*sizeof(struct line_t));
+ worldData = std::vector<WorldData> (lineCount, (WorldData) { false, {0,0}, INDOOR_FLOOR_HEIGHT, 0 });
- for(i=0;i<lineCount;i++){ // Indoor areas don't have to be directly on the ground (i.e. 0)...
- line[i].y=INDOOR_FLOOR_HEIGHT;
- }
- //behind=infront=NULL; // Set pointers to other worlds to NULL
- //toLeft=toRight=NULL; // to avoid accidental calls to goWorld... functions
- x_start=0-getWidth(this)/2+GEN_INC/2*HLINE; // Calculate x_start (explained in world.h)
+ worldStart = (width - GROUND_HILLINESS) * HLINE / 2 * -1;
}
void IndoorWorld::draw(Player *p){
@@ -1405,13 +1222,11 @@ void IndoorWorld::draw(Player *p){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //for the t direction
glColor4ub(255,255,255,255);
- glBegin(GL_QUADS);
- //for(j = x_start - SCREEN_WIDTH / 2;j < -x_start + SCREEN_WIDTH / 2; j += 512){
- glTexCoord2i(0,1); glVertex2i( x_start - SCREEN_WIDTH / 2,0);
- glTexCoord2i((-x_start*2+SCREEN_WIDTH)/512,1);glVertex2i(-x_start + SCREEN_WIDTH / 2,0);
- glTexCoord2i((-x_start*2+SCREEN_WIDTH)/512,0);glVertex2i(-x_start + SCREEN_WIDTH / 2,SCREEN_HEIGHT);
- glTexCoord2i(0,0); glVertex2i( x_start - SCREEN_WIDTH / 2,SCREEN_HEIGHT);
- //}
+ glBegin(GL_QUADS);
+ glTexCoord2i(0,1); glVertex2i( worldStart - SCREEN_WIDTH / 2,0);
+ glTexCoord2i((-worldStart*2+SCREEN_WIDTH)/512,1);glVertex2i(-worldStart + SCREEN_WIDTH / 2,0);
+ glTexCoord2i((-worldStart*2+SCREEN_WIDTH)/512,0);glVertex2i(-worldStart + SCREEN_WIDTH / 2,SCREEN_HEIGHT);
+ glTexCoord2i(0,0); glVertex2i( worldStart - SCREEN_WIDTH / 2,SCREEN_HEIGHT);
glEnd();
glUseProgram(0);
@@ -1438,14 +1253,14 @@ void IndoorWorld::draw(Player *p){
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "sampler"), 0);
glBegin(GL_QUADS);
- for(;i < ie - GEN_INC;i++){
+ for(;i < ie - GROUND_HILLINESS;i++){
safeSetColor(150,100,50);
- x = x_start + i * HLINE;
- glVertex2i(x ,line[i].y);
- glVertex2i(x + HLINE,line[i].y);
- glVertex2i(x + HLINE,line[i].y - 50);
- glVertex2i(x ,line[i].y - 50);
+ x = worldStart + i * HLINE;
+ glVertex2i(x ,worldData[i].groundHeight);
+ glVertex2i(x + HLINE,worldData[i].groundHeight);
+ glVertex2i(x + HLINE,worldData[i].groundHeight - 50);
+ glVertex2i(x ,worldData[i].groundHeight - 50);
}
glEnd();
glUseProgram(0);
@@ -1478,15 +1293,10 @@ Arena::Arena(World *leave,Player *p,Mob *m){
battleNest.push_back(leave);
battleNestLoc.push_back(p->loc);
-
- star = new vec2[100];
- memset(star,0,100 * sizeof(vec2));
}
Arena::~Arena(void){
delete bgTex;
- delete[] star;
- delete[] line;
deleteEntities();
}
@@ -1514,16 +1324,14 @@ World *Arena::exitArena(Player *p){
#include <tinyxml2.h>
using namespace tinyxml2;
-char *currentXML = NULL;
+std::string currentXML = "\0";
extern World *currentWorld;
World *loadWorldFromXML(const char *path){
- if(currentXML){
+ if ( currentXML != "\0" )
currentWorld->save();
- delete[] currentXML;
- }
-
+
return loadWorldFromXMLNoSave(path);
}
@@ -1537,16 +1345,10 @@ World *loadWorldFromXMLNoSave(const char *path){
bool dialog,Indoor;
const char *ptr,*name;
-
- unsigned int size = 5 + strlen(path);
+
+ currentXML = (std::string)"xml/" + path;
- if(currentXML)
- delete[] currentXML;
- memset((currentXML = new char[size]),0,size);
- strcpy(currentXML,"xml/");
- strcat(currentXML,path);
-
- xml.LoadFile(currentXML);
+ xml.LoadFile(currentXML.c_str());
wxml = xml.FirstChildElement("World");
if(wxml){
@@ -1563,12 +1365,14 @@ World *loadWorldFromXMLNoSave(const char *path){
while(wxml){
name = wxml->Name();
+
if(!strcmp(name,"link")){
if((ptr = wxml->Attribute("left")))
tmp->setToLeft(ptr);
else if((ptr = wxml->Attribute("right")))
tmp->setToRight(ptr);
- else abort();
+ else
+ abort();
}else if(!strcmp(name,"style")){
tmp->setStyle(wxml->Attribute("folder"));
tmp->setBackground((WORLD_BG_TYPE)wxml->UnsignedAttribute("background"));
@@ -1577,20 +1381,19 @@ World *loadWorldFromXMLNoSave(const char *path){
if(!strcmp(wxml->Attribute("type"),"Random")){
if(Indoor)
((IndoorWorld *)tmp)->generate(wxml->UnsignedAttribute("width"));
- else
+ else {
+
tmp->generate(wxml->UnsignedAttribute("width"));
- }else if(Indoor){
+ }
+ }else if(Indoor)
abort();
- }
}else if(!strcmp(name,"mob")){
unsigned int type;
-
type = wxml->UnsignedAttribute("type");
if(wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR)
- tmp->addMob(type,getRand() % tmp->getTheWidth() / 2,100);
+ tmp->addMob(type,0,100);
else
tmp->addMob(type,spawnx,wxml->FloatAttribute("y"));
-
if(wxml->QueryBoolAttribute("aggressive",&dialog) == XML_NO_ERROR)
tmp->mob.back()->aggressive = dialog;
@@ -1598,7 +1401,7 @@ World *loadWorldFromXMLNoSave(const char *path){
const char *npcname;
if(wxml->QueryFloatAttribute("x",&spawnx) != XML_NO_ERROR)
- tmp->addNPC(getRand() % tmp->getTheWidth() / 2.0f,100);
+ tmp->addNPC(0,100);
else
tmp->addNPC(spawnx,wxml->FloatAttribute("y"));
@@ -1642,7 +1445,7 @@ World *loadWorldFromXMLNoSave(const char *path){
while(vil){
name = vil->Name();
- randx = getRand() % tmp->getTheWidth() - (tmp->getTheWidth() / 2.0f);
+ randx = 0;
/**
* READS DATA ABOUT STRUCTURE CONTAINED IN VILLAGE
diff --git a/xml/playerSpawnHill1.xml b/xml/playerSpawnHill1.xml
index d84d291..2cac743 100644
--- a/xml/playerSpawnHill1.xml
+++ b/xml/playerSpawnHill1.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<World>
<style background="0" bgm="assets/music/embark.wav" folder="assets/style/classic/" />
- <generation type="Random" width="1600" />
+ <generation type="Random" width="500" />
<link left="playerSpawnHill2.xml" />
<mob type="1" aggressive="false" />