Implement TMX map loading

This commit is contained in:
Camden Dixie O'Brien 2024-12-26 20:00:42 +00:00
parent 57a9b20449
commit c0fc016b85
3 changed files with 95 additions and 4 deletions

View File

@ -4,6 +4,7 @@ project(epec-mcu-emulator LANGUAGES C)
option(TESTS "Build unit tests" ON) option(TESTS "Build unit tests" ON)
option(WERROR "Treat warnings as errors" OFF) option(WERROR "Treat warnings as errors" OFF)
option(SANITIZERS "Enable memory and undefined behaviour sanitizers" OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -14,6 +15,10 @@ macro(set_default_target_options target)
if (${WERROR}) if (${WERROR})
target_compile_options(${target} PRIVATE -Werror) target_compile_options(${target} PRIVATE -Werror)
endif() endif()
if (${SANITIZERS})
target_compile_options(${target} PRIVATE -fsanitize=memory,undefined)
target_link_options(${target} PRIVATE -fsanitize=memory,undefined)
endif()
endmacro() endmacro()
add_custom_target(format add_custom_target(format
@ -29,6 +34,7 @@ add_custom_target(lint
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
) )
find_package(LibXml2 REQUIRED)
find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2 SDL2main) find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2 SDL2main)
add_subdirectory(engine) add_subdirectory(engine)

View File

@ -5,4 +5,4 @@ set_default_target_options(game)
target_include_directories(game PUBLIC include) target_include_directories(game PUBLIC include)
target_link_libraries(game target_link_libraries(game
PRIVATE SDL2::SDL2 SDL2::SDL2main) PRIVATE LibXml2::LibXml2 SDL2::SDL2 SDL2::SDL2main)

View File

@ -5,16 +5,32 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <assert.h> #include <assert.h>
#include <ctype.h>
#include <libxml/parser.h>
#define TILESIZE 32 #define TILESIZE 32
#define WINWIDTH 30 #define WINWIDTH 30
#define WINHEIGHT 20 #define WINHEIGHT 20
SDL_Window *window; #define MAX_PATH_LEN 128
SDL_Renderer *renderer;
int main(void) #define MAP_ASSET "/map.tmx"
#define MAPWIDTH 112
#define MAPHEIGHT 112
#define MAPSHIFTX 48
#define MAPSHIFTY 48
static SDL_Window *window;
static SDL_Renderer *renderer;
static unsigned map[MAPWIDTH][MAPHEIGHT];
int main(int argc, char *argv[])
{ {
if (2 != argc) {
fprintf(stderr, "Usage: %s ASSETS-DIR\n", argv[0]);
return 1;
}
int err = SDL_Init(SDL_INIT_VIDEO); int err = SDL_Init(SDL_INIT_VIDEO);
assert(0 == err); assert(0 == err);
window = SDL_CreateWindow( window = SDL_CreateWindow(
@ -24,6 +40,75 @@ int main(void)
renderer = SDL_CreateRenderer(window, -1, 0); renderer = SDL_CreateRenderer(window, -1, 0);
assert(NULL != renderer); assert(NULL != renderer);
xmlDocPtr doc;
xmlNodePtr node;
char mappath[MAX_PATH_LEN];
strncpy(mappath, argv[1], MAX_PATH_LEN);
strncat(mappath, MAP_ASSET, MAX_PATH_LEN);
doc = xmlParseFile(mappath);
assert(NULL != doc);
node = xmlDocGetRootElement(doc);
assert(0 == xmlStrcmp(node->name, (const xmlChar *)"map"));
node = node->xmlChildrenNode;
while (NULL != node
&& xmlStrcmp(node->name, (const xmlChar *)"layer") != 0)
node = node->next;
assert(NULL != node);
node = node->xmlChildrenNode;
while (NULL != node
&& xmlStrcmp(node->name, (const xmlChar *)"data") != 0)
node = node->next;
assert(NULL != node);
xmlNodePtr chunk_contents;
for (node = node->xmlChildrenNode; NULL != node; node = node->next) {
if (0 != xmlStrcmp(node->name, (const xmlChar *)"chunk"))
continue;
xmlChar *x_attr, *y_attr;
x_attr = xmlGetProp(node, (const xmlChar *)"x");
y_attr = xmlGetProp(node, (const xmlChar *)"y");
const int chunk_x = atoi((const char *)x_attr);
const int chunk_y = atoi((const char *)y_attr);
chunk_contents = node->xmlChildrenNode;
assert(
0 == xmlStrcmp(chunk_contents->name, (const xmlChar *)"text"));
int x = chunk_x + MAPSHIFTX, y = chunk_y + MAPSHIFTY;
xmlChar buf[10];
const xmlChar *p, *q;
q = chunk_contents->content;
while (isspace((const char)*q))
++q;
p = q;
while ('\0' != *q) {
switch (*q) {
case (xmlChar)',':
memset(buf, 0, sizeof(buf));
memcpy(buf, p, sizeof(xmlChar) * (q - p));
assert(x < MAPWIDTH && y < MAPHEIGHT);
map[x][y] = (unsigned)atoi((const char *)buf);
++x;
p = ++q;
break;
case (xmlChar)'\n':
if (x < MAPWIDTH) {
memset(buf, 0, sizeof(buf));
memcpy(buf, p, sizeof(xmlChar) * (q - p));
assert(y < MAPHEIGHT);
map[x][y] = (unsigned)atoi((const char *)buf);
}
x = chunk_x + MAPSHIFTX;
++y;
p = ++q;
break;
default:
++q;
break;
}
}
}
SDL_Event event; SDL_Event event;
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
while (1) { while (1) {