This commit is contained in:
KikooDX 2021-01-04 18:05:10 +01:00
commit 8804a12a90
4 changed files with 45 additions and 15 deletions

View File

@ -1,6 +1,8 @@
#ifndef _DEF_PLAYER
#define _DEF_PLAYER
#include <stdbool.h>
#include "vec.h"
typedef struct Player {
@ -10,6 +12,7 @@ typedef struct Player {
Vec vbox; /* the bottom left corner of the player's visual box */
Vec origin; /* the origin of the sprite (offset) */
uint grace; /* coyot jump */
bool jump_held; /* used to control jump height */
} Player;
#include "level.h"

View File

@ -25,10 +25,10 @@ void layer_draw(const Level *level, Camera *camera, uint layer_id) {
vec_add(&display_br, VEC_PRECISE_HALF_DISP);
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;
int end_y = (display_br.y < level->height) ? display_br.y + 1 : level->height;
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);
int end_y = (display_br.y < level->height) ? (display_br.y + 1) : (level->height);
for (int y = start_y; y < end_y; ++y) {
for (int x = start_x; x < end_x; ++x) {
const Tile cell = layer[x + y * level->width];

View File

@ -34,7 +34,8 @@ int play_level(uint level_id) {
.hbox = {TILE_SIZE - 1, TILE_SIZE - 1},
.vbox = {7, 7},
.origin = {0 * VEC_PRECISION, 0 * VEC_PRECISION},
.grace = 0
.grace = 0,
.jump_held = false
};
vec_cpy(&player.pos, (Vec){0, 0}); /* place the player at "0/0"*/

View File

@ -14,10 +14,13 @@
#define FRICTION 0.99
#define ACCELERATION (int)(MAX_SPD * (1 - FRICTION))
#define GRAVITY PXS
#define FAST_FALL_FACTOR 3
#define JUMP_SPD (-128 * PXS)
#define GRACE_UNITS (int)(UPS / 5)
#define EARLY_UNITS (int)(UPS / 5)
#define SGN(x) ((x > 0) ? (1) : ((x < 0) ? (-1) : (0)))
#define H_CLIP_MARGIN (TILE_SIZE / 4)
#define V_CLIP_MARGIN (TILE_SIZE / 3)
#define SGN(x) (((x) > 0) ? (1) : (((x) < 0) ? (-1) : (0)))
#define PLAYER_COLLIDE_SOLID(pos) (player_collide_or(player, pos, level, level->solid_layer) & F_SOLID)
void player_move(Player *player, const Level *level) {
@ -29,15 +32,25 @@ void player_move(Player *player, const Level *level) {
/* snap the player to the grid if they hit a wall */
destination.x += player->spd.x;
if (PLAYER_COLLIDE_SOLID(destination)) {
destination.x = player->pos.x - player->pos.x % TILE_SIZE;
/* Move the player tile per tile until it enters an
* occuped tile. */
while (!PLAYER_COLLIDE_SOLID(destination)) {
destination.x += TILE_SIZE * sgn_spd_x;
/* Used for clipping and positionning. */
int offset = destination.y % TILE_SIZE;
if (offset > H_CLIP_MARGIN) {
offset = 0;
}
destination.y -= offset;
if (PLAYER_COLLIDE_SOLID(destination))
{
destination.y += offset;
destination.x = player->pos.x - player->pos.x % TILE_SIZE;
/* Move the player tile per tile until it enters an
* occupied tile. */
while (!PLAYER_COLLIDE_SOLID(destination)) {
destination.x += TILE_SIZE * sgn_spd_x;
}
/* then, move it back one tile */
destination.x -= TILE_SIZE * sgn_spd_x;
player->spd.x = 0;
}
/* then, move it back one tile */
destination.x -= TILE_SIZE * sgn_spd_x;
player->spd.x = 0;
}
/* do the same for y */
destination.y += player->spd.y;
@ -69,7 +82,14 @@ void player_step(Player *player, Input *input, const Level *level, uint step) {
int xacc = move.x * ACCELERATION; /* calculate horizontal acceleration */
player->spd.x *= FRICTION; /* apply horizontal friction */
player->spd.x += xacc; /* apply horizontal acceleration */
player->spd.y += GRAVITY; /* apply gravity */
/* apply gravity */
if (player->spd.y < 0 && !player->jump_held) {
/* The player is rising and let go the jump key,
* accelerate gravity until they reach 0. */
player->spd.y += GRAVITY * FAST_FALL_FACTOR;
} else {
player->spd.y += GRAVITY;
}
/* Grace frames allow the player to jump a short
* time after leaving a platform. */
if (player->grace) {
@ -80,8 +100,14 @@ void player_step(Player *player, Input *input, const Level *level, uint step) {
* corresponding y speed. */
player->grace = 0;
player->spd.y = JUMP_SPD;
player->jump_held = true;
}
}
/* See if the player is still holding their jump button, this is
* usefull for jump height and gravity manipulation. */
if (player->jump_held && !k_jump) {
player->jump_held = false;
}
player_move(player, level); /* move the player according to their speed */
}