Refactor misc to be more expandable

This commit is contained in:
Edgaru089 2024-04-02 15:56:49 +08:00
parent 5b00594685
commit 9f60aa339b
3 changed files with 52 additions and 85 deletions

View File

@ -42,41 +42,25 @@ void app_Render(App *app) {
(int)round(box.lefttop.y + box.size.y)); (int)round(box.lefttop.y + box.size.y));
} }
if (e->misc) { if (e->misc) {
if (e->misc->textbox) { if (e->misc->textbox)
setlinecolor(RGB(0, 0, 255)); setlinecolor(RGB(0, 0, 255));
Box2 box = camera_TransformBox2(app->camera, box2_Offset(e->misc->textbox->trigger_box, e->position->position)); if (e->misc->respawn_pos) {
rectangle(
(int)round(box.lefttop.x),
(int)round(box.lefttop.y),
(int)round(box.lefttop.x + box.size.x),
(int)round(box.lefttop.y + box.size.y));
}
if (e->misc->respawn) {
setlinecolor(RGB(255, 0, 255)); setlinecolor(RGB(255, 0, 255));
Box2 box;
Vec2 pos; Vec2 pos;
if (e->position) { if (e->position)
box = camera_TransformBox2(app->camera, box2_Offset(e->misc->respawn->trigger_box, e->position->position)); pos = camera_TransformVec2(app->camera, vec2_Add(*e->misc->respawn_pos, e->position->position));
pos = camera_TransformVec2(app->camera, vec2_Add(e->misc->respawn->respawn_pos, e->position->position)); else
} else { pos = camera_TransformVec2(app->camera, *e->misc->respawn_pos);
box = camera_TransformBox2(app->camera, e->misc->respawn->trigger_box);
pos = camera_TransformVec2(app->camera, e->misc->respawn->respawn_pos);
}
rectangle(
(int)round(box.lefttop.x),
(int)round(box.lefttop.y),
(int)round(box.lefttop.x + box.size.x),
(int)round(box.lefttop.y + box.size.y));
line((int)round(pos.x + 12), (int)round(pos.y), (int)round(pos.x - 12), (int)round(pos.y)); line((int)round(pos.x + 12), (int)round(pos.y), (int)round(pos.x - 12), (int)round(pos.y));
line((int)round(pos.x), (int)round(pos.y + 12), (int)round(pos.x), (int)round(pos.y - 12)); line((int)round(pos.x), (int)round(pos.y + 12), (int)round(pos.x), (int)round(pos.y - 12));
} }
if (e->misc->hazard) { if (e->misc->trigger_flags & misc_Hazard)
setlinecolor(RGB(255, 0, 0)); setlinecolor(RGB(255, 0, 0));
Box2 box; Box2 box;
if (e->position) if (e->position)
box = camera_TransformBox2(app->camera, box2_Offset(*e->misc->hazard, e->position->position)); box = camera_TransformBox2(app->camera, box2_Offset(e->misc->trigger, e->position->position));
else else
box = camera_TransformBox2(app->camera, *e->misc->hazard); box = camera_TransformBox2(app->camera, e->misc->trigger);
rectangle( rectangle(
(int)round(box.lefttop.x), (int)round(box.lefttop.x),
(int)round(box.lefttop.y), (int)round(box.lefttop.y),
@ -84,7 +68,6 @@ void app_Render(App *app) {
(int)round(box.lefttop.y + box.size.y)); (int)round(box.lefttop.y + box.size.y));
} }
} }
}
if (app->player->player) { if (app->player->player) {
setlinecolor(RGB(255, 0, 255)); setlinecolor(RGB(255, 0, 255));
Vec2 respawn = camera_TransformVec2(app->camera, app->player->player->hazardRespawn); Vec2 respawn = camera_TransformVec2(app->camera, app->player->player->hazardRespawn);

View File

@ -16,17 +16,19 @@ void misc_DeleteComponent(Component_Misc *misc) {
free(misc->textbox->text); free(misc->textbox->text);
free(misc->textbox); free(misc->textbox);
} }
if (misc->respawn) if (misc->respawn_pos)
free(misc->respawn); free(misc->respawn_pos);
if (misc->hazard)
free(misc->hazard);
free(misc); free(misc);
} }
} }
#define ABSOLUTE_BOX(entity, box) ((entity->position) ? (box2_Offset(box, entity->position->position)) : (box))
#define ABSOLUTE_VEC(entity, pnt) ((entity->position) ? (vec2_Add(pnt, entity->position->position)) : (pnt))
void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) { void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) {
if (!e->misc || !e->misc->respawn) { if (!e->misc || !e->misc->respawn_pos) {
WARN("called on an entity without misc or misc.respawn", 0); WARN("called on an entity without misc or misc.respawn", 0);
e->thinker = NULL; e->thinker = NULL;
return; return;
@ -36,23 +38,15 @@ void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) {
Component_Player *p = app->player->player; Component_Player *p = app->player->player;
Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox); Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox);
Box2 worldbox; // Offset if position component exists Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger);
Vec2 worldspawn; Vec2 worldspawn = ABSOLUTE_VEC(e, *e->misc->respawn_pos);
if (e->position) {
worldbox = box2_Offset(e->misc->respawn->trigger_box, e->position->position);
worldspawn = vec2_Add(e->misc->respawn->respawn_pos, e->position->position);
} else {
worldbox = e->misc->respawn->trigger_box;
worldspawn = e->misc->respawn->respawn_pos;
}
if (box2_Intersects(worldbox, playerbox, NULL)) if (box2_Intersects(worldbox, playerbox, NULL))
p->hazardRespawn = worldspawn; p->hazardRespawn = worldspawn;
} }
void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime) { void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime) {
if (!e->misc || !e->misc->hazard) { if (!e->misc || !(e->misc->trigger_flags & misc_Hazard)) {
WARN("called on an entity without misc or misc.textbox", 0); WARN("called on an entity without misc or misc.flags|Hazard", 0);
e->thinker = NULL; e->thinker = NULL;
return; return;
} }
@ -61,12 +55,7 @@ void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime) {
Component_Player *p = app->player->player; Component_Player *p = app->player->player;
Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox); Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox);
Box2 worldbox; // Offset if position component exists Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger);
if (e->position)
worldbox = box2_Offset(*e->misc->hazard, e->position->position);
else
worldbox = *e->misc->hazard;
if (box2_Intersects(worldbox, playerbox, NULL)) if (box2_Intersects(worldbox, playerbox, NULL))
player_HazardHarm(app->player); player_HazardHarm(app->player);
} }
@ -85,10 +74,7 @@ void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime) {
Component_Player *p = app->player->player; Component_Player *p = app->player->player;
Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox); Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox);
Box2 worldbox; // Offset if position component exists Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger);
ASSERT(e->position && "Textboxes must have a position component");
worldbox = box2_Offset(t->trigger_box, e->position->position);
if (box2_Intersects(worldbox, playerbox, NULL)) if (box2_Intersects(worldbox, playerbox, NULL))
// Fade in // Fade in
t->progress = fminf(1.0f, t->progress + duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED); t->progress = fminf(1.0f, t->progress + duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED);
@ -116,10 +102,10 @@ void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger
ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set"); ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set");
ASSERT((e->render == NULL || e->render->custom == NULL) && "Instantiate for Textbox must be called with e.render.custom not set"); ASSERT((e->render == NULL || e->render->custom == NULL) && "Instantiate for Textbox must be called with e.render.custom not set");
e->misc = zero_malloc(sizeof(Component_Misc)); e->misc = zero_malloc(sizeof(Component_Misc));
e->misc->trigger = trigger_box;
e->misc->textbox = zero_malloc(sizeof(misc_Textbox)); e->misc->textbox = zero_malloc(sizeof(misc_Textbox));
e->misc->textbox->text = copy_malloc(text); e->misc->textbox->text = copy_malloc(text);
e->misc->textbox->trigger_box = trigger_box;
e->misc->textbox->offset = offset; e->misc->textbox->offset = offset;
if (!e->render) if (!e->render)
@ -132,10 +118,8 @@ void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger
void misc_InstantiateHazardRespawn(App *app, Entity *e, Box2 trigger_box, Vec2 respawn_pos) { void misc_InstantiateHazardRespawn(App *app, Entity *e, Box2 trigger_box, Vec2 respawn_pos) {
ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set"); ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set");
e->misc = zero_malloc(sizeof(Component_Misc)); e->misc = zero_malloc(sizeof(Component_Misc));
e->misc->respawn = zero_malloc(sizeof(misc_HazardRespawn)); e->misc->trigger = trigger_box;
e->misc->respawn_pos = copy_malloc_size(&respawn_pos, sizeof(Vec2));
e->misc->respawn->respawn_pos = respawn_pos;
e->misc->respawn->trigger_box = trigger_box;
e->thinker = &misc_thinker_HazardRespawn; e->thinker = &misc_thinker_HazardRespawn;
} }
@ -143,7 +127,8 @@ void misc_InstantiateHazardRespawn(App *app, Entity *e, Box2 trigger_box, Vec2 r
void misc_InstantiateHazard(App *app, Entity *e, Box2 trigger_box) { void misc_InstantiateHazard(App *app, Entity *e, Box2 trigger_box) {
ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set"); ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set");
e->misc = zero_malloc(sizeof(Component_Misc)); e->misc = zero_malloc(sizeof(Component_Misc));
e->misc->hazard = copy_malloc_size(&trigger_box, sizeof(Box2)); e->misc->trigger = trigger_box;
e->misc->trigger_flags = misc_Hazard;
e->thinker = &misc_thinker_Hazard; e->thinker = &misc_thinker_Hazard;
} }

