Half-working camera
This commit is contained in:
parent
33a9f50b1e
commit
2c954c6d13
4
app.c
4
app.c
@ -1,5 +1,6 @@
|
||||
|
||||
#include "app.h"
|
||||
#include "camera.h"
|
||||
#include "entity.h"
|
||||
#include "input.h"
|
||||
#include "physics.h"
|
||||
@ -16,6 +17,7 @@ App *app_NewApp() {
|
||||
app->physics = physics_NewSystem(app);
|
||||
app->player = player_NewSystem(app);
|
||||
app->entity = entity_NewSystem(app);
|
||||
app->camera = camera_NewSystem(app);
|
||||
|
||||
app->wantQuit = false;
|
||||
|
||||
@ -59,6 +61,7 @@ void app_DeleteApp(App *app) {
|
||||
entity_DeleteSystem(app->entity);
|
||||
physics_DeleteSystem(app->physics);
|
||||
player_DeleteSystem(app->player);
|
||||
camera_DeleteSystem(app->camera);
|
||||
|
||||
free(app);
|
||||
}
|
||||
@ -69,4 +72,5 @@ void app_Advance(App *app, Duration deltaTime) {
|
||||
player_Advance(app->player, deltaTime);
|
||||
physics_Advance(app->physics, deltaTime);
|
||||
entity_Advance(app->entity, deltaTime);
|
||||
camera_Advance(app->camera, deltaTime);
|
||||
}
|
||||
|
2
app.h
2
app.h
@ -4,6 +4,7 @@
|
||||
#include "physics.h"
|
||||
#include "player.h"
|
||||
#include "input.h"
|
||||
#include "camera.h"
|
||||
#include "types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
@ -17,6 +18,7 @@ typedef struct _App {
|
||||
System_Player *player;
|
||||
System_Input *input;
|
||||
System_Entity *entity;
|
||||
System_Camera *camera;
|
||||
|
||||
bool wantQuit;
|
||||
} App;
|
||||
|
14
app_debug.c
14
app_debug.c
@ -1,5 +1,6 @@
|
||||
|
||||
#include "app.h"
|
||||
#include "types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -19,7 +20,7 @@ void app_DebugText(App *app, vector_Vector *vec_string) {
|
||||
buf, sizeof(buf) - 1,
|
||||
"Player:\n"
|
||||
" Pos: [%.4lf, %.4lf]\n"
|
||||
" Vec:[%.4lf, %.4lf]\n"
|
||||
" Vec: [%.4lf, %.4lf]\n"
|
||||
" OnGround: %s\n"
|
||||
" JumpCount: %d\n",
|
||||
player->super->position->position.x,
|
||||
@ -31,6 +32,17 @@ void app_DebugText(App *app, vector_Vector *vec_string) {
|
||||
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';
|
||||
vector_Push(vec_string, &zero);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
#include "app.h"
|
||||
#include "camera.h"
|
||||
#include "physics.h"
|
||||
#include "easyx.h"
|
||||
#include "util/tree.h"
|
||||
@ -21,7 +22,7 @@ void app_Render(App *app) {
|
||||
else
|
||||
setlinecolor(RGB(255, 255, 0));
|
||||
|
||||
Box2 box = physics_HitboxAbsolute(e->hitbox);
|
||||
Box2 box = camera_TransformBox2(app->camera, physics_HitboxAbsolute(e->hitbox));
|
||||
rectangle(
|
||||
(int)round(box.lefttop.x),
|
||||
(int)round(box.lefttop.y),
|
||||
|
80
camera.c
80
camera.c
@ -1,12 +1,86 @@
|
||||
|
||||
#include "camera.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 *sys = zero_malloc(sizeof(System_Camera));
|
||||
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;
|
||||
}
|
||||
|
7
camera.h
7
camera.h
@ -15,6 +15,7 @@ typedef struct {
|
||||
App *super;
|
||||
Component_Player *player;
|
||||
|
||||
Box2 screen; // Screen box, e.g. 1280x720 origin (0,0)
|
||||
Box2 cam, target; // Current & target camera
|
||||
double speed; // Fraction of distance between cam & target to be covered in 1 sec
|
||||
} System_Camera;
|
||||
@ -22,8 +23,14 @@ typedef struct {
|
||||
System_Camera *camera_NewSystem(App *super);
|
||||
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);
|
||||
|
||||
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world);
|
||||
Box2 camera_TransformBox2(System_Camera *sys, Box2 world);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
4
entity.c
4
entity.c
@ -1,6 +1,7 @@
|
||||
|
||||
#include "entity.h"
|
||||
#include "app.h"
|
||||
#include "camera.h"
|
||||
#include "physics.h"
|
||||
#include "util/assert.h"
|
||||
#include "util/tree.h"
|
||||
@ -29,6 +30,7 @@ void entity_DeleteSystem(System_Entity *sys) {
|
||||
|
||||
physics_DeleteEntity(sys->super->physics, e->id);
|
||||
player_DeleteEntity(sys->super->player, e->id);
|
||||
camera_DeleteEntity(sys->super->camera, e->id);
|
||||
|
||||
if (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) {
|
||||
physics_AddEntity(sys->super->physics, 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);
|
||||
player_DeleteEntity(sys->super->player, e->id);
|
||||
camera_DeleteEntity(sys->super->camera, e->id);
|
||||
|
||||
if (e->position)
|
||||
free(e->position);
|
||||
|
16
types.c
16
types.c
@ -25,6 +25,13 @@ Vec2 vec2_Add(Vec2 x, Vec2 y) {
|
||||
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 result = {
|
||||
.x = v.x * scale,
|
||||
@ -71,6 +78,15 @@ Vec2 box2_Center(Box2 box) {
|
||||
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) {
|
||||
box.lefttop = vec2_Add(box.lefttop, offset);
|
||||
return box;
|
||||
|
2
types.h
2
types.h
@ -29,6 +29,7 @@ static inline Vec2 vec2(double x, double y) {
|
||||
}
|
||||
|
||||
Vec2 vec2_Add(Vec2 x, Vec2 y);
|
||||
Vec2 vec2_Minus(Vec2 pos, Vec2 neg);
|
||||
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);
|
||||
|
||||
Vec2 box2_Center(Box2 box);
|
||||
Box2 box2_FromCenter(Vec2 center, Vec2 size);
|
||||
|
||||
Box2 box2_Offset(Box2 box, Vec2 offset);
|
||||
Box2 box2_OffsetX(Box2 box, double offsetX);
|
||||
|
Loading…
Reference in New Issue
Block a user