Half-working camera

This commit is contained in:
Edgaru089 2024-03-08 14:51:29 +08:00
parent 33a9f50b1e
commit 2c954c6d13
9 changed files with 127 additions and 5 deletions

4
app.c
View File

@ -1,5 +1,6 @@
#include "app.h" #include "app.h"
#include "camera.h"
#include "entity.h" #include "entity.h"
#include "input.h" #include "input.h"
#include "physics.h" #include "physics.h"
@ -16,6 +17,7 @@ App *app_NewApp() {
app->physics = physics_NewSystem(app); app->physics = physics_NewSystem(app);
app->player = player_NewSystem(app); app->player = player_NewSystem(app);
app->entity = entity_NewSystem(app); app->entity = entity_NewSystem(app);
app->camera = camera_NewSystem(app);
app->wantQuit = false; app->wantQuit = false;
@ -59,6 +61,7 @@ void app_DeleteApp(App *app) {
entity_DeleteSystem(app->entity); entity_DeleteSystem(app->entity);
physics_DeleteSystem(app->physics); physics_DeleteSystem(app->physics);
player_DeleteSystem(app->player); player_DeleteSystem(app->player);
camera_DeleteSystem(app->camera);
free(app); free(app);
} }
@ -69,4 +72,5 @@ void app_Advance(App *app, Duration deltaTime) {
player_Advance(app->player, deltaTime); player_Advance(app->player, deltaTime);
physics_Advance(app->physics, deltaTime); physics_Advance(app->physics, deltaTime);
entity_Advance(app->entity, deltaTime); entity_Advance(app->entity, deltaTime);
camera_Advance(app->camera, deltaTime);
} }

2
app.h
View File

@ -4,6 +4,7 @@
#include "physics.h" #include "physics.h"
#include "player.h" #include "player.h"
#include "input.h" #include "input.h"
#include "camera.h"
#include "types.h" #include "types.h"
#include "util/vector.h" #include "util/vector.h"
@ -17,6 +18,7 @@ typedef struct _App {
System_Player *player; System_Player *player;
System_Input *input; System_Input *input;
System_Entity *entity; System_Entity *entity;
System_Camera *camera;
bool wantQuit; bool wantQuit;
} App; } App;

View File

@ -1,5 +1,6 @@
#include "app.h" #include "app.h"
#include "types.h"
#include "util/vector.h" #include "util/vector.h"
#include <stdio.h> #include <stdio.h>
@ -31,6 +32,17 @@ void app_DebugText(App *app, vector_Vector *vec_string) {
PUSH_STRING(buf); PUSH_STRING(buf);
} }
Vec2 center = box2_Center(app->camera->cam),
size = app->camera->cam.size;
snprintf(
buf, sizeof(buf) - 1,
"Camera:\n"
" Center: [%.4lf, %.4lf]\n"
" Size: [%.4lf, %.4lf]\n",
center.x, center.y,
size.x, size.y);
PUSH_STRING(buf);
char zero = '\0'; char zero = '\0';
vector_Push(vec_string, &zero); vector_Push(vec_string, &zero);
} }

View File

