Misc functions like textbox
This commit is contained in:
parent
93ffbfd66c
commit
c69fe1738c
@ -21,6 +21,8 @@ extern "C" {
|
||||
|
||||
|
||||
void app_Render(App *app) {
|
||||
render_SetModes(render_ModeDefault, time_Now());
|
||||
|
||||
for (tree_Node *i = tree_FirstNode(app->entity->entities);
|
||||
i != NULL;
|
||||
i = tree_Node_Next(i)) {
|
||||
@ -38,6 +40,17 @@ void app_Render(App *app) {
|
||||
(int)round(box.lefttop.x + box.size.x),
|
||||
(int)round(box.lefttop.y + box.size.y));
|
||||
}
|
||||
if (e->misc) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static FillMode mode_rotate = {
|
||||
@ -51,6 +64,8 @@ void app_Render(App *app) {
|
||||
|
||||
|
||||
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_2"), vec2(750, 200));
|
||||
|
||||
|
||||
// Draw particles
|
||||
|
76
bundles.txt
76
bundles.txt
@ -31,3 +31,79 @@ P -28.000000 -43.000000
|
||||
P 25.000000 -29.000000
|
||||
ENDPRIM
|
||||
ENDBUNDLE
|
||||
|
||||
BUNDLE info_plate_small_1
|
||||
PRIM POLY
|
||||
FG 255 255 255
|
||||
BG 0 0 0
|
||||
P 9.000000 -83.000000
|
||||
P 39.000000 -57.000000
|
||||
P 35.000000 -16.000000
|
||||
P 18.000000 0.000000
|
||||
P -12.000000 0.000000
|
||||
P -28.000000 -28.000000
|
||||
P -26.000000 -65.000000
|
||||
ENDPRIM
|
||||
PRIM LINESTRIP
|
||||
FG 0 0 0
|
||||
BG 0 0 0
|
||||
P 7.000000 -80.000000
|
||||
P 28.000000 -55.000000
|
||||
P 26.000000 -22.000000
|
||||
P 15.000000 -6.000000
|
||||
ENDPRIM
|
||||
PRIM LINES
|
||||
FG 0 0 0
|
||||
BG 0 0 0
|
||||
P -18.000000 -63.000000
|
||||
P 15.000000 -52.000000
|
||||
P -15.000000 -46.000000
|
||||
P 16.000000 -38.000000
|
||||
P -16.000000 -25.000000
|
||||
P 14.000000 -23.000000
|
||||
ENDPRIM
|
||||
ENDBUNDLE
|
||||
|
||||
BUNDLE info_plate_small_2
|
||||
PRIM POLY
|
||||
FG 255 255 255
|
||||
BG 0 0 0
|
||||
P 7.000000 -79.000000
|
||||
P 45.000000 -63.000000
|
||||
P 49.000000 -23.000000
|
||||
P 34.000000 0.000000
|
||||
P -6.000000 0.000000
|
||||
P -24.000000 -23.000000
|
||||
P -24.000000 -56.000000
|
||||
ENDPRIM
|
||||
PRIM LINESTRIP
|
||||
FG 0 0 0
|
||||
BG 0 0 0
|
||||
P 7.000000 -76.000000
|
||||
P 33.000000 -52.000000
|
||||
P 37.000000 -24.000000
|
||||
P 31.000000 -4.000000
|
||||
ENDPRIM
|
||||
PRIM LINES
|
||||
FG 0 0 0
|
||||
BG 0 0 0
|
||||
P -16.000000 -48.000000
|
||||
P 15.000000 -55.000000
|
||||
P -12.000000 -37.000000
|
||||
P 20.000000 -41.000000
|
||||
P -6.000000 -18.000000
|
||||
P 24.000000 -27.000000
|
||||
P 12.000000 -13.000000
|
||||
P 27.000000 -15.000000
|
||||
ENDPRIM
|
||||
ENDBUNDLE
|
||||
|
||||
BUNDLE spike
|
||||
PRIM POLY
|
||||
FG 255 255 255
|
||||
BG 0 0 0
|
||||
P 0.000000 -50.000000
|
||||
P 15.000000 0.000000
|
||||
P -15.000000 0.000000
|
||||
ENDPRIM
|
||||
ENDBUNDLE
|
||||
|
38
entity.c
38
entity.c
@ -2,6 +2,7 @@
|
||||
#include "entity.h"
|
||||
#include "app.h"
|
||||
#include "camera.h"
|
||||
#include "mapper_misc.h"
|
||||
#include "physics.h"
|
||||
#include "util/assert.h"
|
||||
#include "util/tree.h"
|
||||
@ -11,6 +12,23 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// Frees every member if they exists.
|
||||
static void _entity_FreeMembers(Entity *e) {
|
||||
if (e->position)
|
||||
free(e->position);
|
||||
if (e->hitbox)
|
||||
free(e->hitbox);
|
||||
if (e->player)
|
||||
free(e->player);
|
||||
if (e->name)
|
||||
free(e->name);
|
||||
if (e->render)
|
||||
render_DeleteComponent(e->render);
|
||||
if (e->misc)
|
||||
misc_DeleteComponent(e->misc);
|
||||
}
|
||||
|
||||
|
||||
System_Entity *entity_NewSystem(App *super) {
|
||||
System_Entity *sys = malloc(sizeof(System_Entity));
|
||||
|
||||
@ -32,14 +50,7 @@ void entity_DeleteSystem(System_Entity *sys) {
|
||||
player_DeleteEntity(sys->super->player, e->id);
|
||||
camera_DeleteEntity(sys->super->camera, e->id);
|
||||
|
||||
if (e->position)
|
||||
free(e->position);
|
||||
if (e->hitbox)
|
||||
free(e->hitbox);
|
||||
if (e->player)
|
||||
free(e->player);
|
||||
if (e->name)
|
||||
free(e->name);
|
||||
_entity_FreeMembers(e);
|
||||
}
|
||||
|
||||
tree_Destroy(sys->entities);
|
||||
@ -87,14 +98,7 @@ static inline void _entity_Delete(System_Entity *sys, uintptr_t id) {
|
||||
player_DeleteEntity(sys->super->player, e->id);
|
||||
camera_DeleteEntity(sys->super->camera, e->id);
|
||||
|
||||
if (e->position)
|
||||
free(e->position);
|
||||
if (e->hitbox)
|
||||
free(e->hitbox);
|
||||
if (e->player)
|
||||
free(e->player);
|
||||
if (e->name)
|
||||
free(e->name);
|
||||
_entity_FreeMembers(e);
|
||||
|
||||
tree_Delete(sys->entities, node);
|
||||
}
|
||||
@ -116,6 +120,6 @@ void entity_Advance(System_Entity *sys, Duration deltaTime) {
|
||||
Entity *e = (Entity *)(i->data);
|
||||
|
||||
if (e->thinker)
|
||||
e->thinker(e, deltaTime);
|
||||
e->thinker(sys->super, e, deltaTime);
|
||||
}
|
||||
}
|
||||
|
9
entity.h
9
entity.h
@ -6,6 +6,8 @@
|
||||
#include "util/tree.h"
|
||||
#include "physics.h"
|
||||
#include "player.h"
|
||||
#include "render_component.h"
|
||||
#include "mapper_misc.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -13,8 +15,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _App App;
|
||||
typedef struct _Entity Entity;
|
||||
typedef void (*entity_Thinker)(Entity *e, Duration deltaTime); // The Thinker function type assigned to Entities
|
||||
typedef void (*entity_Thinker)(App *app, Entity *e, Duration deltaTime); // The Thinker function type assigned to Entities
|
||||
|
||||
|
||||
// Entity.
|
||||
@ -25,6 +28,8 @@ typedef struct _Entity {
|
||||
Component_Position *position;
|
||||
Component_Hitbox *hitbox;
|
||||
Component_Player *player;
|
||||
Component_Render *render;
|
||||
Component_Misc *misc;
|
||||
|
||||
entity_Thinker thinker; // Called by System_Entity each frame if not NULL.
|
||||
void *thinkerData; // Data managed by the Thinker, if exists.
|
||||
@ -39,8 +44,6 @@ typedef struct _Entity {
|
||||
} while (false)
|
||||
|
||||
|
||||
typedef struct _App App;
|
||||
|
||||
// Entity manager.
|
||||
typedef struct {
|
||||
App *super;
|
||||
|
87
mapper_misc.c
Normal file
87
mapper_misc.c
Normal file
@ -0,0 +1,87 @@
|
||||
|
||||
#include "mapper_misc.h"
|
||||
#include "app.h"
|
||||
#include "entity.h"
|
||||
#include "types.h"
|
||||
#include "util/assert.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
void misc_DeleteComponent(Component_Misc *misc) {
|
||||
if (misc) {
|
||||
if (misc->textbox) {
|
||||
if (misc->textbox->text)
|
||||
free(misc->textbox->text);
|
||||
free(misc->textbox);
|
||||
}
|
||||
if (misc->respawn)
|
||||
free(misc->respawn);
|
||||
if (misc->hazard)
|
||||
free(misc->hazard);
|
||||
free(misc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void misc_thinker_HazardRespawn(App *app, Entity *e, Duration deltaTime) {
|
||||
if (!e->misc || !e->misc->respawn) {
|
||||
WARN("called on an entity without misc or misc.respawn", 0);
|
||||
return;
|
||||
}
|
||||
if (app->player->player == NULL) // No player
|
||||
return;
|
||||
Component_Player *p = app->player->player;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (box2_Contains(worldbox, p->super->position->position))
|
||||
p->hazardRespawn = worldspawn;
|
||||
}
|
||||
|
||||
void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime) {
|
||||
if (!e->misc || !e->misc->textbox) {
|
||||
WARN("called on an entity without misc or misc.textbox", 0);
|
||||
return;
|
||||
}
|
||||
misc_Textbox *t = e->misc->textbox;
|
||||
if (app->player->player == NULL) { // No player, fade out
|
||||
t->progress = fmaxf(0.0f, t->progress - duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED);
|
||||
return;
|
||||
}
|
||||
Component_Player *p = app->player->player;
|
||||
|
||||
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);
|
||||
|
||||
if (box2_Contains(worldbox, p->super->position->position))
|
||||
// Fade in
|
||||
t->progress = fminf(1.0f, t->progress + duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED);
|
||||
else
|
||||
// Fade out
|
||||
t->progress = fmaxf(0.0f, t->progress - duration_Seconds(deltaTime) * MISC_TEXTBOX_FADEIN_SPEED);
|
||||
}
|
||||
|
||||
|
||||
// Utility functions for creating misc entities
|
||||
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->render == NULL && "Instantiate must be called with e.render not set yet");
|
||||
e->misc = zero_malloc(sizeof(Component_Misc));
|
||||
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->render = render_NewComponentFunc(app, &misc_render_Textbox, NULL);
|
||||
e->thinker = &misc_thinker_Textbox;
|
||||
}
|
61
mapper_misc.h
Normal file
61
mapper_misc.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _App App;
|
||||
typedef struct _Entity Entity;
|
||||
|
||||
|
||||
#define MISC_TEXTBOX_FADEIN_SPEED 5.0 // Fades in/out in 1/5 seconds
|
||||
|
||||
// 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
|
||||
} misc_Textbox;
|
||||
|
||||
// Thinker for textboxes
|
||||
// Tracks the player & see if they're in the box
|
||||
void misc_thinker_Textbox(App *app, Entity *e, Duration deltaTime);
|
||||
// Render callback for textboxes
|
||||
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);
|
||||
|
||||
|
||||
// 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
|
||||
} Component_Misc;
|
||||
|
||||
// Deletes everything nested in misc, and then itself.
|
||||
void misc_DeleteComponent(Component_Misc *misc);
|
||||
|
||||
|
||||
// Inserts the required components for a textbox.
|
||||
// Creates misc + render components & sets the thinker.
|
||||
void misc_InstantiateTextbox(App *app, Entity *e, const char *text, Box2 trigger_box, float offset);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
67
mapper_misc_render.cpp
Normal file
67
mapper_misc_render.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
#include "mapper_misc.h"
|
||||
#include "app.h"
|
||||
#include "entity.h"
|
||||
#include "render_util.h"
|
||||
#include "util/assert.h"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <easyx.h>
|
||||
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define NCHAR char
|
||||
#else
|
||||
#define NCHAR wchar_t
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
static vector_Vector *tbuf;
|
||||
|
||||
void convert_text(const char *str) {
|
||||
if (!tbuf)
|
||||
tbuf = vector_Create(sizeof(NCHAR));
|
||||
|
||||
const NCHAR zero = 0;
|
||||
|
||||
vector_Clear(tbuf);
|
||||
int len = strlen(str);
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
NCHAR wc = str[i];
|
||||
vector_Push(tbuf, &wc);
|
||||
i++;
|
||||
}
|
||||
|
||||
vector_Push(tbuf, &zero);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
extern "C" void misc_render_Textbox(App *app, Entity *e, Vec2 entity_screen_pos, void *user) {
|
||||
if (!e->misc || !e->misc->textbox) {
|
||||
WARN("called on an entity without misc or misc.textbox", 0);
|
||||
return;
|
||||
}
|
||||
misc_Textbox *t = e->misc->textbox;
|
||||
|
||||
// If we're too dim to see, quit early
|
||||
if (t->progress < EPS)
|
||||
return;
|
||||
|
||||
// Set the color
|
||||
int rgb = (int)round(fminf(t->progress, 1.0f) * 255.0);
|
||||
settextcolor(RGB(rgb, rgb, rgb));
|
||||
|
||||
// Compute the bounding rect
|
||||
RECT rect;
|
||||
ASSERT(e->position && "Textboxes must have a position component");
|
||||
rect.left = (LONG)round(entity_screen_pos.x) - 20;
|
||||
rect.right = (LONG)round(entity_screen_pos.x) + 20;
|
||||
rect.top = (LONG)round(entity_screen_pos.y) + t->offset;
|
||||
rect.top = (LONG)round(entity_screen_pos.y) + t->offset + 40;
|
||||
|
||||
// Convert & draw
|
||||
convert_text(t->text);
|
||||
drawtext((LPCTSTR)vector_Data(tbuf), &rect, DT_CENTER | DT_NOCLIP);
|
||||
}
|
2
player.c
2
player.c
@ -75,7 +75,7 @@ void player_Advance(System_Player *sys, Duration deltaTime) {
|
||||
sys->super->particle,
|
||||
vec2_Add(vec2_Random(-20, 20, -10, 10), to_pos),
|
||||
vec2(0, -100), 2, 6, 6,
|
||||
duration_FromSeconds(0), &render_ModeDefault);
|
||||
duration_FromSeconds(0), &render_ModeInverse);
|
||||
}
|
||||
// Particles when dashing
|
||||
if (time_Since(p->lastDash).microseconds < dashLength.microseconds && dabs(p->super->position->velocity.x) > EPS) {
|
||||
|
2
player.h
2
player.h
@ -25,6 +25,8 @@ typedef struct {
|
||||
double storedSpeedY; // Speed stored in the middle of a dash
|
||||
bool onGround; // If the player is on the ground?
|
||||
bool moveLeft, moveRight; // If the player is moving left/right?
|
||||
|
||||
Vec2 hazardRespawn; // Where the last hazard respawn is
|
||||
} Component_Player;
|
||||
|
||||
|
||||
|
@ -37,6 +37,8 @@ void render_DeleteBundle(render_Bundle *b) {
|
||||
vector_Destroy(p->points);
|
||||
}
|
||||
vector_Destroy(b->prims);
|
||||
if (b->name)
|
||||
free(b->name);
|
||||
free(b);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@ extern "C" void render_DrawPrimitiveW(App *app, render_Primitive *p, Vec2 offset
|
||||
buff = vector_Create(sizeof(POINT));
|
||||
vector_Clear(buff);
|
||||
|
||||
bool needDraw = false;
|
||||
|
||||
// Construct the points in screen space
|
||||
for (int i = 0; i < vector_Size(p->points); i++) {
|
||||
Vec2 realpos = vec2_Add(*((Vec2 *)vector_At(p->points, i)), offset);
|
||||
@ -27,8 +29,12 @@ extern "C" void render_DrawPrimitiveW(App *app, render_Primitive *p, Vec2 offset
|
||||
// Really weird
|
||||
fprintf(stderr, "[WARN][render_DrawPrimitiveW] called without a Camera system\n");
|
||||
screenpos = realpos;
|
||||
} else
|
||||
needDraw = true;
|
||||
} else {
|
||||
screenpos = camera_TransformVec2(app->camera, realpos);
|
||||
needDraw = needDraw || box2_Contains(app->camera->cam, realpos);
|
||||
}
|
||||
|
||||
|
||||
// Round the screen position to ints
|
||||
POINT rounded;
|
||||
@ -37,6 +43,8 @@ extern "C" void render_DrawPrimitiveW(App *app, render_Primitive *p, Vec2 offset
|
||||
vector_Push(buff, &rounded);
|
||||
}
|
||||
|
||||
// See if any of the points are in the camera box
|
||||
if (needDraw) {
|
||||
// Set the colors
|
||||
setlinecolor(p->fg);
|
||||
setfillcolor(p->fg);
|
||||
@ -65,4 +73,5 @@ extern "C" void render_DrawPrimitiveW(App *app, render_Primitive *p, Vec2 offset
|
||||
fillpolygon((POINT *)vector_Data(buff), vector_Size(buff));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
29
render_component.c
Normal file
29
render_component.c
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
#include "render_component.h"
|
||||
#include "app.h"
|
||||
#include "render_bundle.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
Component_Render *render_NewComponent(App *app, const char *bundle_name) {
|
||||
render_Bundle *b = render_FindBundle(bundle_name);
|
||||
if (b == NULL) // Not found
|
||||
return NULL;
|
||||
|
||||
Component_Render *r = zero_malloc(sizeof(Component_Render));
|
||||
r->super = app;
|
||||
r->bundle = b;
|
||||
return r;
|
||||
}
|
||||
|
||||
Component_Render *render_NewComponentFunc(App *app, render_CustomFunc func, void *data) {
|
||||
Component_Render *r = zero_malloc(sizeof(Component_Render));
|
||||
r->super = app;
|
||||
r->custom = func;
|
||||
r->custom_data = data;
|
||||
return r;
|
||||
}
|
||||
|
||||
void render_DeleteComponent(Component_Render *r) {
|
||||
free(r);
|
||||
}
|
35
render_component.h
Normal file
35
render_component.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "render_bundle.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _App App;
|
||||
typedef struct _Entity Entity;
|
||||
|
||||
typedef void (*render_CustomFunc)(App *app, Entity *e, Vec2 entity_screen_pos, void *user);
|
||||
|
||||
// Rendering component.
|
||||
// This is mostly for components requiring static renders.
|
||||
typedef struct {
|
||||
App *super;
|
||||
|
||||
render_Bundle *bundle; // A render bundle, usually found by render_FindBundle()
|
||||
render_CustomFunc custom; // Custom rendering function
|
||||
void *custom_data; // User data for the callback
|
||||
} Component_Render;
|
||||
|
||||
|
||||
// Creates a new component with a static render bundle
|
||||
Component_Render *render_NewComponent(App *app, const char *bundle_name);
|
||||
// Creates a new component with a callback for rendering
|
||||
Component_Render *render_NewComponentFunc(App *app, render_CustomFunc func, void *data);
|
||||
void render_DeleteComponent(Component_Render *r);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
11
types.c
11
types.c
@ -82,6 +82,17 @@ bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection) {
|
||||
}
|
||||
}
|
||||
|
||||
bool box2_Contains(const Box2 box, const Vec2 point) {
|
||||
return box.lefttop.x < point.x &&
|
||||
box.lefttop.x + box.size.x > point.x &&
|
||||
box.lefttop.y < point.y &&
|
||||
box.lefttop.y + box.size.y > point.y;
|
||||
}
|
||||
|
||||
bool box2_NotZero(Box2 box) {
|
||||
return box.size.x > EPS && box.size.y > EPS;
|
||||
}
|
||||
|
||||
Vec2 box2_Center(Box2 box) {
|
||||
return vec2(
|
||||
box.lefttop.x + box.size.x / 2.0,
|
||||
|
5
types.h
5
types.h
@ -58,6 +58,8 @@ typedef struct {
|
||||
|
||||
// Intersection test.
|
||||
bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection);
|
||||
// Contain test.
|
||||
bool box2_Contains(const Box2 box, const Vec2 point);
|
||||
|
||||
Vec2 box2_Center(Box2 box);
|
||||
Box2 box2_FromCenter(Vec2 center, Vec2 size);
|
||||
@ -66,6 +68,9 @@ Box2 box2_Offset(Box2 box, Vec2 offset);
|
||||
Box2 box2_OffsetX(Box2 box, double offsetX);
|
||||
Box2 box2_OffsetY(Box2 box, double offsetY);
|
||||
|
||||
// Returns true if the area of the box is not 0.
|
||||
bool box2_NotZero(Box2 box);
|
||||
|
||||
|
||||
// Time duration.
|
||||
typedef struct {
|
||||
|
Loading…
Reference in New Issue
Block a user