View File

@ -16,7 +16,6 @@ typedef struct _Entity Entity;
// A textbox that shows itself when the player is close // A textbox that shows itself when the player is close
typedef struct { typedef struct {
char *text; // Allocated & copied char *text; // Allocated & copied
Box2 trigger_box; // Relative
float progress; // [0.0, 1.0] float progress; // [0.0, 1.0]
float offset; // Offset of the top of the text to its origin, usually negative float offset; // Offset of the top of the text to its origin, usually negative
} misc_Textbox; } misc_Textbox;
@ -28,12 +27,6 @@ void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime);
void misc_render_Textbox(App *app, Entity *e, Vec2 entity_screen_pos, void *user); void misc_render_Textbox(App *app, Entity *e, Vec2 entity_screen_pos, void *user);
// Hazard respawn point
typedef struct {
Box2 trigger_box;
Vec2 respawn_pos;
} misc_HazardRespawn;
// Thinker for hazard respawns // Thinker for hazard respawns
// Tracks the player & sets its respawn point // Tracks the player & sets its respawn point
void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime); void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime);
@ -47,13 +40,19 @@ void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime);
// Kills itself after some time // Kills itself after some time
void misc_thinker_ToLive(App *app, Entity *e, Duration deltaTime); void misc_thinker_ToLive(App *app, Entity *e, Duration deltaTime);
typedef enum {
misc_Hazard = 1 << 0, // Hazard, harms the player on contact
} misc_TriggerFlags;
// Misc data an entity in the map might want. // Misc data an entity in the map might want.
// Used as patches for quick logic like hazard respawn & textbox // Used as patches for quick logic like hazard respawn & textbox
typedef struct { typedef struct {
Box2 trigger; // Relative to Position if exists; absolute otherwise
misc_TriggerFlags trigger_flags;
misc_Textbox *textbox; misc_Textbox *textbox;
misc_HazardRespawn *respawn; Vec2 *respawn_pos; // Set hazard respawn trigger
Box2 *hazard; // Harms the player on contact if not null, relative
TimePoint tolive; // Deletes itself after this time if it is not 0 TimePoint tolive; // Deletes itself after this time if it is not 0
} Component_Misc; } Component_Misc;