@ -1,5 +1,6 @@
#include "app.h" #include "app.h"
#include "camera.h"
#include "physics.h" #include "physics.h"
#include "easyx.h" #include "easyx.h"
#include "util/tree.h" #include "util/tree.h"
@ -21,7 +22,7 @@ void app_Render(App *app) {
else else
setlinecolor(RGB(255, 255, 0)); setlinecolor(RGB(255, 255, 0));
Box2 box = physics_HitboxAbsolute(e->hitbox); Box2 box = camera_TransformBox2(app->camera, physics_HitboxAbsolute(e->hitbox));
rectangle( rectangle(
(int)round(box.lefttop.x), (int)round(box.lefttop.x),
(int)round(box.lefttop.y), (int)round(box.lefttop.y),

View File

@ -1,12 +1,86 @@
#include "camera.h" #include "camera.h"
#include "types.h" #include "types.h"
#include "entity.h"
#include "util/assert.h"
static inline double dabs(double x) { return x < 0.0 ? -x : x; }
static inline double dmin(double x, double y) { return x < y ? x : y; }
System_Camera *camera_NewSystem(App *super) { System_Camera *camera_NewSystem(App *super) {
System_Camera *sys = zero_malloc(sizeof(System_Camera)); System_Camera *sys = zero_malloc(sizeof(System_Camera));
sys->super = super; sys->super = super;
}
void camera_DeleteSystem(System_Camera *sys);
void camera_Advance(System_Camera *sys, Duration deltaTime); Box2 default_screen = {
.lefttop = {.x = 0.0, .y = 0.0},
.size = {.x = 1280, .y = 720}};
sys->cam = sys->screen = default_screen;
return sys;
}
void camera_DeleteSystem(System_Camera *sys) {
free(sys);
}
void camera_AddEntity(System_Camera *sys, Entity *e) {
if (e->player) {
ASSERT(!sys->player && "Two player entities are added! Did you forget to DeleteEntity for player?");
sys->player = e->player;
}
}
void camera_DeleteEntity(System_Camera *sys, uintptr_t id) {
if (sys->player && sys->player->super->id == id)
sys->player = NULL;
}
void camera_Advance(System_Camera *sys, Duration deltaTime) {
Vec2 tocenter;
if (sys->target.size.x > EPS)
tocenter = box2_Center(sys->target);
else if (sys->player)
tocenter = sys->player->super->position->position;
else
return;
double speed;
if (dabs(sys->speed) < EPS)
speed = 4.0;
else
speed = sys->speed;
Vec2 oldcenter = box2_Center(sys->cam), oldsize = sys->cam.size;
Vec2 newcenter, newsize;
Vec2 diff = vec2_Minus(tocenter, oldcenter);
if (dabs(diff.x) < EPS && dabs(diff.y) < EPS)
newcenter = tocenter;
else {
Vec2 xdiff = vec2_Scale(diff, dmin(speed * duration_Seconds(deltaTime), 1.0));
newcenter = vec2_Add(oldcenter, xdiff);
}
// TODO size scaling
newsize = oldsize;
sys->cam = box2_FromCenter(newcenter, newsize);
}
inline static Vec2 _camera_TransformSize(System_Camera *sys, Vec2 worldSize) {
Vec2 result = {
.x = worldSize.x / sys->cam.size.x * sys->screen.size.x,
.y = worldSize.y / sys->cam.size.y * sys->screen.size.y};
return result;
}
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world) {
Vec2 relative = vec2_Minus(world, sys->cam.lefttop);
return vec2_Add(sys->screen.lefttop, _camera_TransformSize(sys, relative));
}
Box2 camera_TransformBox2(System_Camera *sys, Box2 world) {
Box2 result = {
.lefttop = camera_TransformVec2(sys, world.lefttop),
.size = _camera_TransformSize(sys, world.size)};
return result;
}

View File

@ -15,6 +15,7 @@ typedef struct {
App *super; App *super;
Component_Player *player; Component_Player *player;
Box2 screen; // Screen box, e.g. 1280x720 origin (0,0)
Box2 cam, target; // Current & target camera Box2 cam, target; // Current & target camera
double speed; // Fraction of distance between cam & target to be covered in 1 sec double speed; // Fraction of distance between cam & target to be covered in 1 sec
} System_Camera; } System_Camera;
@ -22,8 +23,14 @@ typedef struct {
System_Camera *camera_NewSystem(App *super); System_Camera *camera_NewSystem(App *super);
void camera_DeleteSystem(System_Camera *sys); void camera_DeleteSystem(System_Camera *sys);
void camera_AddEntity(System_Camera *sys, Entity *e);
void camera_DeleteEntity(System_Camera *sys, uintptr_t id);
void camera_Advance(System_Camera *sys, Duration deltaTime); void camera_Advance(System_Camera *sys, Duration deltaTime);
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world);
Box2 camera_TransformBox2(System_Camera *sys, Box2 world);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,6 +1,7 @@
#include "entity.h" #include "entity.h"
#include "app.h" #include "app.h"
#include "camera.h"
#include "physics.h" #include "physics.h"
#include "util/assert.h" #include "util/assert.h"
#include "util/tree.h" #include "util/tree.h"
@ -29,6 +30,7 @@ void entity_DeleteSystem(System_Entity *sys) {
physics_DeleteEntity(sys->super->physics, e->id); physics_DeleteEntity(sys->super->physics, e->id);
player_DeleteEntity(sys->super->player, e->id); player_DeleteEntity(sys->super->player, e->id);
camera_DeleteEntity(sys->super->camera, e->id);
if (e->position) if (e->position)
free(e->position); free(e->position);
@ -67,6 +69,7 @@ Entity *entity_Create(System_Entity *sys, const char *name) {
void entity_Commit(System_Entity *sys, Entity *e) { void entity_Commit(System_Entity *sys, Entity *e) {
physics_AddEntity(sys->super->physics, e); physics_AddEntity(sys->super->physics, e);
player_AddEntity(sys->super->player, e); player_AddEntity(sys->super->player, e);
camera_AddEntity(sys->super->camera, e);
} }
@ -82,6 +85,7 @@ static inline void _entity_Delete(System_Entity *sys, uintptr_t id) {
physics_DeleteEntity(sys->super->physics, e->id); physics_DeleteEntity(sys->super->physics, e->id);
player_DeleteEntity(sys->super->player, e->id); player_DeleteEntity(sys->super->player, e->id);
camera_DeleteEntity(sys->super->camera, e->id);
if (e->position) if (e->position)
free(e->position); free(e->position);

16
types.c
View File

@ -25,6 +25,13 @@ Vec2 vec2_Add(Vec2 x, Vec2 y) {
return result; return result;
} }
Vec2 vec2_Minus(Vec2 pos, Vec2 neg) {
Vec2 result = {
.x = pos.x - neg.x,
.y = pos.y - neg.y};
return result;
}
Vec2 vec2_Scale(Vec2 v, double scale) { Vec2 vec2_Scale(Vec2 v, double scale) {
Vec2 result = { Vec2 result = {
.x = v.x * scale, .x = v.x * scale,
@ -71,6 +78,15 @@ Vec2 box2_Center(Box2 box) {
box.lefttop.y + box.size.y / 2.0); box.lefttop.y + box.size.y / 2.0);
} }
Box2 box2_FromCenter(Vec2 center, Vec2 size) {
Box2 box = {
.size = size,
.lefttop = {
.x = center.x - size.x / 2.0,
.y = center.y - size.y / 2.0}};
return box;
}
Box2 box2_Offset(Box2 box, Vec2 offset) { Box2 box2_Offset(Box2 box, Vec2 offset) {
box.lefttop = vec2_Add(box.lefttop, offset); box.lefttop = vec2_Add(box.lefttop, offset);
return box; return box;

View File

@ -29,6 +29,7 @@ static inline Vec2 vec2(double x, double y) {
} }
Vec2 vec2_Add(Vec2 x, Vec2 y); Vec2 vec2_Add(Vec2 x, Vec2 y);
Vec2 vec2_Minus(Vec2 pos, Vec2 neg);
Vec2 vec2_Scale(Vec2 v, double scale); Vec2 vec2_Scale(Vec2 v, double scale);
@ -43,6 +44,7 @@ typedef struct {
bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection); bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection);
Vec2 box2_Center(Box2 box); Vec2 box2_Center(Box2 box);
Box2 box2_FromCenter(Vec2 center, Vec2 size);
Box2 box2_Offset(Box2 box, Vec2 offset); Box2 box2_Offset(Box2 box, Vec2 offset);
Box2 box2_OffsetX(Box2 box, double offsetX); Box2 box2_OffsetX(Box2 box, double offsetX);