Implement drawlist updating for increasing y

This commit is contained in:
Camden Dixie O'Brien 2025-01-04 12:26:32 +00:00
parent 9325563991
commit f3c9d6ac30

View File

@ -87,6 +87,15 @@ typedef enum {
ENTITY_OBJ, ENTITY_OBJ,
} entitytag_t; } entitytag_t;
/*
* Common entity header -- this must be at the start of each type of
* entity structure.
*
* The tag is used to distinguish different types of entity when
* accessing them through the drawlist. The prev and next pointers
* allow the drawlist to be threaded through all entities as a
* doubly-linked list.
*/
typedef struct entity { typedef struct entity {
entitytag_t tag; entitytag_t tag;
struct entity *prev; struct entity *prev;
@ -559,6 +568,87 @@ static inline bool tile_passable(const map_t map, int x, int y)
return true; return true;
} }
static inline int dynentity_bottom(dynentity_t *e)
{
return e->pos.y + e->ext.y / 2;
}
static inline int objentity_bottom(objentity_t *e)
{
return e->pos.y;
}
static inline int entity_bottom(entity_t *e)
{
switch (e->tag) {
case ENTITY_DYN:
return dynentity_bottom((dynentity_t *)e);
case ENTITY_OBJ:
return objentity_bottom((objentity_t *)e);
}
}
static void update_drawlist(dynentity_t *e, entity_t **drawlist)
{
if (e->dir.y == 0)
return;
if (e->dir.y > 0) {
// The entity moved down -- check if it needs to be moved
// along in the drawlist.
entity_t *n = e->e.next;
if (n == NULL)
// The entity is already at the end -- no update required.
return;
const int y = dynentity_bottom(e);
int nexty = entity_bottom(n);
if (y <= nexty)
// The entity is still behind the next entity -- no update
// required.
return;
// Update required -- find the earliest entity that is in
// front of e, or the end of the list.
while (n->next != NULL && y > nexty) {
n = n->next;
nexty = entity_bottom(n);
}
assert(n != NULL);
if (y > nexty) {
// The end of the list was reached without finding a
// larger or equal y -- move the entity to the end of the
// list (after n).
e->e.prev->next = e->e.next;
e->e.next->prev = e->e.prev;
e->e.prev = n;
e->e.next = NULL;
n->next = (entity_t *)e;
} else {
// An entity with greater or equal y was found -- move the
// entity to just before n.
if (e->e.prev == NULL) {
// The entity is at the beginning of the list, we need
// to update the drawlist pointer.
*drawlist = e->e.next;
e->e.next->prev = NULL;
} else {
e->e.prev->next = e->e.next;
e->e.next->prev = e->e.prev;
}
e->e.prev = n->prev;
e->e.next = n;
n->prev->next = (entity_t *)e;
n->prev = (entity_t *)e;
}
}
}
static void update_dynentity(gamestate_t *state, dynentity_t *e, double dt) static void update_dynentity(gamestate_t *state, dynentity_t *e, double dt)
{ {
if (0 == e->speed) { if (0 == e->speed) {
@ -602,6 +692,8 @@ static void update_dynentity(gamestate_t *state, dynentity_t *e, double dt)
if (valid) { if (valid) {
e->pos.x = nextx; e->pos.x = nextx;
e->pos.y = nexty; e->pos.y = nexty;
update_drawlist(e);
} }
} }