macro fuckery for boxed ent arrays
This commit is contained in:
parent
56aebcd921
commit
953ac1c97b
5 changed files with 138 additions and 40 deletions
|
@ -172,7 +172,7 @@ bool cotask_cancel(CoTask *task) {
|
|||
}
|
||||
|
||||
void *cotask_resume(CoTask *task, void *arg) {
|
||||
if(task->bound_ent.ent && !ent_unbox(task->bound_ent)) {
|
||||
if(task->bound_ent.ent && !ENT_UNBOX(task->bound_ent)) {
|
||||
cotask_force_cancel(task);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ EntityInterface *(cotask_bind_to_entity)(CoTask *task, EntityInterface *ent) {
|
|||
UNREACHABLE;
|
||||
}
|
||||
|
||||
task->bound_ent = ent_box(ent);
|
||||
task->bound_ent = ENT_BOX(ent);
|
||||
return ent;
|
||||
}
|
||||
|
||||
|
|
|
@ -244,14 +244,14 @@ void ent_unhook_post_draw(EntityDrawHookCallback callback) {
|
|||
remove_hook(&entities.hooks.post_draw, callback);
|
||||
}
|
||||
|
||||
BoxedEntity ent_box(EntityInterface *ent) {
|
||||
BoxedEntity _ent_box_Entity(EntityInterface *ent) {
|
||||
BoxedEntity h;
|
||||
h.ent = (uintptr_t)ent;
|
||||
h.spawn_id = ent->spawn_id;
|
||||
return h;
|
||||
}
|
||||
|
||||
EntityInterface *ent_unbox(BoxedEntity box) {
|
||||
EntityInterface *_ent_unbox_Entity(BoxedEntity box) {
|
||||
EntityInterface *e = (EntityInterface*)box.ent;
|
||||
|
||||
if(e->spawn_id == box.spawn_id) {
|
||||
|
@ -263,10 +263,10 @@ EntityInterface *ent_unbox(BoxedEntity box) {
|
|||
|
||||
#define ENT_TYPE(typename, id) \
|
||||
Boxed##typename _ent_box_##typename(struct typename *ent) { \
|
||||
return (Boxed##typename) { .as_generic = ent_box(&ent->entity_interface) };\
|
||||
return (Boxed##typename) { .as_generic = _ent_box_Entity(&ent->entity_interface) };\
|
||||
} \
|
||||
struct typename *_ent_unbox_##typename(Boxed##typename box) { \
|
||||
EntityInterface *e = ent_unbox(box.as_generic); \
|
||||
EntityInterface *e = _ent_unbox_Entity(box.as_generic); \
|
||||
return e ? ENT_CAST(e, typename) : NULL; \
|
||||
}
|
||||
|
||||
|
|
118
src/entity.h
118
src/entity.h
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "objectpool.h"
|
||||
#include "util/geometry.h"
|
||||
#include "util/macrohax.h"
|
||||
|
||||
#define LAYER_LOW_BITS 16
|
||||
#define LAYER_LOW_MASK ((1 << LAYER_LOW_BITS) - 1)
|
||||
|
@ -158,8 +159,8 @@ struct BoxedEntity {
|
|||
uint_fast32_t spawn_id;
|
||||
};
|
||||
|
||||
BoxedEntity ent_box(EntityInterface *ent);
|
||||
EntityInterface *ent_unbox(BoxedEntity box);
|
||||
BoxedEntity _ent_box_Entity(EntityInterface *ent);
|
||||
EntityInterface *_ent_unbox_Entity(BoxedEntity box);
|
||||
|
||||
#define ENT_TYPE(typename, id) \
|
||||
typedef union Boxed##typename { \
|
||||
|
@ -172,28 +173,105 @@ EntityInterface *ent_unbox(BoxedEntity box);
|
|||
struct typename; \
|
||||
Boxed##typename _ent_box_##typename(struct typename *ent); \
|
||||
struct typename *_ent_unbox_##typename(Boxed##typename box); \
|
||||
INLINE Boxed##typename _ent_boxed_passthrough_helper_##typename(Boxed##typename box) { return box; }
|
||||
|
||||
ENT_TYPES
|
||||
#undef ENT_TYPE
|
||||
|
||||
#define ENT_BOX(ent) (_Generic((ent), \
|
||||
Projectile*: _ent_box_Projectile, \
|
||||
Laser*: _ent_box_Laser, \
|
||||
Enemy*: _ent_box_Enemy, \
|
||||
Boss*: _ent_box_Boss, \
|
||||
Player*: _ent_box_Player, \
|
||||
Item*: _ent_box_Item, \
|
||||
EntityInterface*: ent_box \
|
||||
)(ent))
|
||||
INLINE BoxedEntity _ent_boxed_passthrough_helper_Entity(BoxedEntity box) { return box; }
|
||||
|
||||
#define ENT_UNBOX(box) (_Generic((box), \
|
||||
BoxedProjectile: _ent_unbox_Projectile, \
|
||||
BoxedLaser: _ent_unbox_Laser, \
|
||||
BoxedEnemy: _ent_unbox_Enemy, \
|
||||
BoxedBoss: _ent_unbox_Boss, \
|
||||
BoxedPlayer: _ent_unbox_Player, \
|
||||
BoxedItem: _ent_unbox_Item, \
|
||||
BoxedEntity: ent_unbox \
|
||||
)(box))
|
||||
#define ENT_UNBOXED_DISPATCH_TABLE(func_prefix) \
|
||||
struct Projectile*: func_prefix##Projectile, \
|
||||
struct Laser*: func_prefix##Laser, \
|
||||
struct Enemy*: func_prefix##Enemy, \
|
||||
struct Boss*: func_prefix##Boss, \
|
||||
struct Player*: func_prefix##Player, \
|
||||
struct Item*: func_prefix##Item, \
|
||||
EntityInterface*: func_prefix##Entity \
|
||||
|
||||
#define ENT_BOXED_DISPATCH_TABLE(func_prefix) \
|
||||
BoxedProjectile: func_prefix##Projectile, \
|
||||
BoxedLaser: func_prefix##Laser, \
|
||||
BoxedEnemy: func_prefix##Enemy, \
|
||||
BoxedBoss: func_prefix##Boss, \
|
||||
BoxedPlayer: func_prefix##Player, \
|
||||
BoxedItem: func_prefix##Item, \
|
||||
BoxedEntity: func_prefix##Entity \
|
||||
|
||||
#define ENT_UNBOXED_DISPATCH_FUNCTION(func_prefix, ...) \
|
||||
_Generic((MACROHAX_FIRST(__VA_ARGS__)), \
|
||||
ENT_UNBOXED_DISPATCH_TABLE(func_prefix) \
|
||||
)(MACROHAX_EXPAND(__VA_ARGS__))
|
||||
|
||||
#define ENT_BOXED_DISPATCH_FUNCTION(func_prefix, ...) \
|
||||
_Generic((MACROHAX_FIRST(__VA_ARGS__)), \
|
||||
ENT_BOXED_DISPATCH_TABLE(func_prefix) \
|
||||
)(MACROHAX_EXPAND(__VA_ARGS__))
|
||||
|
||||
#define ENT_MIXED_DISPATCH_FUNCTION(func_prefix_unboxed, func_prefix_boxed, ...) \
|
||||
_Generic((MACROHAX_FIRST(__VA_ARGS__)), \
|
||||
ENT_UNBOXED_DISPATCH_TABLE(func_prefix_unboxed), \
|
||||
ENT_BOXED_DISPATCH_TABLE(func_prefix_boxed) \
|
||||
)(MACROHAX_EXPAND(__VA_ARGS__))
|
||||
|
||||
#define ENT_BOX(ent) ENT_UNBOXED_DISPATCH_FUNCTION(_ent_box_, ent)
|
||||
#define ENT_UNBOX(box) ENT_BOXED_DISPATCH_FUNCTION(_ent_unbox_, box)
|
||||
#define ENT_BOX_OR_PASSTHROUGH(ent) ENT_MIXED_DISPATCH_FUNCTION(_ent_box_, _ent_boxed_passthrough_helper_, ent)
|
||||
|
||||
typedef struct BoxedEntityArray {
|
||||
BoxedEntity *array;
|
||||
uint capacity;
|
||||
uint size;
|
||||
} BoxedEntityArray;
|
||||
|
||||
#define ENT_TYPE(typename, id) \
|
||||
typedef union Boxed##typename##Array { \
|
||||
BoxedEntityArray as_generic_UNSAFE; \
|
||||
struct { \
|
||||
Boxed##typename *array; \
|
||||
uint capacity; \
|
||||
uint size; \
|
||||
}; \
|
||||
} Boxed##typename##Array; \
|
||||
INLINE void _ent_array_add_##typename(Boxed##typename box, Boxed##typename##Array *a) { \
|
||||
assert(a->size < a->capacity); \
|
||||
a->array[a->size++] = box; \
|
||||
}
|
||||
|
||||
ENT_TYPES
|
||||
#undef ENT_TYPE
|
||||
|
||||
INLINE void _ent_array_add_BoxedEntity(BoxedEntity box, BoxedEntityArray *a) {
|
||||
assert(a->size < a->capacity);
|
||||
a->array[a->size++] = box;
|
||||
}
|
||||
|
||||
INLINE void _ent_array_add_Entity(struct EntityInterface *ent, BoxedEntityArray *a) {
|
||||
_ent_array_add_BoxedEntity(ENT_BOX(ent), a);
|
||||
}
|
||||
|
||||
#define ENT_ARRAY_ADD(_array, _ent) ENT_BOXED_DISPATCH_FUNCTION(_ent_array_add_, ENT_BOX_OR_PASSTHROUGH(_ent), _array)
|
||||
#define ENT_ARRAY_GET_BOXED(_array, _index) ((_array)->array[_index])
|
||||
#define ENT_ARRAY_GET(_array, _index) ENT_UNBOX(ENT_ARRAY_GET_BOXED(_array, _index))
|
||||
|
||||
#define DECLARE_ENT_ARRAY(_ent_type, _name, _capacity) \
|
||||
Boxed##_ent_type##Array _name; \
|
||||
_name.size = 0; \
|
||||
_name.capacity = _capacity; \
|
||||
Boxed##_ent_type _ent_array_data##_name[_name.capacity]; \
|
||||
_name.array = _ent_array_data##_name
|
||||
|
||||
#define ENT_ARRAY(_typename, _capacity) \
|
||||
((Boxed##_typename##Array) { .array = (Boxed##_typename[_capacity]) { 0 }, .capacity = (_capacity), .size = 0 })
|
||||
|
||||
#define ENT_ARRAY_FOREACH(_array, _var, _block) do { \
|
||||
for(uint MACROHAX_ADDLINENUM(_ent_array_iterator) = 0; MACROHAX_ADDLINENUM(_ent_array_iterator) < (_array)->size; ++MACROHAX_ADDLINENUM(_ent_array_iterator)) { \
|
||||
void *MACROHAX_ADDLINENUM(_ent_array_temp) = ENT_ARRAY_GET((_array), MACROHAX_ADDLINENUM(_ent_array_iterator)); \
|
||||
if(MACROHAX_ADDLINENUM(_ent_array_temp) != NULL) { \
|
||||
_var = MACROHAX_ADDLINENUM(_ent_array_temp); \
|
||||
_block \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif // IGUARD_entity_h
|
||||
|
|
|
@ -1721,7 +1721,8 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) {
|
|||
|
||||
int n = global.diff;
|
||||
int nfrog = n*60;
|
||||
BoxedProjectile projs[nfrog];
|
||||
|
||||
DECLARE_ENT_ARRAY(Projectile, projs, nfrog);
|
||||
|
||||
WAIT(20);
|
||||
for(int i = 0; i < nfrog/n; i++) {
|
||||
|
@ -1733,7 +1734,8 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) {
|
|||
|
||||
for(int j = 0; j < n; j++) {
|
||||
float speed = 1+(4+0.5*global.diff)*frand();
|
||||
projs[i*n+j] = ENT_BOX(PROJECTILE(
|
||||
|
||||
ENT_ARRAY_ADD(&projs, PROJECTILE(
|
||||
.proto = pp_ball,
|
||||
.pos = boss->pos,
|
||||
.color = RGB(r, g, b),
|
||||
|
@ -1743,11 +1745,8 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) {
|
|||
YIELD;
|
||||
}
|
||||
WAIT(20);
|
||||
for(int i = 0; i < nfrog; i++) {
|
||||
Projectile *p = ENT_UNBOX(projs[i]);
|
||||
if(p == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ENT_ARRAY_FOREACH(&projs, Projectile *p, {
|
||||
spawn_stain(p->pos, p->angle, 30);
|
||||
spawn_stain(p->pos, p->angle, 30);
|
||||
spawn_projectile_highlight_effect(p);
|
||||
|
@ -1758,7 +1757,8 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) {
|
|||
if(frand() < 0.2) {
|
||||
YIELD;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
WAIT(60);
|
||||
int dir = 2*(frand()>0.5)-1; // wait till they figure this out
|
||||
boss->move = (MoveParams){ .velocity = dir*2.7+I, .retention = 0.99, .acceleration = -dir*0.017 };
|
||||
|
@ -1766,12 +1766,8 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) {
|
|||
aniplayer_queue(&boss->ani,"(9)",0);
|
||||
int d = max(0, global.diff - D_Normal);
|
||||
WAIT(60-5*global.diff);
|
||||
for(int i = 0; i < nfrog; i++) {
|
||||
Projectile *p = ENT_UNBOX(projs[i]);
|
||||
if(p == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ENT_ARRAY_FOREACH(&projs, Projectile *p, {
|
||||
p->color = *RGB(0.9, 0.9, 0.9);
|
||||
p->move.retention = 1+0.002*global.diff*frand();
|
||||
p->move.velocity = 2*cdir(rand_angle());
|
||||
|
@ -1781,7 +1777,7 @@ DEFINE_EXTERN_TASK(stage1_spell_perfect_freeze) {
|
|||
if(frand() < 0.4) {
|
||||
YIELD;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for(int i = 0; i < 30+10*d; i++) {
|
||||
play_loop("shot1_loop");
|
||||
|
|
24
src/util/macrohax.h
Normal file
24
src/util/macrohax.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT License.
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#ifndef IGUARD_util_macrohax_h
|
||||
#define IGUARD_util_macrohax_h
|
||||
|
||||
#include "taisei.h"
|
||||
|
||||
#define MACROHAX_FIRST_(f, ...) f
|
||||
#define MACROHAX_FIRST(...) MACROHAX_FIRST_(__VA_ARGS__, _)
|
||||
#define MACROHAX_EMPTY()
|
||||
#define MACROHAX_DEFER(id) id MACROHAX_EMPTY()
|
||||
#define MACROHAX_OBSTRUCT(...) __VA_ARGS__ MACROHAX_DEFER(MACROHAX_EMPTY)()
|
||||
#define MACROHAX_EXPAND(...) __VA_ARGS__
|
||||
|
||||
#define MACROHAX_CONCAT(a, b) a ## b
|
||||
#define MACROHAX_ADDLINENUM(a) MACROHAX_EXPAND(MACROHAX_DEFER(MACROHAX_CONCAT)(a, __LINE__))
|
||||
|
||||
#endif // IGUARD_util_macrohax_h
|
Loading…
Reference in a new issue