Camera clamping in stage limits and related

This commit is contained in:
KikooDX 2020-09-23 12:19:40 +02:00
parent 431297fa62
commit 52477daac0
12 changed files with 68 additions and 25 deletions

View File

@ -2,18 +2,26 @@
#define _DEF_CAMERA
#include "vec.h"
#include "debug.h"
typedef struct Camera
{
Vec pos;
Vec offset; /* adjusted pixel offset based on pos */
Vec *target; /* the target position to lerp on */
Vec min; /* Values set by level_set used to limit camera position */
Vec max; /* See min comment */
float speed; /* camera lerp speed with 0 < speed <= 1 */
} Camera;
#include "player.h"
#include "level.h"
/* update camera position */
void camera_step(Camera *camera);
/* set the min and max position of the camera and center it on player */
void camera_init(Camera *camera, Player *player, const Level *level);
/* draw a dot corresponding to camera position */
void camera_draw_debug(Camera *camera);

View File

@ -1,7 +1,7 @@
#define VEC_PRECISION 1024
#define UPS 256
#define PXS (VEC_PRECISION / UPS)
#define TILE_SIZE 8
#define TILE_SIZE 8 * VEC_PRECISION
#define VEC_DCENTER (Vec){DWIDTH / 2, DHEIGHT / 2}
#ifdef FX9860G
@ -12,3 +12,5 @@
#define SCALE 2
#define FPS 32
#endif /* FXCG50 */
#define VEC_SCALED_DCENTER (Vec){DWIDTH / (2 * SCALE), DHEIGHT / (2 * SCALE)}

View File

@ -2,6 +2,7 @@
#define _DEF_GEN_LEVELS
#include "level.h"
#include "camera.h"
void level_set(const Level **level, uint level_id);

View File

@ -3,8 +3,6 @@
#include <gint/defs/types.h>
#include "camera.h"
typedef struct Level
{
int width; /* in tiles */
@ -13,6 +11,8 @@ typedef struct Level
int layers_count;
} Level;
#include "camera.h"
void level_step(const Level *level);
void level_draw(const Level *level, Camera *camera);
void layer_draw(const Level *level, Camera *camera, uint layer_id);

View File

@ -2,9 +2,6 @@
#define _DEF_PLAYER
#include "vec.h"
#include "level.h"
#include "camera.h"
#include "input.h"
typedef struct Player
{
@ -14,6 +11,10 @@ typedef struct Player
Vec origin; /* the origin of the player (offset) */
} Player;
#include "level.h"
#include "camera.h"
#include "input.h"
void player_step(Player *player, Input *input);
void player_draw(Player *player, Camera *camera);
void player_draw_debug(Player *player, uint step, const Level *level, uint layer_id);

View File

@ -28,6 +28,9 @@ void vec_divf(Vec *vector, float scale);
* Require a scale ranging from 0 to 1 (0 is instant, 1 is completly still). */
void vec_lerp(Vec *from, Vec to, float scale);
/* limit a vector between two positions */
void vec_clamp(Vec *to_limit, Vec min, Vec max);
/* Draw a rectangle using two Vec as coordinates */
void vec_drect(Vec top_left, Vec bottom_right, int color);

View File

@ -3,32 +3,50 @@
#include "camera.h"
#include "conf.h"
#include "vec.h"
#include "debug.h"
#include "player.h"
#include "level.h"
void camera_step(Camera *camera)
{
/* lerp towards target */
vec_lerp(&camera->pos, *camera->target, camera->speed);
/* put the camera in the right place */
vec_clamp(&camera->pos, camera->min, camera->max);
/* calculate pixel offset */
Vec * const offset = &camera->offset; /* DRY */
vec_cpy(offset, camera->pos);
vec_div(offset, VEC_PRECISION);
Vec scaled_dcenter = VEC_DCENTER;
vec_div(&scaled_dcenter, SCALE);
vec_sub(offset, scaled_dcenter);
vec_sub(offset, VEC_SCALED_DCENTER);
}
void camera_init(Camera *camera, Player *player, const Level *level)
{
/* calculate min and max */
vec_cpy(&camera->min, VEC_SCALED_DCENTER);
vec_mul(&camera->min, VEC_PRECISION);
vec_cpy(&camera->max, (Vec){0, 0});
vec_sub(&camera->max, VEC_SCALED_DCENTER);
vec_mul(&camera->max, VEC_PRECISION);
vec_add(&camera->max, (Vec){TILE_SIZE * level->width, TILE_SIZE * level->height});
vec_cpy(&camera->pos, player->pos);
vec_clamp(&camera->pos, camera->min, camera->max);
}
void camera_draw_debug(Camera *camera)
{
Vec draw_pos;
dprint(0, 0, C_BLACK, "-x: %d, -y: %d", camera->min.x, camera->min.y);
dprint(0, 10, C_BLACK, "+x: %d, +y: %d", camera->max.x, camera->max.y);
dprint(0, 20, C_BLACK, "cx: %d, cy: %d", camera->pos.x, camera->pos.y);
dprint(0, 30, C_BLACK, "px: %d, py: %d", camera->offset.x, camera->offset.y);
/*Vec draw_pos;
vec_cpy(&draw_pos, camera->pos);
vec_mul(&draw_pos, SCALE);
vec_div(&draw_pos, VEC_PRECISION);
#ifdef FX9860G
const int color = C_BLACK;
#endif /* FX9860G */
#endif /* FX9860G *//*
#ifdef FXCG50
const int color = C_RED;
#endif /* FXCG50 */
dpixel(draw_pos.x, draw_pos.y, color);
#endif /* FXCG50 *//*
dpixel(draw_pos.x, draw_pos.y, color);*/
}

