Textbox is working now

This commit is contained in:
Edgaru089 2024-03-30 22:05:49 +08:00
parent c69fe1738c
commit 1a1038522c
6 changed files with 97 additions and 9 deletions

23
app.c
View File

@ -8,6 +8,8 @@
#include "player.h" #include "player.h"
#include "types.h" #include "types.h"
#include "render_bundle.h" #include "render_bundle.h"
#include "render_component.h"
#include "mapper_misc.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -58,6 +60,27 @@ App *app_NewApp() {
hit3->hitbox->fixed = true; hit3->hitbox->fixed = true;
entity_Commit(app->entity, hit3); entity_Commit(app->entity, hit3);
Entity *text1 = entity_Create(app->entity, "text_plate_large_1");
ADD_COMPONENT(text1, position);
text1->position->position = vec2(600, 550);
text1->render = render_NewComponent(app, "info_plate");
misc_InstantiateTextbox(app, text1, "So long lives this,\nAnd this gives life to thee.", misc_TextboxUpright(110, 110), -220);
entity_Commit(app->entity, text1);
Entity *text2 = entity_Create(app->entity, "text_plate_1");
ADD_COMPONENT(text2, position);
text2->position->position = vec2(250, 200);
text2->render = render_NewComponent(app, "info_plate_small_1");
misc_InstantiateTextbox(app, text2, "Press Space to jump.\nYou can jump again midair.", misc_TextboxUpright(70, 70), -180);
entity_Commit(app->entity, text2);
Entity *text3 = entity_Create(app->entity, "text_plate_2");
ADD_COMPONENT(text3, position);
text3->position->position = vec2(750, 200);
text3->render = render_NewComponent(app, "info_plate_small_2");
misc_InstantiateTextbox(app, text3, "Press ; to dash.\nYou can only dash one time midair.", misc_TextboxUpright(70, 70), -180);
entity_Commit(app->entity, text3);
return app; return app;
} }

View File

@ -5,6 +5,7 @@
#include "physics.h" #include "physics.h"
#include "easyx.h" #include "easyx.h"
#include "render_bundle.h" #include "render_bundle.h"
#include "render_component.h"
#include "util/tree.h" #include "util/tree.h"
#include "types.h" #include "types.h"
#include "render_util.h" #include "render_util.h"
@ -63,14 +64,38 @@ void app_Render(App *app) {
render_FillCircleW(app, vec2(200, 100), 20); render_FillCircleW(app, vec2(200, 100), 20);
render_DrawBundleW(app, render_FindBundle("info_plate"), vec2(600, 550)); // render_DrawBundleW(app, render_FindBundle("info_plate"), vec2(600, 550));
render_DrawBundleW(app, render_FindBundle("info_plate_small_1"), vec2(250, 200)); render_DrawBundleW(app, render_FindBundle("info_plate_small_1"), vec2(250, 200));
render_DrawBundleW(app, render_FindBundle("info_plate_small_2"), vec2(750, 200)); render_DrawBundleW(app, render_FindBundle("info_plate_small_2"), vec2(750, 200));
// Draw entities
for (tree_Node *i = tree_FirstNode(app->entity->entities);
i != NULL;
i = tree_Node_Next(i)) {
Entity *e = (Entity *)i->data;
if (e->render) {
Component_Render *r = e->render;
// Calculate global position as offset
Vec2 pos = {.x = 0.0, .y = 0.0};
if (e->position)
pos = e->position->position;
// Has bundle
if (r->bundle)
render_DrawBundleW(app, r->bundle, pos);
// Has custom rendering
if (r->custom)
r->custom(app, e, camera_TransformVec2(app->camera, pos), r->custom_data);
}
}
// Draw particles // Draw particles
setfillcolor(RGB(255, 255, 255)); setfillcolor(RGB(255, 255, 255));
setbkcolor(RGB(0, 0, 0)); setbkcolor(RGB(0, 0, 0));
particle_Render(app->particle); particle_Render(app->particle);
settextcolor(RGB(255, 255, 255));
} }
} }

View File

