RogueLife/src/comp/entity.h

89 lines
3.1 KiB
C

//---
// entity: Varied objects in the game, implemented with components
//
// This game runs on an Entity-Component system. Entities uniquely identify a
// variety of game objects, ranging from players and enemies to skills' areas
// of effect, item drops, spawn regions...
//
// Entities themselves are fairly empty, and most of their properties are
// defined through components. For instance, the [physical] component assigns a
// in space and a hitbox; the [visible] component gives sprites and rendering
// properties; the [mechanical] component provides controlled motion.
//---
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
typedef struct
{
/* Deletion flag - deletions are delayed until end of frame to ease
management of dangling references */
uint32_t deleted: 1;
/* Bitmask of components in that entity (see ENTITY_COMP_*) */
uint32_t comps: 31;
/* Pointer to components; one pointer per non-zero entry in [comps],
starting from LSB to MSB */
void *data[];
} entity_t;
/* Bit field values for each type of component */
#define ENTITY_COMP_physical 0x00000001
#define ENTITY_COMP_visible 0x00000002
#define ENTITY_COMP_mechanical 0x00000004
#define ENTITY_COMP_fighter 0x00000008
#define ENTITY_COMP_aoe 0x00000010
#define ENTITY_COMP_particle 0x00000020
/* Maximum number of components */
#define ENTITY_COMP_CAPACITY 31
/* Get a component from an entity */
static inline void *getcomp(entity_t const *e, uint32_t comp)
{
if(__builtin_expect(!(e->comps & comp), 0))
return NULL;
int i = 0;
while(comp) i += (e->comps & (comp >>= 1)) != 0;
return e->data[i];
}
/* Write "getcomp(e, physical)" */
#define getcomp(e, comp) ((comp ## _t *)getcomp(e, ENTITY_COMP_ ## comp))
/* Create an entity with a fixed set of components */
entity_t *entity_make(uint32_t comp);
/* Variation of entity_make() with up to 6 variable arguments */
#define ENTITY_MAKE_ARGS1(type, ...) \
ENTITY_COMP_##type __VA_OPT__(| ENTITY_MAKE_ARGS(__VA_ARGS__))
#define ENTITY_MAKE_ARGS2(type, ...) \
ENTITY_COMP_##type __VA_OPT__(| ENTITY_MAKE_ARGS1(__VA_ARGS__))
#define ENTITY_MAKE_ARGS3(type, ...) \
ENTITY_COMP_##type __VA_OPT__(| ENTITY_MAKE_ARGS2(__VA_ARGS__))
#define ENTITY_MAKE_ARGS4(type, ...) \
ENTITY_COMP_##type __VA_OPT__(| ENTITY_MAKE_ARGS3(__VA_ARGS__))
#define ENTITY_MAKE_ARGS5(type, ...) \
ENTITY_COMP_##type __VA_OPT__(| ENTITY_MAKE_ARGS4(__VA_ARGS__))
#define ENTITY_MAKE_ARGS6(type, ...) \
ENTITY_COMP_##type __VA_OPT__(| ENTITY_MAKE_ARGS5(__VA_ARGS__))
#define entity_make(...) \
entity_make(ENTITY_MAKE_ARGS6(__VA_ARGS__))
/* Mark an entity for deletion at the next collection step */
void entity_mark_to_delete(entity_t *e);
/* Destroy an entity */
void entity_destroy(entity_t *e);
// Useful types when finding/filtering/sorting entities
/* Propositional predicate on entities; used for counting and filtering */
typedef bool entity_predicate_t(entity_t const *e);
/* Measure; used for filtering-sorting */
typedef int entity_measure_t(entity_t const *e);