View File

@ -8,7 +8,7 @@ uint8_t collide_point(Vec point, const Level *level, uint layer_id)
{
Vec cursor; /* the final position to test */
vec_cpy(&cursor, point);
vec_div(&cursor, VEC_PRECISION * TILE_SIZE); /* get the expected tile ID */
vec_div(&cursor, TILE_SIZE); /* get the expected tile ID */
if (point.x < 0 || point.y < 0 ||
cursor.x >= level->width || cursor.y >= level->height)
{

View File

@ -23,8 +23,8 @@ void layer_draw(const Level *level, Camera *camera, uint layer_id)
vec_cpy(&display_br, display_tl);
vec_sub(&display_tl, VEC_PRECISE_HALF_DISP);
vec_add(&display_br, VEC_PRECISE_HALF_DISP);
vec_div(&display_tl, VEC_PRECISION * TILE_SIZE);
vec_div(&display_br, VEC_PRECISION * TILE_SIZE);
vec_div(&display_tl, TILE_SIZE);
vec_div(&display_br, TILE_SIZE);
int start_x = (display_tl.x > 0) ? display_tl.x : 0;
int start_y = (display_tl.y > 0) ? display_tl.y : 0;
int end_x = (display_br.x < level->width) ? display_br.x + 1 : level->width;
@ -44,12 +44,13 @@ void layer_draw(const Level *level, Camera *camera, uint layer_id)
{
Vec tl = {x, y};
Vec br;
vec_mul(&tl, VEC_PRECISION * TILE_SIZE);
vec_mul(&tl, TILE_SIZE);
vec_div(&tl, VEC_PRECISION);
vec_sub(&tl, camera->offset);
vec_mul(&tl, SCALE);
vec_cpy(&br, tl);
vec_add(&br, (Vec){TILE_SIZE * SCALE - 1, TILE_SIZE * SCALE - 1});
vec_add(&br, (Vec){TILE_SIZE / VEC_PRECISION * SCALE - 1,
TILE_SIZE / VEC_PRECISION * SCALE - 1});
vec_drect(tl, br, color);
}
}

View File

@ -31,7 +31,7 @@ int play_level(uint level_id)
{
/* create player */
Player player = {
.pos = {16 * VEC_PRECISION, 16 * VEC_PRECISION},
.pos = {64 * VEC_PRECISION, 64 * VEC_PRECISION},
.hbox = {7 * VEC_PRECISION, 7 * VEC_PRECISION},
.vbox = {7, 7},
.origin = {4 * VEC_PRECISION, 4 * VEC_PRECISION}
@ -47,6 +47,7 @@ int play_level(uint level_id)
.target = &player.pos,
.speed = 0.02
};
camera_init(&camera, &player, level);
/* create input manager */
Input input;
@ -98,9 +99,9 @@ void draw_event(Player *player, const Level *level, Camera *camera, Input *input
level_draw(level, camera);
player_draw(player, camera);
#ifdef DEBUG
//camera_draw_debug(camera);
camera_draw_debug(camera);
//input_draw_debug(input);
player_draw_debug(player, step, level, 0);
//player_draw_debug(player, step, level, 0);
#endif
dupdate();
}

View File

@ -39,7 +39,7 @@ void player_draw_debug(Player *player, uint step, const Level *level, uint layer
dprint(0, 10, C_BLACK, "y: %d", player->pos.y);
dprint(0, 20, C_BLACK, "vp: %d", VEC_PRECISION);
dprint(0, 30, C_BLACK, "st: %u", step);
dprint(0, 40, C_BLACK, "cx: %d", player->pos.x / (VEC_PRECISION * TILE_SIZE));
dprint(0, 50, C_BLACK, "cy: %d", player->pos.y / (VEC_PRECISION * TILE_SIZE));
dprint(0, 40, C_BLACK, "cx: %d", player->pos.x / TILE_SIZE);
dprint(0, 50, C_BLACK, "cy: %d", player->pos.y / TILE_SIZE);
dprint(0, 60, C_BLACK, "cl: %d", collide_point(player->pos, level, layer_id));
}

View File

@ -57,6 +57,14 @@ void vec_lerp(Vec *from, Vec to, float scale)
vec_add(from, temp);
}
void vec_clamp(Vec *to_limit, Vec min, Vec max)
{
if (to_limit->x < min.x) to_limit->x = min.x;
if (to_limit->y < min.y) to_limit->y = min.y;
if (to_limit->x > max.x) to_limit->x = max.x;
if (to_limit->y > max.y) to_limit->y = max.y;
}
void vec_drect(Vec top_left, Vec bottom_right, int color)
{
drect(top_left.x, top_left.y, bottom_right.x, bottom_right.y, color);