diff --git a/src/lephisto.c b/src/lephisto.c index 6993cc8..f1ecf44 100644 --- a/src/lephisto.c +++ b/src/lephisto.c @@ -94,13 +94,13 @@ int main(int argc, char** argv) { /* Initialize SDL for possible warnings. */ SDL_Init(0); - /* Input must be initialized for config to work. */ - input_init(); - /* Create the home directory if needed. */ if(lfile_dirMakeExist(".")) WARN("Unable to create lephisto directory '%s'", lfile_basePath()); + /* Input must be initialized for config to work. */ + input_init(); + /* Set the configuration. */ snprintf(buf, PATH_MAX, "%s"CONF_FILE, lfile_basePath()); conf_setDefaults(); /* Default config values. */ @@ -115,22 +115,6 @@ int main(int argc, char** argv) { /* Random numbers. */ rng_init(); - if(gl_init()) { - /* Initializes video output. */ - ERR("Initializing video output failed, exiting..."); - SDL_Quit(); - exit(EXIT_FAILURE); - } - - /* See if the data file is valid. */ - if(pack_check(data)) { - ERR("Data file '%s' not found", DATA); - WARN("You can specify what data file you want to use with '-d'"); - WARN("See -h or -- help for more infoamtion."); - SDL_Quit(); - exit(EXIT_FAILURE); - } - /* OpenGL */ if(gl_init()) { /* Init video output. */ ERR("Initializing video output failed, exiting..."); @@ -256,6 +240,7 @@ void unload_all(void) { missions_free(); factions_free(); commodity_free(); + var_cleanup(); /* Clean up mission variables. */ } /** @@ -371,7 +356,7 @@ static void render_all(void) { pilots_render(); weapons_render(WEAPON_LAYER_FG); spfx_render(SPFX_LAYER_BACK); - space_renderOverlay(); + space_renderOverlay(cur_dt); /* FG. */ player_render(); spfx_render(SPFX_LAYER_FRONT); diff --git a/src/nebulae.c b/src/nebulae.c index 7ea9e4f..c140733 100644 --- a/src/nebulae.c +++ b/src/nebulae.c @@ -9,10 +9,13 @@ #include "lfile.h" #include "rng.h" #include "menu.h" +#include "player.h" #include "perlin.h" #define NEBULAE_Z 16 /* Z plane. */ -#define NEBULAE_PATH "gen/nebu_%02d.png" +#define NEBULAE_PUFFS 32 /* Amount of puffs to generate. */ +#define NEBULAE_PATH_BG "gen/nebu_bg_%dx%d_%02d.png" +#define NEBULAE_PATH_PUFF "gen/nebu_puff_%02d.png" /* Extern. */ extern double gui_xoff, gui_yoff; @@ -32,8 +35,28 @@ static unsigned int last_render = 0; static double nebu_view = 0.; static double nebu_dt = 0.; +/* Puff textures. */ +typedef struct NebulaePuffTex_ { + GLuint tex; /* Actualy texture. */ + double w, h; /* Real dimensions. */ + double pw, ph; /* Padding. */ +} NebulaePuffTex; +static NebulaePuffTex nebu_pufftexs[NEBULAE_PUFFS]; + +/* Puff handling. */ +typedef struct NebulaePuff_ { + double x, y; /* Position. */ + double a, va; /* Alpha, alpha velocity. */ + double height; /* Height vs player. */ + NebulaePuffTex* tex; /* Texture. */ +} NebulaePuff; +static NebulaePuff* nebu_puffs = NULL; +static int nebu_npuffs = 0; + static int nebu_checkCompat(const char* file); +static void nebu_loadTexture(SDL_Surface* sur, int w, int h, GLuint tex); static void nebu_generate(void); +static void nebu_generatePuffs(void); static void saveNebulae(float* map, const uint32_t w, const uint32_t h, const char* file); static SDL_Surface* loadNebulae(const char* file); @@ -55,10 +78,12 @@ void nebu_init(void) { nebu_pw = gl_pot(nebu_w); nebu_ph = gl_pot(nebu_h); + nebu_generatePuffs(); + /* Load each, checking for compatibility and padding. */ glGenTextures(NEBULAE_Z, nebu_textures); for(i = 0; i < NEBULAE_Z; i++) { - snprintf(nebu_file, PATH_MAX, NEBULAE_PATH, i); + snprintf(nebu_file, PATH_MAX, NEBULAE_PATH_BG, nebu_w, nebu_h, i); if(nebu_checkCompat(nebu_file)) { /* Incompatable. */ LOG("No nebulae found, generating (this may take a while)."); @@ -75,33 +100,49 @@ void nebu_init(void) { WARN("Nebulae raw size doesn't match expected! (%dx%d instead of %dx%d)", nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph); - /* Prepare to load into OpenGL. */ - nebu_sur = gl_prepareSurface(nebu_sur); - if((nebu_sur->w != nebu_pw) || (nebu_sur->h != nebu_ph)) - WARN("Nebulae size doesn't match expected! (%dx%d instead of %dx%d)", - nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph); - /* Load the textures. */ - glBindTexture(GL_TEXTURE_2D, nebu_textures[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - /* Store into opengl saving only alpha channel in video memory. */ - SDL_LockSurface(nebu_sur); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, nebu_sur->w, nebu_sur->h, - 0, GL_RGBA, GL_UNSIGNED_BYTE, nebu_sur->pixels); - SDL_UnlockSurface(nebu_sur); - - SDL_FreeSurface(nebu_sur); - gl_checkErr(); + nebu_loadTexture(nebu_sur, nebu_pw, nebu_ph, nebu_textures[i]); } DEBUG("Loaded %d Nebulae Layers", NEBULAE_Z); } +/* Load sur into tex, check for expected size of w and h. */ +static void nebu_loadTexture(SDL_Surface* sur, int w, int h, GLuint tex) { + SDL_Surface* nebu_sur; + + nebu_sur = gl_prepareSurface(sur); + if((w != 0) && (h != 0) && + ((nebu_sur->w != w) || (nebu_sur->h != h))) { + + WARN("Nebulae size doesn't match expected! (%dx%d instead of %dx%d)", + nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph); + return; + } + + /* Load the textures. */ + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + /* Store into opengl saving only alpha channel in video memory. */ + SDL_LockSurface(nebu_sur); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, nebu_sur->w, nebu_sur->h, + 0, GL_RGBA, GL_UNSIGNED_BYTE, nebu_sur->pixels); + SDL_UnlockSurface(nebu_sur); + + SDL_FreeSurface(nebu_sur); + gl_checkErr(); +} + /* Clean up the nebu subsystem. */ void nebu_exit(void) { + int i; + glDeleteTextures(NEBULAE_Z, nebu_textures); + + for(i = 0; i < NEBULAE_PUFFS; i++) + glDeleteTextures(1, &nebu_pufftexs[i].tex); } /* Render the nebulae. */ @@ -209,16 +250,19 @@ void nebu_render(void) { gl_checkErr(); } -void nebu_renderOverlay(void) { +void nebu_renderOverlay(const double dt) { #define ANG45 0.70710678118654757 #define COS225 0.92387953251128674 #define SIN225 0.38268343236508978 - glShadeModel(GL_SMOOTH); glMatrixMode(GL_PROJECTION); glPushMatrix(); glTranslated(gui_xoff+shake_pos.x, gui_yoff+shake_pos.y, 0.); - /* Stuff player partially sees. */ + /* Render the puffs. */ + nebu_renderPuffs(dt, 0); + + /* Mask for area player can still see (partially). */ + glShadeModel(GL_SMOOTH); glBegin(GL_TRIANGLE_FAN); ACOLOUR(cPurple, 0.); glVertex2d(0., 0.); @@ -242,10 +286,10 @@ void nebu_renderOverlay(void) { glVertex2d(-nebu_view, 0.); glEnd(); /* GL_TRIANGLE_FAN */ + /* Solid nebulae for areas the player can't see. */ glShadeModel(GL_FLAT); ACOLOUR(cPurple, 1.); - /* Stuff player can't see. */ glBegin(GL_TRIANGLE_FAN); /* Top left. */ glVertex2d(-SCREEN_W/2.-gui_xoff, SCREEN_H/2.-gui_yoff); @@ -296,6 +340,34 @@ void nebu_renderOverlay(void) { #undef SIN225 } +/* Render the puffs. */ +void nebu_renderPuffs(const double dt, int below_player) { + int i; + + glPushMatrix(); /* GL_PROJECTION */ + glTranslated(-(double)SCREEN_W/2., -(double)SCREEN_H/2., 0.); + + for(i = 0; i < nebu_npuffs; i++) { + if((below_player && (nebu_puffs[i].height < 1.)) || + (!below_player && (nebu_puffs[i].height > 1.))) { + + /* Calculate new position. */ + nebu_puffs[i].x -= player->solid->vel.x * nebu_puffs[i].height * dt; + nebu_puffs[i].y -= player->solid->vel.y * nebu_puffs[i].height * dt; + + /* Calculate new alpha. */ + /*nebu_puffs[i].a += nebu_puffs[i].va * dt;*/ + + /* Check boundaries. */ + + /* Render. */ + ACOLOUR(cPurple, nebu_puffs[i].a); + glBegin(GL_QUADS); + glEnd(); /* GL_QUADS */ + } + } +} + /* Prepare the nebulae. */ void nebu_prep(double density, double volatility) { (void)volatility; @@ -305,7 +377,7 @@ void nebu_prep(double density, double volatility) { /* Force generation of new nebulae. */ void nebu_forceGenerate(void) { - nebu_w = nebu_h = -9; + nebu_w = nebu_h = -9; /* Magic numbers. ^.^ */ } /* Generate the nebulae. */ @@ -318,13 +390,13 @@ static void nebu_generate(void) { w = SCREEN_W; h = SCREEN_H; - /* Generate all the nebulae. */ + /* Generate all the nebulae backgrounds. */ nebu = noise_genNebulaeMap(w, h, NEBULAE_Z, 5.); lfile_dirMakeExist("gen"); /* Save each nebulae as an image. */ for(i = 0; i < NEBULAE_Z; i++) { - snprintf(nebu_file, PATH_MAX, NEBULAE_PATH, i); + snprintf(nebu_file, PATH_MAX, NEBULAE_PATH_BG, w, h, i); saveNebulae(&nebu[i*w*h], w, h, nebu_file); } @@ -332,6 +404,33 @@ static void nebu_generate(void) { free(nebu); } +/* Generate the nebulae puffs. */ +static void nebu_generatePuffs(void) { + int i; + int w, h; + SDL_Surface* sur; + float* nebu; + + /* Generate the nebulae puffs. */ + for(i = 0; i < NEBULAE_PUFFS; i++) { + /* Generate the nebulae. */ + w = h = RNG(20, 64); + nebu = noise_genNebulaePuffMap(w, h, 1.); + sur = nebu_surfaceFromNebulaeMap(nebu, w, h); + free(nebu); + + /* Set dimensions. */ + nebu_pufftexs[i].w = w; + nebu_pufftexs[i].h = h; + nebu_pufftexs[i].pw = gl_pot(w); + nebu_pufftexs[i].ph = gl_pot(h); + + /* Actually create the texture. */ + glGenTextures(1, &nebu_pufftexs[i].tex); + nebu_loadTexture(sur, 0, 0, nebu_pufftexs[i].tex); + } +} + /* Check the validity of a nebulae. 0 on success. */ static int nebu_checkCompat(const char* file) { if(lfile_fileExists(file) == 0) /* First check to see if file exists. */ diff --git a/src/nebulae.h b/src/nebulae.h index 4b8b0ea..65256ef 100644 --- a/src/nebulae.h +++ b/src/nebulae.h @@ -6,7 +6,8 @@ void nebu_exit(void); /* Render. */ void nebu_render(void); -void nebu_renderOverlay(void); +void nebu_renderOverlay(const double dt); +void nebu_renderPuffs(const double dt, int below_player); /* Misc. */ void nebu_prep(double density, double volatility); diff --git a/src/perlin.c b/src/perlin.c index 89cc255..703a946 100644 --- a/src/perlin.c +++ b/src/perlin.c @@ -2,6 +2,8 @@ #include #include +#include "SDL.h" + #include "lephisto.h" #include "log.h" #include "rng.h" @@ -239,3 +241,58 @@ float* noise_genNebulaeMap(const int w, const int h, const int n, float rug) { return nebulae; } +/* Generate tiny nebuale puffs */ +float* noise_genNebulaePuffMap(const int w, const int h, float rug) { + int x, y; + float f[3]; + int octaves; + float hurst; + float lacunarity; + perlin_data_t* noise; + float* nebulae; + float value; + float zoom; + float max; + + /* Pretty default values. */ + octaves = 3; + hurst = NOISE_DEFAULT_HURST; + lacunarity = NOISE_DEFAULT_LACUNARITY; + zoom = rug; + + /* Create noise and data. */ + noise = noise_new(hurst, lacunarity); + nebulae = malloc(sizeof(float)*w*h); + if(nebulae == NULL) { + WARN("Out of memory!"); + return NULL; + } + + /* Start to create the nebulae. */ + max = 0.; + f[2] = 0.; + for(y = 0; y < h; y++) { + f[1] = zoom * (float)y / (float)h; + for(x = 0; x < w; x++) { + f[0] = zoom * (float)x / (float)w; + + value = noise_turbulence(noise, f, octaves); + if(max < value) max = value; + + nebulae[y*w + x] = value; + } + } + + /* Post filtering. */ + value = 1. - max; + for(y = 0; y < h; y++) + for(x = 0; x < w; x++) + nebulae[y*w + x] += value; + + /* Clean up. */ + noise_delete(noise); + + /* Results. */ + return nebulae; +} + diff --git a/src/perlin.h b/src/perlin.h index 5db966d..c473674 100644 --- a/src/perlin.h +++ b/src/perlin.h @@ -2,4 +2,5 @@ #include "opengl.h" float* noise_genNebulaeMap(const int w, const int h, const int n, float rug); +float* noise_genNebulaePuffMap(const int w, const int h, float rug); diff --git a/src/space.c b/src/space.c index c92ef30..f1fba39 100644 --- a/src/space.c +++ b/src/space.c @@ -71,7 +71,7 @@ static int mstars = 0; /* Memory stars are taking. */ /* Intern. */ static Planet* planet_pull(const char* name); -static void space_renderStars(double dt); +static void space_renderStars(const double dt); static void space_addFleet(Fleet* fleet); static StarSystem* system_parse(const xmlNodePtr parent); static void system_parseJumps(const xmlNodePtr parent); @@ -805,7 +805,7 @@ int space_load(void) { } /* Render the system. -- Just playing god now. */ -void space_render(double dt) { +void space_render(const double dt) { if(cur_system == NULL) return; if(cur_system->nebu_density > 0.) @@ -815,15 +815,15 @@ void space_render(double dt) { } /* Render the overlay. */ -void space_renderOverlay(void) { +void space_renderOverlay(const double dt) { if(cur_system == NULL) return; if(cur_system->nebu_density > 0.) - nebu_renderOverlay(); + nebu_renderOverlay(dt); } /* Render stars. */ -static void space_renderStars(double dt) { +static void space_renderStars(const double dt) { int i; unsigned int t, timer; double x, y, m, b; @@ -835,7 +835,7 @@ static void space_renderStars(double dt) { t = SDL_GetTicks(); if(!player_isFlag(PLAYER_DESTROYED) && !player_isFlag(PLAYER_CREATING) && pilot_isFlag(player, PILOT_HYPERSPACE) && /* Hyperspace fancy effect. */ - !paused && (player->ptimer-HYPERSPACE_STARS_BLUR < t)) { + (player->ptimer-HYPERSPACE_STARS_BLUR < t)) { timer = player->ptimer - HYPERSPACE_STARS_BLUR; diff --git a/src/space.h b/src/space.h index cc36881..a9ae244 100644 --- a/src/space.h +++ b/src/space.h @@ -120,8 +120,8 @@ char* planet_getSystem(char* planetname); Planet* planet_get(char* planetname); /* Render. */ -void space_render(double dt); -void space_renderOverlay(void); +void space_render(const double dt); +void space_renderOverlay(const double dt); void planets_render(void); /* Update. */