@ -2,6 +2,7 @@
#include "mapper_misc.h" #include "mapper_misc.h"
#include "app.h" #include "app.h"
#include "entity.h" #include "entity.h"
#include "physics.h"
#include "types.h" #include "types.h"
#include "util/assert.h" #include "util/assert.h"
#include <stdio.h> #include <stdio.h>
@ -30,7 +31,8 @@ void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) {
} }
if (app->player->player == NULL) // No player if (app->player->player == NULL) // No player
return; return;
Component_Player *p = app->player->player; Component_Player *p = app->player->player;
Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox);
Box2 worldbox; // Offset if position component exists Box2 worldbox; // Offset if position component exists
Vec2 worldspawn; Vec2 worldspawn;
@ -42,7 +44,7 @@ void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) {
worldspawn = e->misc->respawn->respawn_pos; worldspawn = e->misc->respawn->respawn_pos;
} }
if (box2_Contains(worldbox, p->super->position->position)) if (box2_Intersects(worldbox, playerbox, NULL))
p->hazardRespawn = worldspawn; p->hazardRespawn = worldspawn;
} }
@ -56,13 +58,14 @@ void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime) {
t->progress = fmaxf(0.0f, t->progress - duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED); t->progress = fmaxf(0.0f, t->progress - duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED);
return; return;
} }
Component_Player *p = app->player->player; Component_Player *p = app->player->player;
Box2 playerbox = physics_HitboxAbsolute(p->super->hitbox);
Box2 worldbox; // Offset if position component exists Box2 worldbox; // Offset if position component exists
ASSERT(e->position && "Textboxes must have a position component"); ASSERT(e->position && "Textboxes must have a position component");
worldbox = box2_Offset(t->trigger_box, e->position->position); worldbox = box2_Offset(t->trigger_box, e->position->position);
if (box2_Contains(worldbox, p->super->position->position)) 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);
else else
@ -73,8 +76,8 @@ void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime) {
// Utility functions for creating misc entities // Utility functions for creating misc entities
void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger_box, float offset) { void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger_box, float offset) {
ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set yet"); ASSERT(e->misc == NULL && "Instantiate must be called with e.misc not set");
ASSERT(e->render == NULL && "Instantiate must be called with e.render not set yet"); 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->textbox = zero_malloc(sizeof(misc_Textbox)); e->misc->textbox = zero_malloc(sizeof(misc_Textbox));
@ -82,6 +85,20 @@ void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger
e->misc->textbox->trigger_box = trigger_box; e->misc->textbox->trigger_box = trigger_box;
e->misc->textbox->offset = offset; e->misc->textbox->offset = offset;
e->render = render_NewComponentFunc(app, &misc_render_Textbox, NULL); if (!e->render)
e->render = render_NewComponentFunc(app, &misc_render_Textbox, NULL);
else
e->render->custom = &misc_render_Textbox;
e->thinker = &misc_thinker_Textbox; e->thinker = &misc_thinker_Textbox;
} }
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->thinker = &misc_thinker_HazardRespawn;
}

View File

@ -11,7 +11,7 @@ typedef struct _App App;
typedef struct _Entity Entity; typedef struct _Entity Entity;
#define MISC_TEXTBOX_FADEIN_SPEED 5.0 // Fades in/out in 1/5 seconds #define MISC_TEXTBOX_FADEIN_SPEED 6.0 // Fades in/out in 1/6 seconds
// A textbox that shows itself when the player is close // A textbox that shows itself when the player is close
typedef struct { typedef struct {
@ -55,6 +55,19 @@ void misc_DeleteComponent(Component_Misc *misc);
// Creates misc + render components & sets the thinker. // Creates misc + render components & sets the thinker.
void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger_box, float offset); void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger_box, float offset);
// Inserts the components for a hazard respawn area.
// Creates misc & sets the thinker.
void misc_InstantiateHazardRespawn(App *app, Entity *e, Box2 trigger_box, Vec2 respawn_pos);
static inline Box2 misc_TextboxUpright(double width, double height) {
Box2 b = {
.lefttop = {
.x = -width / 2.0,
.y = -height},
.size = {.x = width, .y = height}};
return b;
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -62,6 +62,7 @@ extern "C" void misc_render_Textbox(App *app, Entity *e, Vec2 entity_screen_pos,
rect.top = (LONG)round(entity_screen_pos.y) + t->offset + 40; rect.top = (LONG)round(entity_screen_pos.y) + t->offset + 40;
// Convert & draw // Convert & draw
// https://docs.easyx.cn/zh-cn/drawtext
convert_text(t->text); convert_text(t->text);
drawtext((LPCTSTR)vector_Data(tbuf), &rect, DT_CENTER | DT_NOCLIP); drawtext((LPCTSTR)vector_Data(tbuf), &rect, DT_CENTER | DT_NOCLIP);
} }

View File

@ -55,6 +55,15 @@ typedef struct {
Vec2 size; Vec2 size;
} Box2; } Box2;
static inline Box2 box2(double x, double y, double width, double height) {
Box2 b;
b.lefttop.x = x;
b.lefttop.y = y;
b.size.x = width;
b.size.y = height;
return b;
}
// Intersection test. // Intersection test.
bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection); bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection);