From 376eedc616094db6c81e8ddf0f1c90f0ccc91648 Mon Sep 17 00:00:00 2001 From: Allanis <allanis@saracraft.net> Date: Mon, 4 Feb 2013 09:09:04 +0000 Subject: [PATCH] [Add] Star systems. [Add] Planets. --- bin/Makefile | 2 +- dat/planet.xml | 4 +- dat/ssys.xml | 8 +- gfx/planet/konosphere.png | Bin 0 -> 17592 bytes gfx/planet/saracraft.png | Bin 0 -> 17592 bytes src/ai.c | 2 +- src/joystick.c | 2 +- src/main.c | 7 +- src/{def.h => main.h} | 2 +- src/opengl.c | 2 +- src/pack.c | 8 +- src/pack.h | 10 +- src/physics.h | 2 +- src/pilot.c | 2 +- src/pilot.h | 2 +- src/player.c | 2 +- src/ship.c | 30 ++-- src/ship.h | 2 +- src/space.c | 296 +++++++++++++++++++++++++++++++++++++- src/space.h | 7 +- utils/pack/main.c | 2 +- 21 files changed, 335 insertions(+), 57 deletions(-) create mode 100644 gfx/planet/konosphere.png create mode 100644 gfx/planet/saracraft.png rename src/{def.h => main.h} (80%) 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 @@ <tech>0</tech> <commodities>1</commodities> </general> - <GFX>KonoSphere</GFX> + <GFX>konosphere.png</GFX> </planet> <planet name="SaraCraft"> <pos> @@ -24,6 +24,6 @@ <tech>0</tech> <commodities>1</commodities> </general> - <GFX>SaraCraft</GFX> + <GFX>saracraft.png</GFX> </planet> </Planets> 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 @@ <y>8</y> </pos> <general> - <stars>50</stars> + <stars>500</stars> <asteroids>0</asteroids> <interference>0</interference> <faction>2</faction> @@ -22,9 +22,6 @@ <fleet chance="50">Sml Merchant Convoy</fleet> <fleet chance="40">Sml Merchant Convoy</fleet> </fleets> - <paths> - <path>KonoSys</path> - </paths> </ssys> <ssys name="KonoSys"> <pos> @@ -44,8 +41,5 @@ <fleet chance="80">Merchant Ship</fleet> <fleet chance="60">Merchant Ship</fleet> </fleets> - <paths> - <path>SaraSys</path> - </paths> </ssys> </Systems> diff --git a/gfx/planet/konosphere.png b/gfx/planet/konosphere.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccb16dccd686601cbaa767614059033c42d4ff GIT binary patch literal 17592 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 literal 0 HcmV?d00001 diff --git a/gfx/planet/saracraft.png b/gfx/planet/saracraft.png new file mode 100644 index 0000000000000000000000000000000000000000..20ccb16dccd686601cbaa767614059033c42d4ff GIT binary patch literal 17592 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 literal 0 HcmV?d00001 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 <math.h> -#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 <SDL.h> #include <string.h> -#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 <string.h> #include <getopt.h> -#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 <stdarg.h> #include <string.h> -#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 <stdlib.h> #include <assert.h> -#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 <malloc.h> -#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 <string.h> -#include <libxml/xmlreader.h> +#include <libxml/parser.h> +#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 <libxml/parser.h> #include <malloc.h> #include <math.h> @@ -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);