Extract map logic into functions

This commit is contained in:
Camden Dixie O'Brien 2024-12-31 13:15:57 +00:00
parent b39189b6d1
commit 8de374bcfb

View File

@ -122,6 +122,103 @@ static inline bool tilepassable(int x, int y)
return true;
}
static void mapload(const char *path)
{
// Find chunk nodes in map XML
xmlDocPtr doc;
xmlNodePtr node;
doc = xmlParseFile(path);
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);
// Iterate through chunks and populate map array.
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;
}
}
}
}
static void mapdraw(void)
{
const int startx = TILESIZE * floor(vpos.x / TILESIZE);
const int starty = TILESIZE * floor(vpos.y / TILESIZE);
for (int y = starty; y < vpos.y + VIEWHEIGHT; y += TILESIZE) {
for (int x = startx; x < vpos.x + VIEWWIDTH; x += TILESIZE) {
const unsigned tileid = tileat(x, y);
if (0 == tileid)
continue;
const SDL_Rect src = {
.x = TILESIZE * ((tileid - 1) % TSCOLS),
.y = TILESIZE * ((tileid - 1) / TSCOLS),
.w = TILESIZE,
.h = TILESIZE,
};
const SDL_Rect dest = {
.x = SCALE * (x - vpos.x),
.y = SCALE * (y - vpos.y),
.w = SCALE * TILESIZE,
.h = SCALE * TILESIZE,
};
SDL_RenderCopy(renderer, tstex, &src, &dest);
}
}
}
static void entityupdate(entity_t *e, double dt)
{
if (0 == e->speed)
@ -193,76 +290,11 @@ int main(int argc, char *argv[])
renderer = SDL_CreateRenderer(window, -1, 0);
assert(NULL != renderer);
// Find chunk nodes in map XML
xmlDocPtr doc;
xmlNodePtr node;
// Load map
assert(strlen(argv[1]) + strlen(MAP_ASSET) < MAX_PATH_LEN);
strcpy(path, argv[1]);
strcat(path, MAP_ASSET);
doc = xmlParseFile(path);
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);
// Iterate through chunks and populate map array.
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;
}
}
}
mapload(path);
// Load tileset
assert(strlen(argv[1]) + strlen(TSASSET) < MAX_PATH_LEN);
@ -354,7 +386,7 @@ int main(int argc, char *argv[])
break;
}
// Calculate and apply velocity
// Calculate player velocity and update player
p.dir.x = (input.left ? -1 : 0) + (input.right ? 1 : 0);
p.dir.y = (input.up ? -1 : 0) + (input.down ? 1 : 0);
const double dmag = mag(p.dir);
@ -386,34 +418,8 @@ int main(int argc, char *argv[])
}
SDL_RenderClear(renderer);
// Draw map
const int startx = TILESIZE * floor(vpos.x / TILESIZE);
const int starty = TILESIZE * floor(vpos.y / TILESIZE);
for (int y = starty; y < vpos.y + VIEWHEIGHT; y += TILESIZE) {
for (int x = startx; x < vpos.x + VIEWWIDTH; x += TILESIZE) {
const unsigned tileid = tileat(x, y);
if (0 == tileid)
continue;
const SDL_Rect src = {
.x = TILESIZE * ((tileid - 1) % TSCOLS),
.y = TILESIZE * ((tileid - 1) / TSCOLS),
.w = TILESIZE,
.h = TILESIZE,
};
const SDL_Rect dest = {
.x = SCALE * (x - vpos.x),
.y = SCALE * (y - vpos.y),
.w = SCALE * TILESIZE,
.h = SCALE * TILESIZE,
};
SDL_RenderCopy(renderer, tstex, &src, &dest);
}
}
// Draw player
mapdraw();
entitydraw(&p, t);
SDL_RenderPresent(renderer);
}