refactored tilemap_load to use tiled xml format

This commit is contained in:
Sara 2023-09-22 17:12:00 +02:00
parent b9e4599d7e
commit 661af077b2
2 changed files with 77 additions and 36 deletions

View file

@ -1,54 +1,95 @@
#include "tilemap.h" #include "tilemap.h"
#include "libxml/threads.h"
#include "libxml/tree.h"
#include "libxml/xmlstring.h"
#include "program.h" #include "program.h"
#include <SDL2/SDL_image.h> #include <SDL2/SDL_image.h>
#include <libxml/xinclude.h>
#include <stdio.h> #include <stdio.h>
struct Tilemap tilemap_load(const char* tilemap_file, const char* tileset_file) { #define XML(__str) (const xmlChar*)__str
static inline
void tilemap_get_size_from_xml(xmlNodePtr node, int* o_width, int* o_height) {
xmlChar* prop = xmlGetProp(node, XML("width"));
if(prop == NULL) { printf("Nu-uh\n"); return; }
*o_width = atoi((char*)prop);
prop = xmlGetProp(node, XML("height"));
if(prop == NULL) { printf("Nu-uh\n"); return; }
*o_height = atoi((char*)prop);
}
static inline
void tilemap_get_tiles_from_xml(xmlDoc* doc, xmlNodePtr node, int* out, int out_len) {
node = node->children;
while(xmlStrcmp(node->name, XML("data")) != 0 && node != NULL) {
node = node->next;
}
if(node == NULL) {
memset(out, 0x0, out_len * sizeof(int));
return;
}
char buffer[5]; buffer[4] = '\0';
char* buffer_writer = buffer;
int* out_writer = out;
xmlChar* str = xmlNodeGetContent(node);
xmlChar* reader = str;
while(*reader != '\0') {
while(isspace(*reader))
reader++;
if(*reader != ',' && *reader != '\0') {
*buffer_writer = (char)*reader;
++buffer_writer;
} else {
*buffer_writer = '\0';
buffer_writer = buffer;
*out_writer = atoi(buffer) - 1;
++out_writer;
}
++reader;
}
}
struct Tilemap tilemap_load(const char* tilemap_file) {
struct Tilemap self = { struct Tilemap self = {
.dimensions = {1,1}, .dimensions = {1,1},
.tiles = NULL .tiles = NULL
}; };
FILE* fs = fopen(tilemap_file, "r"); xmlDocPtr doc = xmlParseFile(tilemap_file);
int n = 0; if(doc == NULL) {
do { printf("Failed to load tilemap file '%s'\n", tilemap_file);
n = fgetc(fs); self.dimensions.x = self.dimensions.y = 0;
if(n == ',') { return self;
self.dimensions.x++; }
}
} while(n != '\n');
do {
n = fgetc(fs);
if(n == '\n') {
self.dimensions.y++;
}
} while(n != '\0');
rewind(fs); xmlNodePtr reader = xmlDocGetRootElement(doc);
if(reader == NULL) {
printf("Failed to find map node in tilemap '%s'\n", tilemap_file);
self.dimensions.x = self.dimensions.y = 0;
xmlFreeDoc(doc);
return self;
}
self.tiles = malloc(self.dimensions.x * self.dimensions.y * sizeof(int)); reader = reader->children;
char csv_buffer[6];
csv_buffer[5] = '\0';
char* writer = csv_buffer;
int* tile = self.tiles;
do { do {
n = fgetc(fs); if(xmlStrcmp(reader->name, XML("layer")) == 0) {
if(isalnum(n)) { tilemap_get_size_from_xml(reader, &self.dimensions.x, &self.dimensions.y);
*writer = n; printf("sizes: %d %d\n", self.dimensions.x, self.dimensions.y);
++writer; self.tiles = malloc(self.dimensions.x * self.dimensions.y * sizeof(int));
} else if(n == ',' || n == '\0' || n == '\n') { printf("reading layer data\n");
*writer = '\0'; tilemap_get_tiles_from_xml(doc, reader, self.tiles, self.dimensions.x * self.dimensions.y);
writer = csv_buffer; } else if(xmlStrcmp(reader->name, XML("objectgroup"))) {
*tile = atoi(csv_buffer);
++tile;
} }
} while(n != '\0'); reader = reader->next;
} while(reader != NULL);
fclose(fs); xmlFreeDoc(doc);
self.tileset = tileset_load(tileset_file);
return self; return self;
} }

View file

@ -18,7 +18,7 @@ struct Tilemap {
struct Tileset tileset; struct Tileset tileset;
}; };
extern struct Tilemap tilemap_load(const char* tilemap_file, const char* tileset_file); extern struct Tilemap tilemap_load(const char* tilemap_file);
extern struct Tileset tileset_load(const char* filename); extern struct Tileset tileset_load(const char* filename);
extern SDL_Rect tileset_index_to_rect(struct Tileset* self, size_t index); extern SDL_Rect tileset_index_to_rect(struct Tileset* self, size_t index);