aboutsummaryrefslogtreecommitdiffstats
path: root/src/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/world.cpp')
-rw-r--r--src/world.cpp1377
1 files changed, 590 insertions, 787 deletions
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