Add support for map objects
This commit is contained in:
parent
12751a49f8
commit
cbb4b7884c
154
app/main.c
154
app/main.c
@ -48,6 +48,9 @@
|
|||||||
|
|
||||||
#define BASEANIMPERIOD 100
|
#define BASEANIMPERIOD 100
|
||||||
|
|
||||||
|
#define MAXOBJTYPES 8
|
||||||
|
#define INITOBJCOLCAP 16
|
||||||
|
|
||||||
#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
|
#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -85,6 +88,22 @@ typedef struct {
|
|||||||
SDL_Rect src;
|
SDL_Rect src;
|
||||||
} entity_t;
|
} 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 const char *assetdir;
|
||||||
static SDL_Window *window;
|
static SDL_Window *window;
|
||||||
static SDL_Renderer *renderer;
|
static SDL_Renderer *renderer;
|
||||||
@ -96,6 +115,8 @@ static const unsigned impassable[] = {
|
|||||||
284, 485, 486, 525, 527, 566, 567, 731,
|
284, 485, 486, 525, 527, 566, 567, 731,
|
||||||
768, 770, 771, 804, 805, 806, 808, 845,
|
768, 770, 771, 804, 805, 806, 808, 845,
|
||||||
};
|
};
|
||||||
|
static objtype_t objtypes[MAXOBJTYPES];
|
||||||
|
static objcol_t objcol;
|
||||||
|
|
||||||
static inline double mag(dvec_t v)
|
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)
|
static void mapload(const char *path)
|
||||||
{
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
@ -197,14 +313,14 @@ static void mapload(const char *path)
|
|||||||
node = xmlDocGetRootElement(doc);
|
node = xmlDocGetRootElement(doc);
|
||||||
assert(0 == xmlStrcmp(node->name, (const xmlChar *)"map"));
|
assert(0 == xmlStrcmp(node->name, (const xmlChar *)"map"));
|
||||||
node = node->xmlChildrenNode;
|
node = node->xmlChildrenNode;
|
||||||
for (int l = 0; l < MAPNLAYERS; ++l) {
|
int layer = 0;
|
||||||
do
|
|
||||||
node = node->next;
|
|
||||||
while (NULL != node
|
|
||||||
&& xmlStrcmp(node->name, (const xmlChar *)"layer") != 0);
|
|
||||||
assert(NULL != node);
|
assert(NULL != node);
|
||||||
maploadlayer(node, l);
|
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)
|
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.x = e->animstep.x * frame + e->svarstep.x * e->svar;
|
||||||
e->src.y = e->animstep.y * frame + e->svarstep.y * e->svar;
|
e->src.y = e->animstep.y * frame + e->svarstep.y * e->svar;
|
||||||
SDL_Rect dest = {
|
SDL_Rect dest = {
|
||||||
.x = SCALE * (int)(e->pos.x - vpos.x - e->src.w / 2),
|
.x = SCALE * (e->pos.x - vpos.x - e->src.w / 2),
|
||||||
.y = SCALE * (int)(e->pos.y - vpos.y - e->src.h / 2),
|
.y = SCALE * (e->pos.y - vpos.y - e->src.h / 2),
|
||||||
.w = SCALE * e->src.w,
|
.w = SCALE * e->src.w,
|
||||||
.h = SCALE * e->src.h,
|
.h = SCALE * e->src.h,
|
||||||
};
|
};
|
||||||
SDL_RenderCopy(renderer, e->tex, &e->src, &dest);
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char path[MAX_PATH_LEN];
|
char path[MAX_PATH_LEN];
|
||||||
@ -436,6 +571,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
mapdraw();
|
mapdraw();
|
||||||
|
objsdraw(t);
|
||||||
entitydraw(&p, t);
|
entitydraw(&p, t);
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user