diff --git a/dat/fleet.xml b/dat/fleet.xml index 342588e..e5c1322 100644 --- a/dat/fleet.xml +++ b/dat/fleet.xml @@ -4,7 +4,7 @@ <ai>test</ai> <faction>Independent</faction> <pilots> - <pilot chance='100'>Enemy Test</pilot> + <pilot chance='100' name="Enemy Test">Lancer</pilot> </pilots> </fleet> <fleet name="Merchant Ship"> diff --git a/dat/gui.xml b/dat/gui.xml index b348443..fbe57fb 100644 --- a/dat/gui.xml +++ b/dat/gui.xml @@ -59,42 +59,54 @@ <x>72</x> <y>72</y> </radar> + <nav> + <x>40</x> + <y>151</y> + <w>112</w> + <h>42</h> + </nav> <health> <shield> <w>98</w> <h>8</h> <x>52</x> - <y>186</y> + <y>201</y> </shield> <armor> <w>98</w> <h>8</h> <x>52</x> - <y>197</y> + <y>212</y> </armor> <energy> <w>98</w> <h>8</h> <x>52</x> - <y>207</y> + <y>223</y> </energy> </health> + <weapon> + <x>40</x> + <y>239</y> + <w>112</w> + <h>42</h> + </weapon> <target> <gfx> <x>34</x> - <y>273</y> + <y>304</y> </gfx> <name> <x>40</x> - <y>260</y> + <y>291</y> </name> <faction> <x>40</x> - <y>273</y> + <y>304</y> </faction> <health> <x>40</x> - <y>370</y> + <y>401</y> </health> </target> </gui> diff --git a/dat/ship.xml b/dat/ship.xml index bbda53d..0a5fad6 100644 --- a/dat/ship.xml +++ b/dat/ship.xml @@ -54,10 +54,10 @@ <outfit quantity ='2'>laser</outfit> </outfits> </ship> - <ship name="Enemy Test"> + <ship name="Lancer"> <GFX>ship1</GFX> <GUI>simple</GUI> - <class>1</class> + <class>2</class> <movement> <thrust>180</thrust> <turn>130</turn> diff --git a/gfx/gui/minimal.png b/gfx/gui/minimal.png index c04f083..9f4a620 100644 Binary files a/gfx/gui/minimal.png and b/gfx/gui/minimal.png differ diff --git a/src/opengl.c b/src/opengl.c index 882cbcd..548d821 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -17,6 +17,9 @@ #define FONT_DEF "../gfx/fonts/FreeSans.ttf" +// Default colors. +glColor cGrey = { .r = .75, .g = 0.75, .b = 0.75, .a = 1 }; + // offsets to Adjust the pilot's place onscreen to be in the middle, even with the GUI. extern double gui_xoff; extern double gui_yoff; @@ -38,7 +41,7 @@ static int pot(int n); // gl_texture. static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh); // Gl font. -static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base); +static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base, int* width_base); // ================ // MISC! @@ -437,10 +440,32 @@ void gl_print(const gl_font* ft_font, const Vec2* pos, const glColor* c, const c glDisable(GL_TEXTURE_2D); } +// Get the width of the text about to be printed. +int gl_printWidth(const gl_font* ft_font, const char* fmt, ...) { + int i, n; + char txt[256]; // Holds the string. + va_list ap; + + if(ft_font == NULL) ft_font = &gl_defFont; + + if(fmt == NULL) return 0; + else { + // Convert the symbols to text. + va_start(ap, fmt); + vsprintf(txt, fmt, ap); + va_end(ap); + } + + for(n = 0, i = 0; i < (int)strlen(txt); i++) + n += ft_font->w[(int)txt[i]]; + + return n; +} + // ================ // FONT! // ================ -static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base) { +static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base, int* width_base) { FT_Glyph glyph; FT_Bitmap bitmap; GLubyte* expanded_data; @@ -492,6 +517,9 @@ static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* te double x = (double)bitmap.width/(double)w; double y = (double)bitmap.rows/(double)h; + // Give the width a value. + width_base[(int)ch] = bitmap.width; + // Draw the texture mapped quad. glBindTexture(GL_TEXTURE_2D, tex_base[(int)ch]); glBegin(GL_TRIANGLE_STRIP); @@ -514,14 +542,20 @@ static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* te FT_Done_Glyph(glyph); } -void gl_fontInit(gl_font* font, const char* fname, unsigned int h) { +void gl_fontInit(gl_font* font, const char* fname, const unsigned int h) { if(font == NULL) font = &gl_defFont; uint32_t bufsize; FT_Byte* buf = pack_readfile(DATA, (fname) ? fname : FONT_DEF, &bufsize); + // Allocatagery. font->textures = malloc(sizeof(GLuint)*128); - font->h = h; + font->w = malloc(sizeof(int)*128); + font->h = (int)h; + if(font->textures == NULL || font->w == NULL) { + WARN("Out of memory!"); + return; + } // Create a FreeType font library. FT_Library library; @@ -544,7 +578,7 @@ void gl_fontInit(gl_font* font, const char* fname, unsigned int h) { // Create each of the font display lists. unsigned char i; for(i = 0; i < 128; i++) - gl_fontMakeDList(face, i, font->list_base, font->textures); + gl_fontMakeDList(face, i, font->list_base, font->textures, font->w); // We can now free the face and library. FT_Done_Face(face); @@ -557,6 +591,7 @@ void gl_freeFont(gl_font* font) { glDeleteLists(font->list_base, 128); glDeleteTextures(128, font->textures); free(font->textures); + free(font->w); } // ================ diff --git a/src/opengl.h b/src/opengl.h index 1a03749..edf88af 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -33,6 +33,9 @@ typedef struct { } glColor; #define COLOR(x) glColor4d((x).r, (x).g, (x).b, (x).a) +// Default colors. +extern glColor cGrey; + // Spritesheet info. typedef struct { double w, h; // Real size of the image (excluding POT buffer. @@ -45,7 +48,8 @@ typedef struct { // Font info. typedef struct { - float h; // Height. + int h; // Height. + int* w; GLuint* textures; GLuint list_base; } gl_font; @@ -53,7 +57,7 @@ extern gl_font gl_defFont; // Default font. // gl_font loading/freeing. // If font is NULL it uses the internal default font, same with gl_print -void gl_fontInit(gl_font* font, const char* fname, unsigned int h); +void gl_fontInit(gl_font* font, const char* fname, const unsigned int h); void gl_freeFont(gl_font* font); // gl_texute loading/freeing. @@ -69,6 +73,7 @@ void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, void gl_blitStatic(const gl_texture* texture, const Vec2* pos, const glColor* c); void gl_bindCamera(const Vec2* pos); void gl_print(const gl_font* ft_font, const Vec2* pos, const glColor* c, const char* fmt, ...); +int gl_printWidth(const gl_font* ft_font, const char* fmt, ...); // Initialize/cleanup. int gl_init(void); diff --git a/src/player.c b/src/player.c index e152881..823ef90 100644 --- a/src/player.c +++ b/src/player.c @@ -8,9 +8,6 @@ #include "xml.h" #include "player.h" -#define XML_NODE_START 1 -#define XML_NODE_TEXT 3 - #define XML_GUI_ID "GUIs" // XML section identifier. #define XML_GUI_TAG "gui" @@ -43,7 +40,10 @@ Pilot* player = NULL; // extern in pilot.h static double player_turn = 0.; // Turn velocity from input. static double player_acc = 0.; // Accel velocity from input. static int player_primary = 0; // Player is shooting primary weapon. +static int player_secondary = 0; // layer is shooting secondary weapon. static unsigned int player_target = PLAYER_ID; // Targetted pilot. +static int planet_target = -1; // Targetted planet. +static int weapon = -1; // Secondary weapon is in use. // Pilot stuff for GUI. extern Pilot** pilot_stack; @@ -88,11 +88,16 @@ typedef struct { gl_texture* gfx_frame; gl_texture* gfx_targetPilot, *gfx_targetPlanet; Radar radar; + Rect nav; Rect shield, armor, energy; + Rect weapon; + // Positions. Vec2 pos_frame; Vec2 pos_radar; + Vec2 pos_nav; Vec2 pos_shield, pos_armor, pos_energy; + Vec2 pos_weapon; Vec2 pos_target, pos_target_health, pos_target_name, pos_target_faction; Vec2 pos_msg; } GUI; @@ -225,6 +230,18 @@ void player_render(void) { gui_renderBar(&cArmor, &gui.pos_armor, &gui.armor, player->armor / player->armor_max); gui_renderBar(&cEnergy, &gui.pos_energy, &gui.energy, player->energy / player->energy_max); + // Nav. + if(planet_target != -1) { + + } else { + i = gl_printWidth(NULL, "Nav"); + vect_csetmin(&v, VX(gui.pos_nav) + (gui.nav.w - i)/2., VY(gui.pos_nav) - 5); + gl_print(NULL, &v, &cGrey, "NAV"); + i = gl_printWidth(&gui.smallFont, "No Target"); + vect_csetmin(&v, VX(gui.pos_nav) + (gui.nav.w - i)/2., VY(gui.pos_nav) - 10 - gui.smallFont.h); + gl_print(&gui.smallFont, &v, &cGrey, "No Target"); + } + // Target. if(player_target != PLAYER_ID) { p = pilot_get(player_target); @@ -245,6 +262,17 @@ void player_render(void) { else // On armor. gl_print(&gui.smallFont, &gui.pos_target_health, NULL, "%s: %.0f%%", "Armor", p->armor/p->armor_max*100.); + } + // Weapon. + if(weapon == -1) { + i = gl_printWidth(NULL, "Secondary"); + vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2., VY(gui.pos_weapon) - 5); + gl_print(NULL, &v, &cGrey, "Secondary"); + i = gl_printWidth(&gui.smallFont, "None"); + vect_csetmin(&v, VX(gui.pos_weapon) + (gui.weapon.w - i)/2., VY(gui.pos_weapon) - 10 - gl_defFont.h); + gl_print(&gui.smallFont, &v, &cGrey, "None"); + } else { + } // Messages. VX(v) = VX(gui.pos_msg); @@ -318,6 +346,11 @@ static void gui_renderBar(const glColor* c, const Vec2* p, const Rect* r, const // Init GUI. int gui_init(void) { + // Set graphics to NULL. + gui.gfx_frame = NULL; + gui.gfx_targetPilot = NULL; + gui.gfx_targetPlanet = NULL; + // Font. gl_fontInit(&gui.smallFont, NULL, 10); // -- Radar. @@ -446,12 +479,15 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { tmp = malloc((strlen(tmp2)+strlen(GUI_GFX)+12) * sizeof(char)); // Frame. snprintf(tmp, strlen(tmp2)+strlen(GUI_GFX)+5, GUI_GFX"%s.png", tmp2); + if(gui.gfx_frame) gl_freeTexture(gui.gfx_frame); // Free if needed. gui.gfx_frame = gl_newImage(tmp); // Pilot. snprintf(tmp, strlen(tmp2)+strlen(GUI_GFX)+11, GUI_GFX"%s_pilot.png", tmp2); + if(gui.gfx_targetPilot) gl_freeTexture(gui.gfx_targetPilot); // Free if needed. gui.gfx_targetPilot = gl_newSprite(tmp, 2, 2); // Planet. snprintf(tmp, strlen(tmp2)+strlen(GUI_GFX)+12, GUI_GFX"%s_planet.png", tmp2); + if(gui.gfx_targetPlanet) gl_freeTexture(gui.gfx_targetPlanet); // Free if needed. gui.gfx_targetPlanet = gl_newSprite(tmp, 2, 2); free(tmp); free(tmp2); @@ -490,6 +526,13 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { VX(gui.pos_frame) + x, VY(gui.pos_frame) + gui.gfx_frame->h - y); } + // Nav computer. + else if(xml_isNode(node, "nav")) { + rect_parse(node, &x, &y, &gui.nav.w, &gui.nav.h); + vect_csetmin(&gui.pos_nav, + VX(gui.pos_frame) + x, + VY(gui.pos_frame) + gui.gfx_frame->h - y - gl_defFont.h); + } // Health bars. else if(xml_isNode(node, "health")) { cur = node->children; @@ -516,6 +559,13 @@ static int gui_parse(const xmlNodePtr parent, const char* name) { } } while((cur = cur->next)); } + // Secondary weapon. + else if(xml_isNode(node, "weapon")) { + rect_parse(node, &x, &y, &gui.weapon.w, &gui.weapon.h); + vect_csetmin(&gui.pos_weapon, + VX(gui.pos_frame) + x, + VY(gui.pos_frame) + gui.gfx_frame->h - y - gl_defFont.h); + } // Target. else if(xml_isNode(node, "target")) { cur = node->children; diff --git a/src/ship.h b/src/ship.h index 0c52b32..9454c3a 100644 --- a/src/ship.h +++ b/src/ship.h @@ -8,10 +8,10 @@ #define SHIP_TARGET_H 96 enum ship_class { - SHIP_CLASS_NULL, - SHIP_CLASS_CIV_LIGHT, - SHIP_CLASS_CIV_MEDIUM, - SHIP_CLASS_CIV_HEAVY + SHIP_CLASS_NULL = 0, + SHIP_CLASS_CIV_LIGHT = 1, + SHIP_CLASS_CIV_MEDIUM = 2, + SHIP_CLASS_CIV_HEAVY = 3 }; typedef enum ship_class ship_class;