diff --git a/src/lephisto.c b/src/lephisto.c index 97a75a0..0d2c38d 100644 --- a/src/lephisto.c +++ b/src/lephisto.c @@ -561,7 +561,7 @@ static void render_all(void) { player_render(); spfx_render(SPFX_LAYER_FRONT); space_renderOverlay(dt); - player_renderGUI(); + player_renderGUI(dt); display_fps(dt); /* Exception. */ } diff --git a/src/perlin.c b/src/perlin.c index b2a5913..108f1f4 100644 --- a/src/perlin.c +++ b/src/perlin.c @@ -323,6 +323,60 @@ void noise_delete(perlin_data_t* noise) { free(noise); } +/** + * @brief Generate radar inteference. + * @param w Width to generate. + * @param h Height to generate. + * @param rug Rugosity of the interference. + * @return The map generated. + */ +float* noise_genRadarInt(const int w, const int h, float rug) { + int x, y; + float f[2]; + int octaves; + float hurst; + float lacunarity; + perlin_data_t* noise; + float* map; + float value; + + /* Pretty default values. */ + octaves = 3; + hurst = NOISE_DEFAULT_HURST; + lacunarity = NOISE_DEFAULT_LACUNARITY; + + /* Create noise and data. */ + noise = noise_new(2, hurst, lacunarity); + map = malloc(sizeof(float)*w*h); + if(map == NULL) { + WARN("Out of memory!"); + return NULL; + } + + /* Start to create the nebulae. */ + for(y = 0; y < h; y++) { + + f[1] = rug * (float)y / (float)h; + for(x = 0; x < w; x++) { + + f[0] = rug * (float)x / (float)w; + + /* Get the 2d noise. */ + value = noise_get2(noise, f); + + /* Set the value to [0, 1]. */ + map[y*w + x] = (value + 1.) / 2.; + } + } + + /* Clean up. */ + noise_delete(noise); + + /* Results. */ + return map; + +} + /** * @brief Generate a 3d nebulae map. * @param w Width of the map. diff --git a/src/perlin.h b/src/perlin.h index c473674..f869c74 100644 --- a/src/perlin.h +++ b/src/perlin.h @@ -1,6 +1,7 @@ #pragma once #include "opengl.h" +float* nouse_genRadarInt(const int w, const int h, float rug); 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/player.c b/src/player.c index c41b073..c64a762 100644 --- a/src/player.c +++ b/src/player.c @@ -32,6 +32,7 @@ #include "unidiff.h" #include "comm.h" #include "intro.h" +#include "perlin.h" #include "player.h" #define XML_GUI_ID "GUIs" /**< XML section identifier for GUI document. */ @@ -51,6 +52,9 @@ #define PLAYER_ENGINE_CHANNEL 9 /**< Player channel for engine noises. */ #define PLAYER_GUI_CHANNEL 9 /**< Player channel. */ +#define INTERFERENCE_LAYERS 16 /**< Number of interference layers. */ +#define INTERFERENCE_CHANGE_DT 0.1 /**< Speed to change at. */ + /* Player stuff. */ Pilot* player = NULL; /**< The player. */ static Ship* player_ship = NULL; /**< Temp ship to hold when naming it. */ @@ -90,6 +94,10 @@ int hyperspace_target = -1; /**< Target hyperspace route. -1 is none /* For death etc. */ static unsigned int player_timer = 0; /**< For death and such. */ static Vec2 player_cam; /**< Again, for death etc. */ +/* For interference. */ +static int interference_layer = 5; /**< Layer of the current interference. */ +static double interference_alpha = 0.; /**< Alpha of the current interference layer. */ +static double interference_t = 0.; /**< Interference timer to control transitions. */ static int* missions_done = NULL; /**< Saves position of completed missions. */ static int missions_mdone = 0; /**< Memory size of completed missions. */ @@ -117,6 +125,7 @@ typedef struct Radar_ { double h; /**< Height. */ RadarShape shape; /**< Shape. */ double res; /**< Resolution. */ + glTexture* interference[INTERFERENCE_LAYERS]; /**< Interference texture. */ } Radar; /* Radar res. */ @@ -218,14 +227,17 @@ static void player_newShipMake(char* name); /* Sound. */ static void player_initSound(void); /* Gui. */ +static void gui_createInterference(void); static void rect_parseParam(const xmlNodePtr parent, char* name, double* param); static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w, double* h); static int gui_parse(const xmlNodePtr parent, const char* name); +static void gui_cleanup(void); +/* Render GUI. */ static void gui_renderPilot(const Pilot* p); static void gui_renderHealth(const glColour* c, const Rect* r, const glTexture* tex, const double w); -static void gui_cleanup(void); +static void gui_renderInterference(double dt); /* Save/Load. */ static int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc); static int player_parse(xmlNodePtr parent); @@ -846,7 +858,6 @@ void player_renderBG(void) { * * @brief Render the player. */ -static int can_jump = 0; /**< Store whether or not the player is able to jump. */ void player_render(void) { Pilot* p; glColour* c; @@ -884,12 +895,11 @@ void player_render(void) { } } +static int can_jump = 0; /**< Store whether or not the player is able to jump. */ /** - * @fn void player_renderGUI(void) - * * @brief Render the players GUI. */ -void player_renderGUI(void) { +void player_renderGUI(double dt) { int i, j; double x, y; char str[10]; @@ -947,16 +957,15 @@ void player_renderGUI(void) { planets_minimap(gui.radar.res, gui.radar.w, gui.radar.h, gui.radar.shape); /* Weapons. */ - glBegin(GL_POINTS); - COLOUR(cRadar_weap); weapon_minimap(gui.radar.res, gui.radar.w, gui.radar.h, gui.radar.shape); - glEnd(); - /* Render the pilots. */ - for(j = 0, i = 1; i < pilot_nstack; i++) { - /* Skip the player. */ - if(pilot_stack[i]->id == player->target) j = i; - else gui_renderPilot(pilot_stack[i]); + /* Render the pilot_nstack. */ + j = 0; + for(i = 1; i < pilot_nstack; i++) { /* Skip the player. */ + if(pilot_stack[i]->id == player->target) + j = i; + else + gui_renderPilot(pilot_stack[i]); } /* Render the targetted pilot. */ if(j != 0) gui_renderPilot(pilot_stack[j]); @@ -972,6 +981,9 @@ void player_renderGUI(void) { glPopMatrix(); /* GL_PROJECTION. */ + /* Interference. */ + gui_renderInterference(dt); + /* Nav. */ if(planet_target >= 0) { /* Planet landing target. */ @@ -1187,6 +1199,45 @@ void player_renderGUI(void) { } } +/** + * @brief Render interference if needed. + * @param dt Current deltatick. + */ +static void gui_renderInterference(double dt) { + glColour c; + glTexture* tex; + int t; + + /* Must be displaying inteference. */ + if(interference_alpha <= 0.) + return; + + /* Calculate frame to draw. */ + interference_t += dt; + if(interference_t > INTERFERENCE_CHANGE_DT) { /* Time to change. */ + t = RNG(0, INTERFERENCE_LAYERS-1); + if(t != interference_layer) + interference_layer = t; + else + interference_layer = (interference_layer == INTERFERENCE_LAYERS-1) ? + 0 : interference_layer+1; + interference_t -= INTERFERENCE_CHANGE_DT; + } + + /* Render the interference. */ + c.r = c.g = c.b = 1.; + c.a = interference_alpha; + tex = gui.radar.interference[interference_layer]; + if(gui.radar.shape == RADAR_CIRCLE) + gl_blitStatic(tex, + gui.radar.x - gui.radar.w, + gui.radar.y - gui.radar.w, &c); + else if(gui.radar.shape == RADAR_RECT) + gl_blitStatic(tex, + gui.radar.x - gui.radar.w / 2, + gui.radar.y - gui.radar.h/2, &c); +} + /* Renders a pilot. */ static void gui_renderPilot(const Pilot* p) { int x, y, sx, sy; @@ -1427,9 +1478,86 @@ static void rect_parse(const xmlNodePtr parent, rect_parseParam(parent, "y", y); } +/** + * @brief Create the interference map for the current gui. + */ +static void gui_createInterference(void) { + uint8_t raw; + int i, j, k; + float* map; + uint32_t* pix; + SDL_Surface* sur; + int w, h, hw, hh; + float c; + int r; + + /* Dimension shortcuts. */ + if(gui.radar.shape == RADAR_CIRCLE) { + w = gui.radar.w*2.; + h = w; + } + else if(gui.radar.shape == RADAR_RECT) { + w = gui.radar.w; + h = gui.radar.h; + } + + for(k = 0; k < INTERFERENCE_LAYERS; k++) { + /* Free the old texture. */ + if(gui.radar.interference[k] != NULL) + gl_freeTexture(gui.radar.interference[k]); + + /* Create the temp surface. */ + sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBAMASK); + pix = sur->pixels; + + /* Load the interference map. */ + map = noise_genRadarInt(w, h, 100.); + + /* Create the texture. */ + SDL_LockSurface(sur); + if(gui.radar.shape == RADAR_CIRCLE) { + r = pow2((int)gui.radar.w); + hw = w/2; + hh = h/2; + for(i = 0; i < h; i++) { + for(j = 0; j < w; j++) { + /* Must be in circle. */ + if(pow2(i-hh) + pow2(j-hw) > r) + continue; + c = map[i*w + j]; + raw = 0xff & (uint8_t)((float)0xff * c); + memset(&pix[i*w + j], raw, sizeof(uint32_t)); + pix[i*w + j] |= AMASK; + } + } + } + else if(gui.radar.shape == RADAR_RECT) { + for(i = 0; i < h*w; i++) { + /* Process pixels. */ + c = map[i]; + raw = 0xff & (uint8_t)((float)0xff * c); + memset(&pix[i], raw, sizeof(uint32_t)); + pix[i] |= AMASK; + } + } + SDL_UnlockSurface(sur); + + /* Set the interference. */ + gui.radar.interference[k] = gl_loadImage(sur); + + /* Clean up. */ + free(map); + } +} + /* Parse a gui node. */ #define RELATIVIZE(a) \ { (a).x += VX(gui.frame); (a).y = VY(gui.frame) + gui.gfx_frame->h-(a).y; } +/** + * @brief Parses a gui node. + * @param Parent node to parse from. + * @param name Name of the GUI to load. + */ static int gui_parse(const xmlNodePtr parent, const char* name) { xmlNodePtr cur, node; char* tmp, buf[PATH_MAX]; @@ -1582,7 +1710,10 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { rect_parse(node, &gui.misc.x, &gui.misc.y, &gui.misc.w, &gui.misc.h); RELATIVIZE(gui.misc); } - } while((node = node->next)); + } while(xml_nextNode(node)); + + /* Some postprocessing. */ + gui_createInterference(); return 0; } @@ -1592,6 +1723,8 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { * @brief Clean up the GUI. */ static void gui_cleanup(void) { + int i; + /* Free textures. */ if(gui.gfx_frame != NULL) { gl_freeTexture(gui.gfx_frame); @@ -1622,6 +1755,13 @@ static void gui_cleanup(void) { gl_freeTexture(gui.gfx_fuel); gui.gfx_fuel = NULL; } + + for(i = 0; i < INTERFERENCE_LAYERS; i++) { + if(gui.radar.interference[i] != NULL) { + gl_freeTexture(gui.radar.interference[i]); + gui.radar.interference[i] = NULL; + } + } } /** diff --git a/src/player.h b/src/player.h index e2469e0..bd348a7 100644 --- a/src/player.h +++ b/src/player.h @@ -44,7 +44,7 @@ int gui_init(void); void gui_free(void); void player_render(void); void player_renderBG(void); /* Render BG layer. */ -void player_renderGUI(void); /* Render the GUI stuff. */ +void player_renderGUI(double dt); /* Render the GUI stuff. */ /* Misc. */ void player_message(const char* fmt, ...); diff --git a/src/space.c b/src/space.c index 0979aab..5e60b67 100644 --- a/src/space.c +++ b/src/space.c @@ -103,7 +103,7 @@ int space_sysLoad(xmlNodePtr parent); /* Draw the planet. Used in planet.c */ /* Matrix mode is already displaced to center of the minimap. */ #define PIXEL(x,y) if((shape == RADAR_RECT && ABS(x)solid->pos.x - player->solid->pos.x) / res; y = (wbackLayer[i]->solid->pos.y - player->solid->pos.y) / res; @@ -139,6 +145,9 @@ void weapon_minimap(const double res, const double w, y = (wfrontLayer[i]->solid->pos.y - player->solid->pos.y) / res; PIXEL(x,y); } + + /* End the points. */ + glEnd(); } #undef PIXEL