objectpool: dynamic extents and other improvements
This commit is contained in:
parent
b2660103e3
commit
de31a20497
18 changed files with 244 additions and 120 deletions
|
@ -12,6 +12,7 @@
|
|||
#include "list.h"
|
||||
#include "global.h"
|
||||
#include "stageobjects.h"
|
||||
#include "objectpool_util.h"
|
||||
|
||||
void aniplayer_create(AniPlayer *plr, Animation *ani) {
|
||||
memset(plr,0,sizeof(AniPlayer));
|
||||
|
@ -22,10 +23,16 @@ AniPlayer* aniplayer_create_copy(AniPlayer *src) {
|
|||
// XXX: maybe it needs another name since it allocates memory?
|
||||
// or maybe aniplayer_create needs another name since it doesn't?
|
||||
|
||||
// AniPlayer *plr = malloc(sizeof(AniPlayer));
|
||||
|
||||
AniPlayer *plr = (AniPlayer*)objpool_acquire(stage_object_pools.aniplayers);
|
||||
aniplayer_copy(plr, src);
|
||||
|
||||
size_t data_size;
|
||||
void *src_data = objpool_object_contents(NULL, &src->object_interface, NULL);
|
||||
void *dst_data = objpool_object_contents(stage_object_pools.aniplayers, &plr->object_interface, &data_size);
|
||||
memcpy(dst_data, src_data, data_size);
|
||||
|
||||
plr->queue = NULL;
|
||||
plr->queuesize = 0;
|
||||
|
||||
return plr;
|
||||
}
|
||||
|
||||
|
@ -51,12 +58,6 @@ void aniplayer_reset(AniPlayer *plr) { // resets to a neutral state with empty q
|
|||
}
|
||||
}
|
||||
|
||||
void aniplayer_copy(AniPlayer *dst, AniPlayer *src) {
|
||||
memcpy(dst, src, sizeof(AniPlayer));
|
||||
dst->queue = NULL;
|
||||
dst->queuesize = 0;
|
||||
}
|
||||
|
||||
AniSequence *aniplayer_queue(AniPlayer *plr, int row, int loops, int delay) {
|
||||
AniSequence *s = (AniSequence*)list_append((List**)&plr->queue, calloc(1, sizeof(AniSequence)));
|
||||
plr->queuesize++;
|
||||
|
|
|
@ -32,8 +32,9 @@ struct AniSequence{
|
|||
bool backwards;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ObjectInterface object_interface; // hack for the boss glow effect
|
||||
typedef struct AniPlayer AniPlayer;
|
||||
struct AniPlayer{
|
||||
OBJECT_INTERFACE(AniPlayer); // hack for the boss glow effect
|
||||
|
||||
Animation *ani;
|
||||
int clock;
|
||||
|
@ -43,12 +44,11 @@ typedef struct {
|
|||
|
||||
AniSequence *queue;
|
||||
int queuesize;
|
||||
} AniPlayer;
|
||||
};
|
||||
|
||||
void aniplayer_create(AniPlayer *plr, Animation *ani);
|
||||
void aniplayer_free(AniPlayer *plr);
|
||||
void aniplayer_reset(AniPlayer *plr); // resets to a neutral state with empty queue.
|
||||
void aniplayer_copy(AniPlayer *dst, AniPlayer *src);
|
||||
|
||||
AniPlayer* aniplayer_create_copy(AniPlayer *src);
|
||||
void aniplayer_free_copy(AniPlayer *ani);
|
||||
|
|
|
@ -99,7 +99,7 @@ typedef struct Attack {
|
|||
|
||||
typedef struct Boss {
|
||||
// XXX: temporary hack for binary compatibility of pos with Enemy and Projectile structs
|
||||
ObjectInterface object_interface;
|
||||
OBJECT_INTERFACE(struct Boss);
|
||||
complex pos;
|
||||
|
||||
Attack *attacks;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define PRAGMA(p)
|
||||
#else
|
||||
#define PRAGMA(p) _Pragma(#p)
|
||||
#define USE_GNU_EXTENSIONS
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW_PRINTF_FORMAT
|
||||
|
|
|
@ -27,13 +27,7 @@ enum {
|
|||
};
|
||||
|
||||
struct Enemy {
|
||||
union {
|
||||
ObjectInterface object_interface;
|
||||
struct {
|
||||
Enemy *next;
|
||||
Enemy *prev;
|
||||
};
|
||||
};
|
||||
OBJECT_INTERFACE(Enemy);
|
||||
|
||||
complex pos;
|
||||
complex pos0;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "resource/texture.h"
|
||||
#include "objectpool.h"
|
||||
|
||||
typedef struct Item Item;
|
||||
|
||||
|
@ -27,8 +28,7 @@ typedef enum {
|
|||
} ItemType;
|
||||
|
||||
struct Item {
|
||||
Item *next;
|
||||
Item *prev;
|
||||
OBJECT_INTERFACE(Item);
|
||||
|
||||
int birthtime;
|
||||
complex pos;
|
||||
|
|
|
@ -19,8 +19,7 @@ typedef complex (*LaserPosRule)(Laser* l, float time);
|
|||
typedef void (*LaserLogicRule)(Laser* l, int time);
|
||||
|
||||
struct Laser {
|
||||
struct Laser *next;
|
||||
struct Laser *prev;
|
||||
OBJECT_INTERFACE(Laser);
|
||||
|
||||
complex pos;
|
||||
|
||||
|
|
16
src/list.h
16
src/list.h
|
@ -9,14 +9,22 @@
|
|||
#pragma once
|
||||
#include "taisei.h"
|
||||
|
||||
#define LIST_INTERFACE_BASE(typename) struct { \
|
||||
typename *next; \
|
||||
typename *prev; \
|
||||
}
|
||||
|
||||
#define LIST_INTERFACE(typename) union { \
|
||||
List list_interface; \
|
||||
LIST_INTERFACE_BASE(typename); \
|
||||
}
|
||||
|
||||
typedef struct List {
|
||||
struct List *next;
|
||||
struct List *prev;
|
||||
LIST_INTERFACE_BASE(struct List);
|
||||
} List;
|
||||
|
||||
typedef struct ListContainer {
|
||||
struct ListContainer *next;
|
||||
struct ListContainer *prev;
|
||||
LIST_INTERFACE(struct ListContainer);
|
||||
void *data;
|
||||
} ListContainer;
|
||||
|
||||
|
|
174
src/objectpool.c
174
src/objectpool.c
|
@ -12,27 +12,26 @@
|
|||
#include "util.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifdef OBJPOOL_DEBUG
|
||||
#define OBJ_USED(pool,obj) ((pool)->usemap[((uintptr_t)(obj) - (uintptr_t)(pool)->objects) / (pool)->size_of_object])
|
||||
#endif
|
||||
|
||||
struct ObjectPool {
|
||||
char *tag;
|
||||
size_t size_of_object;
|
||||
size_t max_objects;
|
||||
size_t usage;
|
||||
size_t peak_usage;
|
||||
size_t num_extents;
|
||||
char **extents;
|
||||
ObjectInterface *free_objects;
|
||||
|
||||
IF_OBJPOOL_DEBUG(
|
||||
bool *usemap;
|
||||
)
|
||||
|
||||
char objects[];
|
||||
};
|
||||
|
||||
static inline ObjectInterface* obj_ptr(ObjectPool *pool, size_t idx) {
|
||||
return (ObjectInterface*)(pool->objects + idx * pool->size_of_object);
|
||||
static inline ObjectInterface* obj_ptr(ObjectPool *pool, char *objects, size_t idx) {
|
||||
return (ObjectInterface*)(objects + idx * pool->size_of_object);
|
||||
}
|
||||
|
||||
static void objpool_register_objects(ObjectPool *pool, char *objects) {
|
||||
for(size_t i = 0; i < pool->max_objects; ++i) {
|
||||
list_push((List**)&pool->free_objects, (List*)obj_ptr(pool, objects, i));
|
||||
}
|
||||
}
|
||||
|
||||
ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag) {
|
||||
|
@ -44,17 +43,12 @@ ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag)
|
|||
pool->free_objects = NULL;
|
||||
pool->usage = 0;
|
||||
pool->peak_usage = 0;
|
||||
pool->num_extents = 0;
|
||||
pool->extents = NULL;
|
||||
pool->tag = strdup(tag);
|
||||
|
||||
IF_OBJPOOL_DEBUG({
|
||||
pool->usemap = calloc(max_objects, sizeof(bool));
|
||||
})
|
||||
|
||||
memset(pool->objects, 0, obj_size * max_objects);
|
||||
|
||||
for(size_t i = 0; i < max_objects; ++i) {
|
||||
list_push((List**)&pool->free_objects, (List*)obj_ptr(pool, i));
|
||||
}
|
||||
objpool_register_objects(pool, pool->objects);
|
||||
|
||||
log_debug("[%s] Allocated pool for %zu objects, %zu bytes each",
|
||||
pool->tag,
|
||||
|
@ -65,14 +59,45 @@ ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag)
|
|||
return pool;
|
||||
}
|
||||
|
||||
static char *objpool_add_extent(ObjectPool *pool) {
|
||||
pool->extents = realloc(pool->extents, (++pool->num_extents) * sizeof(pool->extents));
|
||||
char *extent = pool->extents[pool->num_extents - 1] = calloc(pool->max_objects, pool->size_of_object);
|
||||
objpool_register_objects(pool, extent);
|
||||
return extent;
|
||||
}
|
||||
|
||||
static char* objpool_fmt_size(ObjectPool *pool) {
|
||||
switch(pool->num_extents) {
|
||||
case 0:
|
||||
return strfmt("%zu objects, %zu bytes each",
|
||||
pool->max_objects,
|
||||
pool->size_of_object
|
||||
);
|
||||
|
||||
case 1:
|
||||
return strfmt("%zu objects, %zu bytes each, with 1 extent",
|
||||
pool->max_objects * 2,
|
||||
pool->size_of_object
|
||||
);
|
||||
|
||||
default:
|
||||
return strfmt("%zu objects, %zu bytes each, with %zu extents",
|
||||
pool->max_objects * (1 + pool->num_extents),
|
||||
pool->size_of_object,
|
||||
pool->num_extents
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectInterface *objpool_acquire(ObjectPool *pool) {
|
||||
ObjectInterface *obj = (ObjectInterface*)list_pop((List**)&pool->free_objects);
|
||||
|
||||
if(obj) {
|
||||
acquired:
|
||||
memset(obj, 0, pool->size_of_object);
|
||||
|
||||
IF_OBJPOOL_DEBUG({
|
||||
OBJ_USED(pool, obj) = true;
|
||||
obj->_object_private.used = true;
|
||||
})
|
||||
|
||||
if(++pool->usage > pool->peak_usage) {
|
||||
|
@ -83,49 +108,35 @@ ObjectInterface *objpool_acquire(ObjectPool *pool) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
log_fatal("[%s] Object pool exhausted (%zu objects, %zu bytes each)",
|
||||
char *tmp = objpool_fmt_size(pool);
|
||||
log_warn("[%s] Object pool exhausted (%s), extending",
|
||||
pool->tag,
|
||||
pool->max_objects,
|
||||
pool->size_of_object
|
||||
tmp
|
||||
);
|
||||
free(tmp);
|
||||
|
||||
objpool_add_extent(pool);
|
||||
obj = (ObjectInterface*)list_pop((List**)&pool->free_objects);
|
||||
assert(obj != NULL);
|
||||
goto acquired;
|
||||
}
|
||||
|
||||
void objpool_release(ObjectPool *pool, ObjectInterface *object) {
|
||||
objpool_memtest(pool, object);
|
||||
|
||||
IF_OBJPOOL_DEBUG({
|
||||
char *objofs = (char*)object;
|
||||
char *minofs = pool->objects;
|
||||
char *maxofs = pool->objects + (pool->max_objects - 1) * pool->size_of_object;
|
||||
|
||||
if(objofs < minofs || objofs > maxofs) {
|
||||
log_fatal("[%s] Object pointer %p is not within range %p - %p",
|
||||
pool->tag,
|
||||
(void*)objofs,
|
||||
(void*)minofs,
|
||||
(void*)maxofs
|
||||
);
|
||||
}
|
||||
|
||||
ptrdiff_t misalign = (ptrdiff_t)(objofs - pool->objects) % pool->size_of_object;
|
||||
|
||||
if(misalign) {
|
||||
log_fatal("[%s] Object pointer %p is misaligned by %zi",
|
||||
pool->tag,
|
||||
(void*)objofs,
|
||||
(ssize_t)misalign
|
||||
);
|
||||
}
|
||||
|
||||
if(!OBJ_USED(pool, object)) {
|
||||
if(!object->_object_private.used) {
|
||||
log_fatal("[%s] Attempted to release an unused object %p",
|
||||
pool->tag,
|
||||
(void*)objofs
|
||||
(void*)object
|
||||
);
|
||||
}
|
||||
|
||||
OBJ_USED(pool, object) = false;
|
||||
object->_object_private.used = false;
|
||||
})
|
||||
|
||||
list_push((List**)&pool->free_objects, (List*)object);
|
||||
|
||||
pool->usage--;
|
||||
// log_debug("[%s] Usage: %zu", pool->tag, pool->usage);
|
||||
}
|
||||
|
@ -139,17 +150,74 @@ void objpool_free(ObjectPool *pool) {
|
|||
log_warn("[%s] %zu objects still in use", pool->tag, pool->usage);
|
||||
}
|
||||
|
||||
IF_OBJPOOL_DEBUG({
|
||||
free(pool->usemap);
|
||||
})
|
||||
for(size_t i = 0; i < pool->num_extents; ++i) {
|
||||
free(pool->extents[i]);
|
||||
}
|
||||
|
||||
free(pool->extents);
|
||||
free(pool->tag);
|
||||
free(pool);
|
||||
}
|
||||
|
||||
size_t objpool_object_size(ObjectPool *pool) {
|
||||
return pool->size_of_object;
|
||||
}
|
||||
|
||||
void objpool_get_stats(ObjectPool *pool, ObjectPoolStats *stats) {
|
||||
stats->tag = pool->tag;
|
||||
stats->capacity = pool->max_objects;
|
||||
stats->capacity = pool->max_objects * (1 + pool->num_extents);
|
||||
stats->usage = pool->usage;
|
||||
stats->peak_usage = pool->peak_usage;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static bool objpool_object_in_subpool(ObjectPool *pool, ObjectInterface *object, char *objects) {
|
||||
char *objofs = (char*)object;
|
||||
char *minofs = objects;
|
||||
char *maxofs = objects + (pool->max_objects - 1) * pool->size_of_object;
|
||||
|
||||
if(objofs < minofs || objofs > maxofs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ptrdiff_t misalign = (ptrdiff_t)(objofs - objects) % pool->size_of_object;
|
||||
|
||||
if(misalign) {
|
||||
log_fatal("[%s] Object pointer %p is misaligned by %zi",
|
||||
pool->tag,
|
||||
(void*)objofs,
|
||||
(ssize_t)misalign
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static bool objpool_object_in_pool(ObjectPool *pool, ObjectInterface *object) {
|
||||
if(objpool_object_in_subpool(pool, object, pool->objects)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < pool->num_extents; ++i) {
|
||||
if(objpool_object_in_subpool(pool, object, pool->extents[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void objpool_memtest(ObjectPool *pool, ObjectInterface *object) {
|
||||
assert(pool != NULL);
|
||||
assert(object != NULL);
|
||||
|
||||
IF_OBJPOOL_DEBUG({
|
||||
if(!objpool_object_in_pool(pool, object)) {
|
||||
log_fatal("[%s] Object pointer %p does not belong to this pool",
|
||||
pool->tag,
|
||||
(void*)object
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -35,18 +35,42 @@ struct ObjectPoolStats {
|
|||
size_t peak_usage;
|
||||
};
|
||||
|
||||
#define OBJECT_INTERFACE_BASE(typename) struct { \
|
||||
LIST_INTERFACE(typename); \
|
||||
IF_OBJPOOL_DEBUG( \
|
||||
struct { \
|
||||
bool used; \
|
||||
} _object_private; \
|
||||
) \
|
||||
}
|
||||
|
||||
#define OBJECT_INTERFACE(typename) union { \
|
||||
ObjectInterface object_interface; \
|
||||
OBJECT_INTERFACE_BASE(typename); \
|
||||
}
|
||||
|
||||
struct ObjectInterface {
|
||||
union {
|
||||
List list_interface;
|
||||
struct {
|
||||
ObjectInterface *next;
|
||||
ObjectInterface *prev;
|
||||
};
|
||||
};
|
||||
OBJECT_INTERFACE_BASE(ObjectInterface);
|
||||
};
|
||||
|
||||
#ifdef USE_GNU_EXTENSIONS
|
||||
// Do some compile-time checks to make sure the type is compatible with object pools
|
||||
|
||||
#define OBJPOOL_ALLOC(typename,max_objects) (__extension__ ({ \
|
||||
static_assert(__builtin_types_compatible_p(ObjectInterface, __typeof__(((typename*)(0))->object_interface)), \
|
||||
#typename " must implement ObjectInterface (use the OBJECT_INTERFACE macro)"); \
|
||||
static_assert(__builtin_offsetof(typename, object_interface) == 0, \
|
||||
"object_interface must be the first member in " #typename); \
|
||||
objpool_alloc(sizeof(typename), max_objects, #typename); \
|
||||
}))
|
||||
#else
|
||||
#define OBJPOOL_ALLOC(typename,max_objects) objpool_alloc(sizeof(typename), max_objects, #typename)
|
||||
#endif
|
||||
|
||||
ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag);
|
||||
void objpool_free(ObjectPool *pool);
|
||||
ObjectInterface *objpool_acquire(ObjectPool *pool);
|
||||
void objpool_release(ObjectPool *pool, ObjectInterface *object);
|
||||
void objpool_get_stats(ObjectPool *pool, ObjectPoolStats *stats);
|
||||
void objpool_memtest(ObjectPool *pool, ObjectInterface *object);
|
||||
size_t objpool_object_size(ObjectPool *pool);
|
||||
|
|
|
@ -15,6 +15,8 @@ struct ObjectPool {
|
|||
size_t size_of_object;
|
||||
};
|
||||
|
||||
size_t sizeof_objpool_interface = sizeof(ObjectInterface);
|
||||
|
||||
ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag) {
|
||||
ObjectPool *pool = malloc(sizeof(ObjectPool));
|
||||
pool->size_of_object = obj_size;
|
||||
|
@ -37,3 +39,12 @@ void objpool_get_stats(ObjectPool *pool, ObjectPoolStats *stats) {
|
|||
memset(&stats, 0, sizeof(ObjectPoolStats));
|
||||
stats->tag = "<N/A>";
|
||||
}
|
||||
|
||||
void objpool_memtest(ObjectPool *pool, ObjectInterface *object) {
|
||||
assert(pool != NULL);
|
||||
assert(object != NULL);
|
||||
}
|
||||
|
||||
size_t objpool_object_size(ObjectPool *pool) {
|
||||
return pool->size_of_object;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "taisei.h"
|
||||
|
||||
#include "objectpool_util.h"
|
||||
#include "util.h"
|
||||
|
||||
static void* objpool_release_list_callback(List **dest, List *elem, void *vpool) {
|
||||
list_unlink(dest, elem);
|
||||
|
@ -25,3 +26,18 @@ bool objpool_is_full(ObjectPool *pool) {
|
|||
objpool_get_stats(pool, &stats);
|
||||
return stats.capacity == stats.usage;
|
||||
}
|
||||
|
||||
size_t objpool_object_contents_size(ObjectPool *pool) {
|
||||
return objpool_object_size(pool) - sizeof(ObjectInterface);
|
||||
}
|
||||
|
||||
void *objpool_object_contents(ObjectPool *pool, ObjectInterface *obj, size_t *out_size) {
|
||||
assert(obj != NULL);
|
||||
|
||||
if(out_size != NULL) {
|
||||
objpool_memtest(pool, obj);
|
||||
*out_size = objpool_object_contents_size(pool);
|
||||
}
|
||||
|
||||
return (char*)obj + sizeof(ObjectInterface);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
#pragma once
|
||||
#include "taisei.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "objectpool.h"
|
||||
|
||||
void objpool_release_list(ObjectPool *pool, List **dest);
|
||||
bool objpool_is_full(ObjectPool *pool);
|
||||
size_t objpool_object_contents_size(ObjectPool *pool);
|
||||
void *objpool_object_contents(ObjectPool *pool, ObjectInterface *obj, size_t *out_size);
|
||||
|
|
|
@ -54,13 +54,7 @@ typedef enum ProjFlags {
|
|||
} ProjFlags;
|
||||
|
||||
struct Projectile {
|
||||
union {
|
||||
ObjectInterface object_interface;
|
||||
struct {
|
||||
Projectile *next;
|
||||
Projectile *prev;
|
||||
};
|
||||
};
|
||||
OBJECT_INTERFACE(Projectile);
|
||||
|
||||
complex pos;
|
||||
complex pos0;
|
||||
|
|
|
@ -27,13 +27,7 @@
|
|||
#endif
|
||||
|
||||
typedef struct CacheEntry {
|
||||
union {
|
||||
ObjectInterface object_interface;
|
||||
struct {
|
||||
struct CacheEntry *next;
|
||||
struct CacheEntry *prev;
|
||||
};
|
||||
};
|
||||
OBJECT_INTERFACE(struct CacheEntry);
|
||||
|
||||
SDL_Surface *surf;
|
||||
int width;
|
||||
|
@ -241,7 +235,7 @@ void fontrenderer_draw(FontRenderer *f, const char *text, Font *font) {
|
|||
void init_fonts(void) {
|
||||
TTF_Init();
|
||||
memset(&resources.fontren, 0, sizeof(resources.fontren));
|
||||
cache_pool = objpool_alloc(sizeof(CacheEntry), 512, "fontcache");
|
||||
cache_pool = OBJPOOL_ALLOC(CacheEntry, 512);
|
||||
}
|
||||
|
||||
void uninit_fonts(void) {
|
||||
|
|
|
@ -505,7 +505,7 @@ static void stage_draw_hud_objpool_stats(float x, float y, float width, Font *fo
|
|||
char buf[32];
|
||||
objpool_get_stats(*pool, &stats);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%zu | %4zu", stats.usage, stats.peak_usage);
|
||||
snprintf(buf, sizeof(buf), "%zu | %5zu", stats.usage, stats.peak_usage);
|
||||
draw_text(AL_Left | AL_Flag_NoAdjust, (int)x, (int)y, stats.tag, font);
|
||||
draw_text(AL_Right | AL_Flag_NoAdjust, (int)(x + width), (int)y, buf, font);
|
||||
|
||||
|
|
|
@ -15,26 +15,35 @@
|
|||
#include "laser.h"
|
||||
#include "aniplayer.h"
|
||||
|
||||
#define MAX_PROJECTILES 8192
|
||||
#define MAX_ITEMS MAX_PROJECTILES
|
||||
#define MAX_ENEMIES 256
|
||||
#define MAX_LASERS 256
|
||||
#define MAX_ANIPLAYERS 32
|
||||
#define MAX_projectiles 1024
|
||||
#define MAX_items MAX_projectiles
|
||||
#define MAX_enemies 64
|
||||
#define MAX_lasers 64
|
||||
#define MAX_aniplayers 32
|
||||
|
||||
#define OBJECT_POOLS \
|
||||
OBJECT_POOL(Projectile, projectiles) \
|
||||
OBJECT_POOL(Item, items) \
|
||||
OBJECT_POOL(Enemy, enemies) \
|
||||
OBJECT_POOL(Laser, lasers) \
|
||||
OBJECT_POOL(AniPlayer, aniplayers) \
|
||||
|
||||
StageObjectPools stage_object_pools;
|
||||
|
||||
void stage_objpools_alloc(void) {
|
||||
stage_object_pools.projectiles = objpool_alloc(sizeof(Projectile), MAX_PROJECTILES, "proj+part");
|
||||
stage_object_pools.items = objpool_alloc(sizeof(Item), MAX_ITEMS, "item");
|
||||
stage_object_pools.enemies = objpool_alloc(sizeof(Enemy), MAX_ENEMIES, "enemy");
|
||||
stage_object_pools.lasers = objpool_alloc(sizeof(Laser), MAX_LASERS, "laser");
|
||||
stage_object_pools.aniplayers = objpool_alloc(sizeof(AniPlayer), MAX_ANIPLAYERS, "aniplr");
|
||||
stage_object_pools = (StageObjectPools){
|
||||
#define OBJECT_POOL(type,field) \
|
||||
.field = OBJPOOL_ALLOC(type, MAX_##field),
|
||||
|
||||
OBJECT_POOLS
|
||||
#undef OBJECT_POOL
|
||||
};
|
||||
}
|
||||
|
||||
void stage_objpools_free(void) {
|
||||
objpool_free(stage_object_pools.projectiles);
|
||||
objpool_free(stage_object_pools.items);
|
||||
objpool_free(stage_object_pools.enemies);
|
||||
objpool_free(stage_object_pools.lasers);
|
||||
objpool_free(stage_object_pools.aniplayers);
|
||||
#define OBJECT_POOL(type,field) \
|
||||
objpool_free(stage_object_pools.field);
|
||||
|
||||
OBJECT_POOLS
|
||||
#undef OBJECT_POOL
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "taisei.h"
|
||||
|
||||
#include "build_config.h"
|
||||
#include "compat.h"
|
||||
|
||||
#ifdef TAISEI_BUILDCONF_DEBUG
|
||||
#define DEBUG 1
|
||||
|
|
Loading…
Reference in a new issue