diff --git a/bin/Makefile b/bin/Makefile index 422d80d..de4299e 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -31,7 +31,7 @@ LDFLAGS = -lm $(LDLUA) $(LDSDL) $(LDXML) $(LDTTF) $(LDGL) DATA = data DATAFILES = $(shell find ../scripts/ai/ ../gfx/ ../dat/ -name '*.lua' -o -name '*.png' -o -name '*.xml') -%.o: %.c +%.o: %.c %.h @gcc -c $(CFLAGS) -o $@ $< @echo -e "\tCC $@" diff --git a/dat/planet.xml b/dat/planet.xml index 34d4d29..71834f0 100644 --- a/dat/planet.xml +++ b/dat/planet.xml @@ -11,7 +11,7 @@ 0 1 - KonoSphere + konosphere.png @@ -24,6 +24,6 @@ 0 1 - SaraCraft + saracraft.png diff --git a/dat/ssys.xml b/dat/ssys.xml index 85fdb37..a3b8a56 100644 --- a/dat/ssys.xml +++ b/dat/ssys.xml @@ -6,7 +6,7 @@ 8 - 50 + 500 0 0 2 @@ -22,9 +22,6 @@ Sml Merchant Convoy Sml Merchant Convoy - - KonoSys - @@ -44,8 +41,5 @@ Merchant Ship Merchant Ship - - SaraSys - diff --git a/gfx/planet/konosphere.png b/gfx/planet/konosphere.png new file mode 100644 index 0000000..20ccb16 Binary files /dev/null and b/gfx/planet/konosphere.png differ diff --git a/gfx/planet/saracraft.png b/gfx/planet/saracraft.png new file mode 100644 index 0000000..20ccb16 Binary files /dev/null and b/gfx/planet/saracraft.png differ diff --git a/src/ai.c b/src/ai.c index b747830..a813470 100644 --- a/src/ai.c +++ b/src/ai.c @@ -5,7 +5,7 @@ #include -#include "def.h" +#include "main.h" #include "log.h" #include "pilot.h" #include "physics.h" diff --git a/src/joystick.c b/src/joystick.c index 5649a31..96e9293 100644 --- a/src/joystick.c +++ b/src/joystick.c @@ -1,6 +1,6 @@ #include #include -#include "def.h" +#include "main.h" #include "log.h" #include "joystick.h" diff --git a/src/main.c b/src/main.c index f1ff217..432d4f8 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ #include #include -#include "def.h" +#include "main.h" #include "log.h" #include "physics.h" #include "opengl.h" @@ -196,11 +196,12 @@ int main(int argc, char** argv) { // Data loading. ships_load(); + space_load(); // Testing. pilot_create(get_ship("Ship"), "Player", NULL, NULL, PILOT_PLAYER); gl_bindCamera(&player->solid->pos); - space_init(); + space_init("SaraSys"); pilot_create(get_ship("Test"), NULL, NULL, NULL, 0); @@ -264,6 +265,8 @@ static void update_all(void) { glClear(GL_COLOR_BUFFER_BIT); space_render(dt); + planets_render(); + pilots_update(dt); display_fps(dt); diff --git a/src/def.h b/src/main.h similarity index 80% rename from src/def.h rename to src/main.h index afd8def..1d24a79 100644 --- a/src/def.h +++ b/src/main.h @@ -5,5 +5,5 @@ #define ABS(X) ((X<0)?-X:X) -#define DATA "data" +#define DATA "data" // Data file. diff --git a/src/opengl.c b/src/opengl.c index af6d91b..efd0648 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -7,7 +7,7 @@ #include #include -#include "def.h" +#include "main.h" #include "log.h" #include "pack.h" #include "opengl.h" diff --git a/src/pack.c b/src/pack.c index bdb72de..d1760c2 100644 --- a/src/pack.c +++ b/src/pack.c @@ -53,7 +53,7 @@ static off_t getfilesize(const char* filename) { } // Return true if filename is a Packfile. -int pack_check(char* filename) { +int pack_check(const char* filename) { int fd = open(filename, O_RDONLY); if(fd == -1) { ERR("Error opening %s: %s", filename, strerror(errno)); @@ -77,7 +77,7 @@ int pack_check(char* filename) { ERR("Error writing to file: %s", strerror(errno)); \ free(buf); return -1; } -int pack_files(char* outfile, char** infiles, uint32_t nfiles) { +int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles) { void* buf; struct stat file; int i, namesize; @@ -162,7 +162,7 @@ int pack_files(char* outfile, char** infiles, uint32_t nfiles) { #define READ(f,b,n) if(read(f,b,n) != n) { \ ERR("Too few bytes read. Expected more."); \ free(buf); return -1; } -int pack_open(Packfile* file, char* packfile, char* filename) { +int pack_open(Packfile* file, const char* packfile, const char* filename) { int i, j; uint32_t nfiles; char* buf = (char*)malloc(MAX_FILENAME); @@ -237,7 +237,7 @@ ssize_t pack_read(Packfile* file, void* buf, size_t count) { } // Loads an entire file into memory and returns a pointer to it. -void* pack_readfile(char* packfile, char* filename, uint32_t* filesize) { +void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize) { Packfile* file = (Packfile*)malloc(sizeof(Packfile)); void* buf; int size, bytes; diff --git a/src/pack.h b/src/pack.h index 596b519..c35d08e 100644 --- a/src/pack.h +++ b/src/pack.h @@ -11,12 +11,12 @@ typedef struct { // Packfile manipulation. Automatically allocated and freed (with open and close). // Basic. -int pack_check(char* filename); -int pack_files(char* outfile, char** infiles, uint32_t nfiles); -int pack_open(Packfile* file, char* packfile, char* filename); -ssize_t pack_read(Packfile* file, void* buf, size_t count); +int pack_check(const char* filename); +int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles); +int pack_open(Packfile* file, const char* packfile, const char* filename); +ssize_t pack_read(Packfile* file, void* buf, const size_t count); int pack_close(Packfile* file); // Fancy stuff. -void* pack_readfile(char* packfile, char* filename, uint32_t* filesize); +void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesize); diff --git a/src/physics.h b/src/physics.h index e47ead4..77f6e28 100644 --- a/src/physics.h +++ b/src/physics.h @@ -1,5 +1,5 @@ #pragma once -#include "def.h" +#include "main.h" #define VX(v) ((v).x) #define VY(v) ((v).y) diff --git a/src/pilot.c b/src/pilot.c index 7e3b484..180f76d 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -3,7 +3,7 @@ #include #include -#include "def.h" +#include "main.h" #include "log.h" #include "pilot.h" diff --git a/src/pilot.h b/src/pilot.h index 16f75d7..65e0d07 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -1,5 +1,5 @@ #pragma once -#include "def.h" +#include "main.h" #include "physics.h" #include "ai.h" #include "ship.h" diff --git a/src/player.c b/src/player.c index 6ec1aac..2736bc6 100644 --- a/src/player.c +++ b/src/player.c @@ -1,5 +1,5 @@ #include -#include "def.h" +#include "main.h" #include "pilot.h" #include "log.h" #include "player.h" diff --git a/src/ship.c b/src/ship.c index 60f7c05..af8be5f 100644 --- a/src/ship.c +++ b/src/ship.c @@ -1,16 +1,15 @@ #include -#include +#include +#include "main.h" #include "log.h" #include "pack.h" #include "ship.h" -#define MAX_PATH_NAME 20 // Maximum size of the path. +#define MAX_PATH_NAME 30 // Maximum size of the path. #define XML_NODE_START 1 #define XML_NODE_TEXT 3 -#define XML_NODE_CLOSE 15 -#define XML_NODE_CDATA 4 #define XML_ID "Ships" // XML section identifier. #define XML_SHIP "ship" @@ -125,42 +124,39 @@ Ship* ship_parse(xmlNodePtr parent) { } int ships_load(void) { - xmlNodePtr node; - uint32_t bufsize; char* buf = pack_readfile(DATA, SHIP_DATA, &bufsize); + + xmlNodePtr node; xmlDocPtr doc = xmlParseMemory(buf, bufsize); Ship* tmp = NULL; node = doc->xmlChildrenNode; // Ships node. if(strcmp((char*)node->name, XML_ID)) { - ERR("Malformed ships xml file: missing tag %s", XML_ID); + ERR("Malformed "SHIP_DATA" file: missing root element '"XML_ID"'"); return -1; } node = node->xmlChildrenNode; // First ship node. if(node == NULL) { - ERR("Malformed ships xml file: is missing ships"); + ERR("Malformed "SHIP_DATA" file: Does not contain elements"); return -1; } do { if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_SHIP)==0) { - if(ship_stack == NULL) { - ship_stack = tmp = ship_parse(node); - ships = 1; - } else { - tmp = ship_parse(node); - ship_stack = realloc(ship_stack, sizeof(Ship)*(++ships)); - memcpy(ship_stack+ships-1, tmp, sizeof(Ship)); - free(tmp); - } + tmp = ship_parse(node); + ship_stack = realloc(ship_stack, sizeof(Ship)*(++ships)); + memcpy(ship_stack+ships-1, tmp, sizeof(Ship)); + free(tmp); } } while((node = node->next)); xmlFreeDoc(doc); free(buf); + xmlCleanupParser(); + return 0; } diff --git a/src/ship.h b/src/ship.h index c6a7119..e998a45 100644 --- a/src/ship.h +++ b/src/ship.h @@ -1,5 +1,5 @@ #pragma once -#include "def.h" +#include "main.h" #include "opengl.h" enum ship_class { SHIP_CLASS_NULL, SHIP_CLASS_CIVILIAN }; diff --git a/src/space.c b/src/space.c index f92ab51..c7b7006 100644 --- a/src/space.c +++ b/src/space.c @@ -1,3 +1,4 @@ +#include #include #include @@ -6,20 +7,98 @@ #include "opengl.h" #include "rng.h" #include "pilot.h" +#include "pack.h" #include "space.h" +#define MAX_PATH_NAME 30 // Max size of the path. + +#define XML_NODE_START 1 +#define XML_NODE_TEST 3 + +#define XML_PLANET_ID "Planets" +#define XML_PLANET_TAG "planet" + +#define XML_SYSTEM_ID "Systems" +#define XML_SYSTEM_TAG "ssys" + +#define PLANET_DATA "../dat/planet.xml" +#define SPACE_DATA "../dat/ssys.xml" + +#define PLANET_GFX "../gfx/planet/" + +// Planet types. I didn't take them from Star Trek, I promise. +typedef enum { + PLANET_CLASS_A, // Geothermal. + PLANET_CLASS_B, // Geomorteus. + PLANET_CLASS_C, // Geoinactive. + PLANET_CLASS_D, // Asteroid/Moon. + PLANET_CLASS_E, // Geoplastic. + PLANET_CLASS_F, // Geometallic. + PLANET_CLASS_G, // GroCrystaline. + PLANET_CLASS_H, // Desert. + PLANET_CLASS_I, // Gas Supergiant. + PLANET_CLASS_J, // Gas Giant. + PLANET_CLASS_K, // Adaptable. + PLANET_CLASS_L, // Marginal. + PLANET_CLASS_M, // Terrestrial. + PLANET_CLASS_N, // Reducing. + PLANET_CLASS_O, // Pelagic. + PLANET_CLASS_P, // Glaciated. + PLANET_CLASS_Q, // Variable. + PLANET_CLASS_R, // Rogue. + PLANET_CLASS_S, // Ultragiant. + PLANET_CLASS_T, // Ultragiant. + PLANET_CLASS_X, // Demon. + PLANET_CLASS_Y, // Demon. + PLANER_CLASS_Z // Demon. +} PlanetClass; + +typedef struct { + char* name; + double x, y; // Position in star system. + PlanetClass class; + gl_texture* gfx_space; // Graphics in space. +} Planet; + +typedef struct { + char* name; + double x, y; // Position. + int stars, asteroids; // Un numero! + double interference; // Un uh.. Percentage. + + // Factions. + Planet* planets; // Planets. + int nplanets; + + // TODO: Throw some fleets here. +} StarSystem; + +static StarSystem* systems = NULL; +static int nsystems = 0; +static StarSystem* cur_system = NULL; // Current star system. + #define STAR_BUF 100 // Area to leave around screen. typedef struct { - double x, y; + double x, y; // Position. It is simpler ligher to use two doubles than the physics. double brightness; } Star; -Star* stars; -int nstars; +static Star* stars = NULL; // Star array. +static int nstars = 0; // Total stars. -void space_init(void) { +static Planet* planet_get(const char* name); +static StarSystem* system_parse(const xmlNodePtr parent); + +// Init the system. +void space_init(const char* sysname) { int i; - nstars = (500*gl_screen.w*gl_screen.h + STAR_BUF*STAR_BUF)/(800*640);; + for(i = 0; i < nsystems; i++) + if(strcmp(sysname, systems[i].name)==0) + break; + if(i == nsystems) ERR("System %s not found in stack", sysname); + cur_system = systems++; + + nstars = (cur_system->stars*gl_screen.w*gl_screen.h+STAR_BUF*STAR_BUF)/(800*640); stars = malloc(sizeof(Star)*nstars); for(i = 0; i < nstars; i++) { stars[i].brightness = (double)RNG(50, 200)/256.; @@ -28,6 +107,186 @@ void space_init(void) { } } +// Load the planets of name 'name'. +static Planet* planet_get(const char* name) { + Planet* tmp = NULL; + + char str[MAX_PATH_NAME] = "\0"; + + uint32_t bufsize; + char* buf = pack_readfile(DATA, PLANET_DATA, &bufsize); + + xmlNodePtr node, cur; + xmlDocPtr doc = xmlParseMemory(buf, bufsize); + + node = doc->xmlChildrenNode; + if(strcmp((char*)node->name, XML_PLANET_ID)) { + ERR("Malformed "PLANET_DATA" file: missing root element '"XML_PLANET_ID"'"); + return NULL; + } + + node = node->xmlChildrenNode; // First system node. + if(node == NULL) { + ERR("Malformed "PLANET_DATA" file: does not contain elements"); + return NULL; + } + + do { + if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_PLANET_TAG)==0) { + if(strcmp((char*)xmlGetProp(node, (xmlChar*)"name"), name)==0) { // Found. + tmp = CALLOC_L(Planet); + tmp->name = strdup(name); + + node = node->xmlChildrenNode; + + while((node = node->next)) { + if(strcmp((char*)node->name, "GFX")==0) { + cur = node->children; + if(strcmp((char*)cur->name, "text")==0) { + snprintf(str, strlen((char*)cur->content)+sizeof(PLANET_GFX), + PLANET_GFX"%s", (char*)cur->content); + tmp->gfx_space = gl_newSprite(str, 1, 1); + } + } + else if(strcmp((char*)node->name, "pos")==0) { + cur = node->children; + while((cur = cur->next)) { + if(strcmp((char*)cur->name, "x")==0) + tmp->x = atof((char*)cur->children->content); + else if(strcmp((char*)cur->name, "y")==0) + tmp->y = atof((char*)cur->children->content); + } + } + else if(strcmp((char*)node->name, "general")==0) { + cur = node->children; + while((cur = cur->next)) { + if(strcmp((char*)cur->name, "class")==0) + tmp->class = atoi((char*)cur->children->content); + } + } + } + break; + } + } + } while((node = node->next)); + + xmlFreeDoc(doc); + free(buf); + xmlCleanupParser(); + + // Check elements. + if(tmp) { +#define MELEMENT(o,s) if(o == 0) WARN("Planet '%s' missing '"s"' element", tmp->name) + MELEMENT(tmp->x, "x"); + MELEMENT(tmp->x, "y"); + MELEMENT(tmp->class, "class"); +#undef MELEMENT + } else + WARN("No planet found matching name '%s'", name); + + return tmp; +} + +// Parse node 'parent' which should be the node of a system. +// Return the StarSystem fully loaded. +static StarSystem* system_parse(const xmlNodePtr parent) { + Planet* planet = NULL; + StarSystem* tmp = CALLOC_L(StarSystem); + xmlNodePtr cur, node; + + tmp->name = strdup((char*) xmlGetProp(parent, (xmlChar*)"name")); + + node = parent->xmlChildrenNode; + + while((node = node->next)) { + // Load all the things! + if(strcmp((char*)node->name, "pos")==0) { + cur = node->children; + while((cur = cur->next)) { + if(strcmp((char*)cur->name, "x")==0) + tmp->x = atof((char*)cur->children->content); + if(strcmp((char*)cur->name, "y")==0) + tmp->y = atof((char*)cur->children->content); + } + } + else if(strcmp((char*)node->name, "general")==0) { + cur = node->children; + while((cur = cur->next)) { + if(strcmp((char*)cur->name, "stars")==0) + tmp->stars = atoi((char*)cur->children->content); + else if(strcmp((char*)cur->name, "asteroids")==0) + tmp->asteroids = atoi((char*)cur->children->content); + else if(strcmp((char*)cur->name, "interference")==0) + tmp->interference = atof((char*)cur->children->content); + } + } + else if(strcmp((char*)node->name, "planets")==0) { + cur = node->children; + while((cur = cur->next)) { + if(strcmp((char*)cur->name, "planet")==0) { + planet = planet_get((const char*)cur->children->content); + tmp->planets = realloc(tmp->planets, sizeof(Planet)*(++tmp->nplanets)); + memcpy(tmp->planets+tmp->nplanets-1, planet, sizeof(Planet)); + free(planet); + } + } + } + } + // Check elements. +#define MELEMENT(o,s) if(o == 0) WARN("Star System '%s' missing '"s"' element", tmp->name) + MELEMENT(tmp->x, "x"); + MELEMENT(tmp->x, "y"); + MELEMENT(tmp->stars, "stars"); + /*MELEMENT(tmp->asteroids, "asteroids"); // Can be 0. + MELEMENT(tmp->interference, "interference");*/ +#undef MELEMENT + DEBUG("Loaded Star System '%s' with %d Planets%s", tmp->name, tmp->nplanets, (tmp->nplanets > 1) ? "s" : ""); + + return tmp; +} + +// Load the ENTIRE universe into RAM. -- WOAH! -- Wasn't that bad. :P +int space_load(void) { + uint32_t bufsize; + char* buf = pack_readfile(DATA, SPACE_DATA, &bufsize); + + StarSystem* tmp; + + xmlNodePtr node; + xmlDocPtr doc = xmlParseMemory(buf, bufsize); + + node = doc->xmlChildrenNode; + if(strcmp((char*)node->name, XML_SYSTEM_ID)) { + ERR("Malformed "SPACE_DATA" file: missing root element '"XML_SYSTEM_ID"'"); + return -1; + } + node = node->xmlChildrenNode; // First system node. + if(node == NULL) { + ERR("Malformed "SPACE_DATA" file: does not contain elements"); + return -1; + } + do { + if(node->type == XML_NODE_START && strcmp((char*)node->name, XML_SYSTEM_TAG)==0) { + if(systems == NULL) { + systems = tmp = system_parse(node); + nsystems = 1; + } else { + tmp = system_parse(node); + systems = realloc(systems, sizeof(StarSystem)*(++nsystems)); + memcpy(systems+nsystems-1, tmp, sizeof(StarSystem)); + free(tmp); + } + } + } while((node = node->next)); + + xmlFreeDoc(doc); + free(buf); + xmlCleanupParser(); + + return 0; +} + +// Render the system. -- Just playing god now. void space_render(double dt) { int i; glMatrixMode(GL_PROJECTION); @@ -51,7 +310,30 @@ void space_render(double dt) { glPopMatrix(); // Projection translation matrix. } -void space_exit(void) { - free(stars); +// Render the planets. +void planets_render(void) { + int i; + Vec2 v; + for(i = 0; i < cur_system->nplanets; i++) { + v.x = cur_system->planets[i].x; + v.y = cur_system->planets[i].y; + gl_blitSprite(cur_system->planets[i].gfx_space, &v, 0, 0); + } +} + +// Clean up the system. +void space_exit(void) { + int i,j; + for(i = 0; i < nsystems; i++) { + free(systems[i].name); + for(j = 0; j < systems[i].nplanets; j++) { + free(systems[i].planets[j].name); + if(systems[i].planets[j].gfx_space) + gl_freeTexture(systems[i].planets[j].gfx_space); + } + free(systems[i].planets); + } + free(systems); + if(stars) free(stars); } diff --git a/src/space.h b/src/space.h index 1314f72..d4f77e9 100644 --- a/src/space.h +++ b/src/space.h @@ -1,8 +1,11 @@ #pragma once -#include "def.h" -void space_init(void); +// Load/Exit. +void space_init(const char* sysname); +int space_load(void); void space_exit(void); +// Render. void space_render(double dt); +void planets_render(void); diff --git a/utils/pack/main.c b/utils/pack/main.c index db463b0..f92a76f 100644 --- a/utils/pack/main.c +++ b/utils/pack/main.c @@ -19,7 +19,7 @@ int main(int argc, char** argv) { uint32_t nfiles = (uint32_t)argc - 2; argv += 2; - pack_files(outfile, argv, nfiles); + pack_files(outfile, (const char**)argv, nfiles); exit(EXIT_SUCCESS);