Implement jumping
This commit is contained in:
parent
790bcddfa9
commit
4cab2a66b9
90
platformer.c
90
platformer.c
|
@ -29,9 +29,9 @@ static char tilemap[] = " "
|
||||||
" "
|
" "
|
||||||
" "
|
" "
|
||||||
" "
|
" "
|
||||||
"gg "
|
"gg g "
|
||||||
" "
|
" g g"
|
||||||
" "
|
" g "
|
||||||
" g "
|
" g "
|
||||||
" g g "
|
" g g "
|
||||||
"gggggggggg";
|
"gggggggggg";
|
||||||
|
@ -49,6 +49,10 @@ static void on_disconnect(void *context) {
|
||||||
|
|
||||||
static bool left_held, right_held, jump_held;
|
static bool left_held, right_held, jump_held;
|
||||||
|
|
||||||
|
static double jump_maxhold = 0.3;
|
||||||
|
static double jump_maxheight = 21;
|
||||||
|
static double jump_duration = 0.4;
|
||||||
|
|
||||||
static void on_keyboard(void *context, uint32_t window, uint32_t codepoint) {
|
static void on_keyboard(void *context, uint32_t window, uint32_t codepoint) {
|
||||||
(void) context;
|
(void) context;
|
||||||
if (window != main_window)
|
if (window != main_window)
|
||||||
|
@ -62,7 +66,14 @@ static void on_keyboard(void *context, uint32_t window, uint32_t codepoint) {
|
||||||
case -KBKEY_RIGHT: right_held = false; break;
|
case -KBKEY_RIGHT: right_held = false; break;
|
||||||
case KBKEY_SPACE: jump_held = true; break;
|
case KBKEY_SPACE: jump_held = true; break;
|
||||||
case -KBKEY_SPACE: jump_held = false; break;
|
case -KBKEY_SPACE: jump_held = false; break;
|
||||||
|
case KBKEY_Q: jump_maxhold += 0.1; break;
|
||||||
|
case KBKEY_A: jump_maxhold -= 0.1; break;
|
||||||
|
case KBKEY_W: jump_maxheight += 0.1; break;
|
||||||
|
case KBKEY_S: jump_maxheight -= 0.1; break;
|
||||||
|
case KBKEY_E: jump_duration += 0.1; break;
|
||||||
|
case KBKEY_D: jump_duration -= 0.1; break;
|
||||||
}
|
}
|
||||||
|
printf("hold %i height %i duration %i\n", (int)(jump_maxhold * 10), (int)(jump_maxheight * 10), (int)(jump_duration * 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_quit(void *context, uint32_t window) {
|
static void on_quit(void *context, uint32_t window) {
|
||||||
|
@ -91,21 +102,67 @@ static char sample_tilemap(size_t x, size_t y) {
|
||||||
return tilemap[ty * TILES + tx];
|
return tilemap[ty * TILES + tx];
|
||||||
}
|
}
|
||||||
|
|
||||||
static double player_x, player_y;
|
static bool jumping = false;
|
||||||
|
static bool on_ground = false;
|
||||||
|
static double jump_start_y;
|
||||||
|
static double in_jump;
|
||||||
|
static double player_x = 0, player_y = 80;
|
||||||
static double player_dx, player_dy;
|
static double player_dx, player_dy;
|
||||||
static void update(struct timespec now, struct timespec dt_timespec) {
|
static void update(struct timespec now, struct timespec dt_timespec) {
|
||||||
(void) now;
|
(void) now;
|
||||||
double dt = timespec2double(dt_timespec);
|
double dt = timespec2double(dt_timespec);
|
||||||
|
|
||||||
player_x += player_dx * dt;
|
player_x += player_dx * dt;
|
||||||
player_y += player_dy * dt;
|
//player_y += player_dy * dt;
|
||||||
|
|
||||||
if (left_held) player_dx = -30;
|
if (left_held) player_dx = -30;
|
||||||
else if (right_held) player_dx = 30;
|
else if (right_held) player_dx = 30;
|
||||||
else player_dx = 0;
|
else player_dx = 0;
|
||||||
|
|
||||||
if (jump_held) player_dy = -30;
|
if (on_ground && jump_held && !jumping) {
|
||||||
else player_dy = 30;
|
jumping = true;
|
||||||
|
in_jump = 0;
|
||||||
|
jump_start_y = player_y;
|
||||||
|
}
|
||||||
|
if (!on_ground && !jumping) {
|
||||||
|
// TODO: implement proper falling
|
||||||
|
jumping = true;
|
||||||
|
in_jump = jump_duration;
|
||||||
|
jump_start_y = player_y + jump_maxheight;
|
||||||
|
}
|
||||||
|
if (jumping) {
|
||||||
|
in_jump += dt;
|
||||||
|
// Jump is a quadratic arc
|
||||||
|
// h = at^2 + bt + c
|
||||||
|
//
|
||||||
|
// Beginning of jump, zero height
|
||||||
|
// t = 0, h = 0
|
||||||
|
// 0 = a0^2 + b0 + c
|
||||||
|
// c = 0
|
||||||
|
//
|
||||||
|
// At 2*duration, zero height
|
||||||
|
// t = 2T, h = 0
|
||||||
|
// 0 = a(2T)^2 + b(2T) + 0
|
||||||
|
// 0 = 4aT^2 + 2bT
|
||||||
|
// 0 = 2aT^2 + bT
|
||||||
|
// 0 = 2aT + b
|
||||||
|
// b = -2aT
|
||||||
|
//
|
||||||
|
// At duration, maximum height
|
||||||
|
// t = T, h = H
|
||||||
|
// H = aT^2 + bT + 0
|
||||||
|
// H = aT^2 - 2aT^2
|
||||||
|
// H = -aT^2
|
||||||
|
// a = -H / (T^2)
|
||||||
|
// b
|
||||||
|
double a = -jump_maxheight / (jump_duration * jump_duration);
|
||||||
|
double b = -2 * a * jump_duration;
|
||||||
|
double jump_height = a * in_jump * in_jump + b * in_jump;
|
||||||
|
player_y = jump_start_y - jump_height;
|
||||||
|
// player_dy is negative of derivative of jump_height
|
||||||
|
// H = a*t^2 + b*t
|
||||||
|
// H' = 2*a*t + b
|
||||||
|
player_dy = -2 * a * in_jump - b;
|
||||||
|
}
|
||||||
|
|
||||||
// Collision against walls of the map
|
// Collision against walls of the map
|
||||||
if (player_x < 0) {
|
if (player_x < 0) {
|
||||||
|
@ -129,7 +186,7 @@ static void update(struct timespec now, struct timespec dt_timespec) {
|
||||||
size_t left_cx = px - 1;
|
size_t left_cx = px - 1;
|
||||||
size_t right_cx = px + TILE_SIDE;
|
size_t right_cx = px + TILE_SIDE;
|
||||||
size_t leftright_top_cy = py;
|
size_t leftright_top_cy = py;
|
||||||
size_t leftright_bottom_cy = py + TILE_SIDE - 1;
|
size_t leftright_bottom_cy = py + TILE_SIDE - 2;
|
||||||
if ((sample_tilemap(left_cx, leftright_top_cy) != ' ' ||
|
if ((sample_tilemap(left_cx, leftright_top_cy) != ' ' ||
|
||||||
sample_tilemap(left_cx, leftright_bottom_cy) != ' ') &&
|
sample_tilemap(left_cx, leftright_bottom_cy) != ' ') &&
|
||||||
player_dx < 0) {
|
player_dx < 0) {
|
||||||
|
@ -152,14 +209,15 @@ static void update(struct timespec now, struct timespec dt_timespec) {
|
||||||
size_t top_cy = py - 1;
|
size_t top_cy = py - 1;
|
||||||
size_t bottom_cy = py + TILE_SIDE;
|
size_t bottom_cy = py + TILE_SIDE;
|
||||||
|
|
||||||
bool on_ground = false;
|
on_ground = false;
|
||||||
if ((sample_tilemap(topbottom_left_cx, bottom_cy) != ' ' ||
|
if (sample_tilemap(topbottom_left_cx, bottom_cy) != ' ' ||
|
||||||
sample_tilemap(topbottom_right_cx, bottom_cy) != ' ') &&
|
sample_tilemap(topbottom_right_cx, bottom_cy) != ' ') {
|
||||||
player_dy > 0) {
|
|
||||||
on_ground = true;
|
on_ground = true;
|
||||||
size_t snapped_py = py / TILE_SIDE * TILE_SIDE;
|
if (player_dy > 0) {
|
||||||
player_y = snapped_py;
|
jumping = false;
|
||||||
player_dy = 0;
|
size_t snapped_py = py / TILE_SIDE * TILE_SIDE;
|
||||||
|
player_y = snapped_py;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((sample_tilemap(topbottom_left_cx, top_cy) != ' ' ||
|
if ((sample_tilemap(topbottom_left_cx, top_cy) != ' ' ||
|
||||||
sample_tilemap(topbottom_right_cx, top_cy) != ' ') &&
|
sample_tilemap(topbottom_right_cx, top_cy) != ' ') &&
|
||||||
|
|
Loading…
Reference in New Issue