diff --git a/app_render.cpp b/app_render.cpp index 462d789..047f98f 100644 --- a/app_render.cpp +++ b/app_render.cpp @@ -42,47 +42,30 @@ void app_Render(App *app) { (int)round(box.lefttop.y + box.size.y)); } if (e->misc) { - if (e->misc->textbox) { + if (e->misc->textbox) setlinecolor(RGB(0, 0, 255)); - Box2 box = camera_TransformBox2(app->camera, box2_Offset(e->misc->textbox->trigger_box, e->position->position)); - 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) { + if (e->misc->respawn_pos) { setlinecolor(RGB(255, 0, 255)); - Box2 box; Vec2 pos; - 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->respawn_pos, e->position->position)); - } else { - 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)); + if (e->position) + pos = camera_TransformVec2(app->camera, vec2_Add(*e->misc->respawn_pos, e->position->position)); + else + pos = camera_TransformVec2(app->camera, *e->misc->respawn_pos); 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)); } - if (e->misc->hazard) { + if (e->misc->trigger_flags & misc_Hazard) setlinecolor(RGB(255, 0, 0)); - Box2 box; - if (e->position) - box = camera_TransformBox2(app->camera, box2_Offset(*e->misc->hazard, e->position->position)); - else - box = camera_TransformBox2(app->camera, *e->misc->hazard); - 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)); - } + Box2 box; + if (e->position) + box = camera_TransformBox2(app->camera, box2_Offset(e->misc->trigger, e->position->position)); + else + box = camera_TransformBox2(app->camera, e->misc->trigger); + 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 (app->player->player) { diff --git a/mapper_misc.c b/mapper_misc.c index 65d46ca..37f3253 100644 --- a/mapper_misc.c +++ b/mapper_misc.c @@ -16,17 +16,19 @@ void misc_DeleteComponent(Component_Misc *misc) { free(misc->textbox->text); free(misc->textbox); } - if (misc->respawn) - free(misc->respawn); - if (misc->hazard) - free(misc->hazard); + if (misc->respawn_pos) + free(misc->respawn_pos); 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) { - if (!e->misc || !e->misc->respawn) { + if (!e->misc || !e->misc->respawn_pos) { WARN("called on an entity without misc or misc.respawn", 0); e->thinker = NULL; return; @@ -36,23 +38,15 @@ void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) { Component_Player *p = app->player->player; Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox); - Box2 worldbox; // Offset if position component exists - Vec2 worldspawn; - 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; - } - + Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger); + Vec2 worldspawn = ABSOLUTE_VEC(e, *e->misc->respawn_pos); if (box2_Intersects(worldbox, playerbox, NULL)) p->hazardRespawn = worldspawn; } void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime) { - if (!e->misc || !e->misc->hazard) { - WARN("called on an entity without misc or misc.textbox", 0); + if (!e->misc || !(e->misc->trigger_flags & misc_Hazard)) { + WARN("called on an entity without misc or misc.flags|Hazard", 0); e->thinker = NULL; return; } @@ -61,12 +55,7 @@ void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime) { Component_Player *p = app->player->player; Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox); - Box2 worldbox; // Offset if position component exists - if (e->position) - worldbox = box2_Offset(*e->misc->hazard, e->position->position); - else - worldbox = *e->misc->hazard; - + Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger); if (box2_Intersects(worldbox, playerbox, NULL)) player_HazardHarm(app->player); } @@ -85,10 +74,7 @@ void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime) { Component_Player *p = app->player->player; Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox); - Box2 worldbox; // Offset if position component exists - ASSERT(e->position && "Textboxes must have a position component"); - worldbox = box2_Offset(t->trigger_box, e->position->position); - + Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger); if (box2_Intersects(worldbox, playerbox, NULL)) // Fade in t->progress = fminf(1.0f, t->progress + duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED); @@ -116,11 +102,11 @@ 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->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->trigger = trigger_box; e->misc->textbox = zero_malloc(sizeof(misc_Textbox)); - e->misc->textbox->text = copy_malloc(text); - e->misc->textbox->trigger_box = trigger_box; - e->misc->textbox->offset = offset; + e->misc->textbox->text = copy_malloc(text); + e->misc->textbox->offset = offset; if (!e->render) e->render = render_NewComponentFunc(app, &misc_render_Textbox, NULL); @@ -131,19 +117,18 @@ 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) { ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set"); - e->misc = zero_malloc(sizeof(Component_Misc)); - e->misc->respawn = zero_malloc(sizeof(misc_HazardRespawn)); - - e->misc->respawn->respawn_pos = respawn_pos; - e->misc->respawn->trigger_box = trigger_box; + e->misc = zero_malloc(sizeof(Component_Misc)); + e->misc->trigger = trigger_box; + e->misc->respawn_pos = copy_malloc_size(&respawn_pos, sizeof(Vec2)); e->thinker = &misc_thinker_HazardRespawn; } void misc_InstantiateHazard(App *app, Entity *e, Box2 trigger_box) { ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set"); - e->misc = zero_malloc(sizeof(Component_Misc)); - e->misc->hazard = copy_malloc_size(&trigger_box, sizeof(Box2)); + e->misc = zero_malloc(sizeof(Component_Misc)); + e->misc->trigger = trigger_box; + e->misc->trigger_flags = misc_Hazard; e->thinker = &misc_thinker_Hazard; } diff --git a/mapper_misc.h b/mapper_misc.h index c42aac2..5aeda96 100644 --- a/mapper_misc.h +++ b/mapper_misc.h @@ -15,10 +15,9 @@ typedef struct _Entity Entity; // A textbox that shows itself when the player is close typedef struct { - char *text; // Allocated & copied - Box2 trigger_box; // Relative - float progress; // [0.0, 1.0] - float offset; // Offset of the top of the text to its origin, usually negative + char *text; // Allocated & copied + float progress; // [0.0, 1.0] + float offset; // Offset of the top of the text to its origin, usually negative } misc_Textbox; // Thinker for textboxes @@ -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); -// Hazard respawn point -typedef struct { - Box2 trigger_box; - Vec2 respawn_pos; -} misc_HazardRespawn; - // Thinker for hazard respawns // Tracks the player & sets its respawn point void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime); @@ -47,14 +40,20 @@ void misc_thinker_Hazard(App *app, Entity *e, Duration deltaTime); // Kills itself after some time 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. // Used as patches for quick logic like hazard respawn & textbox typedef struct { - misc_Textbox *textbox; - misc_HazardRespawn *respawn; - Box2 *hazard; // Harms the player on contact if not null, relative - TimePoint tolive; // Deletes itself after this time if it is not 0 + Box2 trigger; // Relative to Position if exists; absolute otherwise + misc_TriggerFlags trigger_flags; + misc_Textbox *textbox; + Vec2 *respawn_pos; // Set hazard respawn trigger + + TimePoint tolive; // Deletes itself after this time if it is not 0 } Component_Misc; // Deletes everything nested in misc, and then itself.