Construct drawlist at end of game_init()

This commit is contained in:
Camden Dixie O'Brien 2025-01-04 09:26:42 +00:00
parent 8763c437b3
commit 56dbf9dbb4

View File

@ -51,6 +51,9 @@
#define MAXOBJTYPES 8
#define INITOBJCOLCAP 16
#define MAXENTITIES 32
#define QSORT_STACKSIZE 64
#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
@ -128,8 +131,14 @@ typedef struct {
objtype_t objtypes[MAXOBJTYPES];
objcol_t objcol;
dynentity_t p;
entity_t *drawlist;
} gamestate_t;
typedef struct {
int y;
entity_t *e;
} y_entity_ref_t;
const engineconf_t game_conf = {
.win = {
.title = "2D Game",
@ -339,6 +348,72 @@ load_map(gamestate_t *state, const char *path, SDL_Renderer *renderer)
xmlFreeDoc(doc);
}
static void y_entity_ref_swap(y_entity_ref_t *a, y_entity_ref_t *b)
{
y_entity_ref_t tmp = *a;
*a = *b;
*b = tmp;
}
void init_drawlist(gamestate_t *state)
{
y_entity_ref_t buf[MAXENTITIES];
int n = 0;
// Populate buffer with player and objects
buf[n].y = (int)rint(state->p.pos.y) + state->p.ext.y / 2;
buf[n++].e = (entity_t *)&state->p;
for (unsigned i = 0; i < state->objcol.n; ++i) {
assert(n < MAXENTITIES);
objentity_t *obj = state->objcol.buf + i;
buf[n].y = obj->pos.y;
buf[n++].e = (entity_t *)obj;
}
// Quicksort on y value
int stack[QSORT_STACKSIZE], *sp = stack;
int l = 0, h = n;
assert(n != 0);
while (1) {
int pivot = buf[l].y;
int i = l, j = h;
do {
for (++i; buf[i].y <= pivot; ++i)
;
for (--j; buf[j].y > pivot; --j)
;
if (i < j)
y_entity_ref_swap(buf + i, buf + j);
} while (i < j);
y_entity_ref_swap(buf + l, buf + j);
assert(sp + 2 <= stack + QSORT_STACKSIZE);
if (j + 2 < h) {
*sp++ = j + 1;
*sp++ = h;
}
if (l + 1 < j) {
h = j;
} else if (sp != stack) {
h = *(--sp);
l = *(--sp);
} else {
break;
}
}
// Set up drawlist from buffer
state->drawlist = buf[0].e;
int i = 0;
buf[i].e->prev = NULL;
buf[i].e->next = buf[i + 1].e;
for (++i; i < n - 1; ++i) {
buf[i].e->prev = buf[i - 1].e;
buf[i].e->next = buf[i + 1].e;
}
buf[i].e->prev = buf[i - 1].e;
buf[i].e->next = NULL;
}
void game_init(int argc, char *argv[], void *mem, SDL_Renderer *renderer)
{
char path[MAX_PATH_LEN];
@ -389,6 +464,8 @@ void game_init(int argc, char *argv[], void *mem, SDL_Renderer *renderer)
state->p.ext.x = PWIDTH;
state->p.ext.y = PHEIGHT;
state->p.tex = state->pidle;
init_drawlist(state);
}
void game_teardown(void *mem)