Add support for map objects
This commit is contained in:
parent
12751a49f8
commit
cbb4b7884c
156
app/main.c
156
app/main.c
@ -48,6 +48,9 @@
|
||||
|
||||
#define BASEANIMPERIOD 100
|
||||
|
||||
#define MAXOBJTYPES 8
|
||||
#define INITOBJCOLCAP 16
|
||||
|
||||
#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
typedef enum {
|
||||
@ -85,6 +88,22 @@ typedef struct {
|
||||
SDL_Rect src;
|
||||
} entity_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned animframes;
|
||||
SDL_Rect src;
|
||||
SDL_Texture *tex;
|
||||
} objtype_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned type;
|
||||
ivec_t pos;
|
||||
} obj_t;
|
||||
|
||||
typedef struct {
|
||||
size_t n, cap;
|
||||
obj_t *buf;
|
||||
} objcol_t;
|
||||
|
||||
static const char *assetdir;
|
||||
static SDL_Window *window;
|
||||
static SDL_Renderer *renderer;
|
||||
@ -96,6 +115,8 @@ static const unsigned impassable[] = {
|
||||
284, 485, 486, 525, 527, 566, 567, 731,
|
||||
768, 770, 771, 804, 805, 806, 808, 845,
|
||||
};
|
||||
static objtype_t objtypes[MAXOBJTYPES];
|
||||
static objcol_t objcol;
|
||||
|
||||
static inline double mag(dvec_t v)
|
||||
{
|
||||
@ -188,6 +209,101 @@ static void maploadlayer(xmlNodePtr layernode, int layeridx)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned objtypeload(const char *templ)
|
||||
{
|
||||
static char buf[MAX_PATH_LEN];
|
||||
assert(strlen(assetdir) + strlen(templ) + 1 < MAX_PATH_LEN);
|
||||
strcpy(buf, assetdir);
|
||||
strcat(buf, "/");
|
||||
strcat(buf, templ);
|
||||
|
||||
// Identify object type ID
|
||||
xmlDocPtr doc = xmlParseFile(buf);
|
||||
assert(NULL != doc);
|
||||
xmlNodePtr node = xmlDocGetRootElement(doc);
|
||||
assert(NULL != node);
|
||||
assert(xmlStrcmp(node->name, (const xmlChar *)"template") == 0);
|
||||
node = node->xmlChildrenNode;
|
||||
while (node != NULL
|
||||
&& xmlStrcmp(node->name, (const xmlChar *)"object") != 0)
|
||||
node = node->next;
|
||||
assert(NULL != node);
|
||||
unsigned id
|
||||
= atoi((const char *)xmlGetProp(node, (const xmlChar *)"gid"));
|
||||
assert(id < MAXOBJTYPES);
|
||||
|
||||
// Populate objtype struct if not already loaded
|
||||
if (NULL == objtypes[id].tex) {
|
||||
objtypes[id].src.x = 0;
|
||||
objtypes[id].src.y = 0;
|
||||
objtypes[id].src.w
|
||||
= atoi((const char *)xmlGetProp(node, (const xmlChar *)"width"));
|
||||
objtypes[id].src.h = atoi(
|
||||
(const char *)xmlGetProp(node, (const xmlChar *)"height"));
|
||||
|
||||
node = node->xmlChildrenNode;
|
||||
while (node != NULL
|
||||
&& xmlStrcmp(node->name, (const xmlChar *)"properties") != 0)
|
||||
node = node->next;
|
||||
assert(NULL != node);
|
||||
for (node = node->xmlChildrenNode; NULL != node; node = node->next) {
|
||||
if (xmlStrcmp(node->name, (const xmlChar *)"property") != 0)
|
||||
continue;
|
||||
const char *key
|
||||
= (const char *)xmlGetProp(node, (const xmlChar *)"name");
|
||||
const char *val
|
||||
= (const char *)xmlGetProp(node, (const xmlChar *)"value");
|
||||
if (strcmp(key, "animframes") == 0) {
|
||||
objtypes[id].animframes = atoi(val);
|
||||
} else if (strcmp(key, "assetpath") == 0) {
|
||||
assert(strlen(assetdir) + strlen(val) < MAX_PATH_LEN);
|
||||
strcpy(buf, assetdir);
|
||||
strcat(buf, val);
|
||||
objtypes[id].tex = IMG_LoadTexture(renderer, buf);
|
||||
assert(NULL != objtypes[id].tex);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static void maploadobjects(xmlNodePtr node)
|
||||
{
|
||||
objcol.n = 0;
|
||||
objcol.cap = INITOBJCOLCAP;
|
||||
objcol.buf = malloc(sizeof(obj_t) * objcol.cap);
|
||||
assert(objcol.buf);
|
||||
|
||||
node = node->xmlChildrenNode;
|
||||
assert(NULL != node);
|
||||
do {
|
||||
if (xmlStrcmp(node->name, (const xmlChar *)"object") != 0)
|
||||
continue;
|
||||
|
||||
// Get slot for object, growing buffer if needed.
|
||||
if (objcol.n == objcol.cap) {
|
||||
objcol.cap *= 2;
|
||||
objcol.buf = realloc(objcol.buf, sizeof(obj_t) * objcol.cap);
|
||||
assert(objcol.buf);
|
||||
}
|
||||
obj_t *o = &objcol.buf[objcol.n++];
|
||||
|
||||
// Load object type
|
||||
const xmlChar *templ = xmlGetProp(node, (const xmlChar *)"template");
|
||||
assert(NULL != templ);
|
||||
o->type = objtypeload((const char *)templ);
|
||||
|
||||
// Load object location and set size from objtype
|
||||
o->pos.x
|
||||
= atoi((const char *)xmlGetProp(node, (const xmlChar *)"x"));
|
||||
o->pos.y
|
||||
= atoi((const char *)xmlGetProp(node, (const xmlChar *)"y"));
|
||||
} while ((node = node->next) != NULL);
|
||||
}
|
||||
|
||||
static void mapload(const char *path)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
@ -197,14 +313,14 @@ static void mapload(const char *path)
|
||||
node = xmlDocGetRootElement(doc);
|
||||
assert(0 == xmlStrcmp(node->name, (const xmlChar *)"map"));
|
||||
node = node->xmlChildrenNode;
|
||||
for (int l = 0; l < MAPNLAYERS; ++l) {
|
||||
do
|
||||
node = node->next;
|
||||
while (NULL != node
|
||||
&& xmlStrcmp(node->name, (const xmlChar *)"layer") != 0);
|
||||
assert(NULL != node);
|
||||
maploadlayer(node, l);
|
||||
}
|
||||
int layer = 0;
|
||||
assert(NULL != node);
|
||||
do {
|
||||
if (xmlStrcmp(node->name, (const xmlChar *)"layer") == 0)
|
||||
maploadlayer(node, layer++);
|
||||
else if (xmlStrcmp(node->name, (const xmlChar *)"objectgroup") == 0)
|
||||
maploadobjects(node);
|
||||
} while ((node = node->next) != NULL);
|
||||
}
|
||||
|
||||
static void mapdraw(void)
|
||||
@ -279,14 +395,33 @@ static void entitydraw(entity_t *e, uint64_t t)
|
||||
e->src.x = e->animstep.x * frame + e->svarstep.x * e->svar;
|
||||
e->src.y = e->animstep.y * frame + e->svarstep.y * e->svar;
|
||||
SDL_Rect dest = {
|
||||
.x = SCALE * (int)(e->pos.x - vpos.x - e->src.w / 2),
|
||||
.y = SCALE * (int)(e->pos.y - vpos.y - e->src.h / 2),
|
||||
.x = SCALE * (e->pos.x - vpos.x - e->src.w / 2),
|
||||
.y = SCALE * (e->pos.y - vpos.y - e->src.h / 2),
|
||||
.w = SCALE * e->src.w,
|
||||
.h = SCALE * e->src.h,
|
||||
};
|
||||
SDL_RenderCopy(renderer, e->tex, &e->src, &dest);
|
||||
}
|
||||
|
||||
static void objsdraw(uint64_t t)
|
||||
{
|
||||
for (unsigned i = 0; i < objcol.n; ++i) {
|
||||
const obj_t *obj = &objcol.buf[i];
|
||||
assert(obj->type < MAXOBJTYPES);
|
||||
const objtype_t *type = &objtypes[obj->type];
|
||||
assert(NULL != type->tex);
|
||||
SDL_Rect src = type->src;
|
||||
src.x += type->src.w * ((t / BASEANIMPERIOD) % type->animframes);
|
||||
SDL_Rect dest = {
|
||||
.x = SCALE * (obj->pos.x - vpos.x),
|
||||
.y = SCALE * (obj->pos.y - vpos.y - type->src.h),
|
||||
.w = SCALE * type->src.w,
|
||||
.h = SCALE * type->src.h,
|
||||
};
|
||||
SDL_RenderCopy(renderer, type->tex, &src, &dest);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char path[MAX_PATH_LEN];
|
||||
@ -436,6 +571,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
mapdraw();
|
||||
objsdraw(t);
|
||||
entitydraw(&p, t);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user