Functionnal collision and movement code, it's pretty slow though (see TODO in player.c)
This commit is contained in:
parent
baa1a72703
commit
8dc31ce32f
|
@ -7,13 +7,9 @@
|
|||
#include "conf.h"
|
||||
#include "level.h"
|
||||
|
||||
/* return tile at the given position
|
||||
* -1 is out of bound */
|
||||
/* Return tile at the given position.
|
||||
* 0 is out of bound or empty. */
|
||||
uint8_t collide_point(Vec point, const Level *level, uint layer);
|
||||
bool collide_right(Player *player, Vec position, const Level *level, uint layer_id);
|
||||
bool collide_left(Player *player, Vec position, const Level *level, uint layer_id);
|
||||
bool collide_down(Player *player, Vec position, const Level *level, uint layer_id);
|
||||
bool collide_up(Player *player, Vec position, const Level *level, uint layer_id);
|
||||
bool collide_full(Player *player, Vec position, const Level *level, uint layer_id);
|
||||
bool player_collide(Player *player, Vec position, const Level *level, uint layer_id);
|
||||
|
||||
#endif /* _DEF_PLAYER_COLLIDE */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define VEC_PRECISION 1024
|
||||
#define UPS 256
|
||||
#define UPS 128
|
||||
#define PXS (VEC_PRECISION / UPS)
|
||||
#define TILE_SIZE 8 * VEC_PRECISION
|
||||
#define VEC_DCENTER (Vec){DWIDTH / 2, DHEIGHT / 2}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
cd levels
|
||||
./create_demo.lua > 0.jtmm2
|
||||
./generate_c.lua > ../src/gen_levels.c
|
||||
|
|
|
@ -18,54 +18,7 @@ uint8_t collide_point(Vec point, const Level *level, uint layer_id) {
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: 'collide{right,left,up,down} are a bad idea, should replace all
|
||||
* of these for by an unique function i.e. 'player_collide'.
|
||||
*/
|
||||
bool collide_right(Player *player, Vec position, const Level *level, uint layer_id) {
|
||||
Vec pos;
|
||||
vec_cpy(&pos, position);
|
||||
vec_sub(&pos, player->origin);
|
||||
pos.x += player->hbox.x;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
pos.y += player->hbox.y;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool collide_left(Player *player, Vec position, const Level *level, uint layer_id) {
|
||||
Vec pos;
|
||||
vec_cpy(&pos, position);
|
||||
vec_sub(&pos, player->origin);
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
pos.y += player->hbox.y;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool collide_down(Player *player, Vec position, const Level *level, uint layer_id) {
|
||||
Vec pos;
|
||||
vec_cpy(&pos, position);
|
||||
vec_sub(&pos, player->origin);
|
||||
pos.y += player->hbox.y;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
pos.x += player->hbox.x;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool collide_up(Player *player, Vec position, const Level *level, uint layer_id) {
|
||||
bool player_collide(Player *player, Vec position, const Level *level, uint layer_id) {
|
||||
Vec pos;
|
||||
vec_cpy(&pos, position);
|
||||
vec_sub(&pos, player->origin);
|
||||
|
@ -76,10 +29,13 @@ bool collide_up(Player *player, Vec position, const Level *level, uint layer_id)
|
|||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
pos.y += player->hbox.y;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
pos.x -= player->hbox.x;
|
||||
if (collide_point(pos, level, layer_id)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool collide_full(Player *player, Vec position, const Level *level, uint layer_id) {
|
||||
return collide_up(player, position, level, layer_id) ||
|
||||
collide_down(player, position, level, layer_id);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ int play_level(uint level_id) {
|
|||
Player player = {
|
||||
//.pos = {TILE_SIZE, TILE_SIZE},
|
||||
.spd = {0, 0},
|
||||
.hbox = {7 * VEC_PRECISION - 1, 7 * VEC_PRECISION - 1},
|
||||
.vbox = {6, 6},
|
||||
.hbox = {TILE_SIZE - 1, TILE_SIZE - 1},
|
||||
.vbox = {7, 7},
|
||||
.origin = {4 * VEC_PRECISION, 4 * VEC_PRECISION}
|
||||
};
|
||||
vec_cpy(&player.pos, player.origin); /* place the player at "0/0"*/
|
||||
|
|
44
src/player.c
44
src/player.c
|
@ -10,27 +10,29 @@
|
|||
#define SGN(x) ((x > 0) ? (1) : ((x < 0) ? (-1) : (0)))
|
||||
|
||||
void player_move(Player *player, const Level *level) {
|
||||
/* Try to move the player to a destination, and stop their
|
||||
* momentum if they hit a wall. The player can move if they're
|
||||
* stuck in a block, to avoid softlock in some situations. If
|
||||
* the destination is solid and they aren't in a block, then we
|
||||
* use the costy player_move function to snap them and reset
|
||||
* their speed accordingly.
|
||||
*/
|
||||
/* TODO: Replace with tile snapping and increase UPS back to 256
|
||||
* if possible. */
|
||||
const int sgn_spd_x = SGN(player->spd.x);
|
||||
const int sgn_spd_y = SGN(player->spd.y);
|
||||
/* Try to move the player according to their speed, and move
|
||||
* them backwards while they are in a wall to snap them in a
|
||||
* correct position. */
|
||||
Vec destination;
|
||||
vec_cpy(&destination, player->pos);
|
||||
vec_add(&destination, player->spd);
|
||||
if (collide_full(player, player->pos, level, level->solid_layer) ||
|
||||
!collide_full(player, destination, level, level->solid_layer)) {
|
||||
vec_cpy(&player->pos, destination);
|
||||
destination.x += player->spd.x;
|
||||
/* move player backwards until wall is no longer hit */
|
||||
while (player_collide(player, destination, level, level->solid_layer)) {
|
||||
destination.x -= sgn_spd_x;
|
||||
player->spd.x = 0;
|
||||
}
|
||||
else {
|
||||
/* TODO
|
||||
* Player can't move to destination, snap them. First
|
||||
* move on x axis, then y axis.
|
||||
*/
|
||||
uint i = 0;
|
||||
/* do the same thing for y */
|
||||
destination.y += player->spd.y;
|
||||
while (player_collide(player, destination, level, level->solid_layer)) {
|
||||
destination.y -= sgn_spd_y;
|
||||
player->spd.y = 0;
|
||||
}
|
||||
/* move the player to their new position */
|
||||
vec_cpy(&player->pos, destination);
|
||||
}
|
||||
|
||||
void player_step(Player *player, Input *input, const Level *level) {
|
||||
|
@ -47,8 +49,7 @@ void player_draw(Player *player, Camera *camera) {
|
|||
Vec tl; /* top left */
|
||||
Vec br; /* bottom right */
|
||||
/* The rest of this function calculates the player on screen
|
||||
* position and draw it.
|
||||
*/
|
||||
* position and draw it. */
|
||||
vec_cpy(&tl, player->pos);
|
||||
vec_sub(&tl, player->origin);
|
||||
vec_cpy(&br, tl);
|
||||
|
@ -59,15 +60,14 @@ void player_draw(Player *player, Camera *camera) {
|
|||
vec_sub(&br, camera->offset);
|
||||
vec_mul(&tl, SCALE);
|
||||
vec_mul(&br, SCALE);
|
||||
vec_add(&br, (Vec){SCALE - 1, SCALE - 1});
|
||||
vec_add(&br, (Vec){ SCALE - 1, SCALE - 1 });
|
||||
/* draw code here */
|
||||
vec_drect(tl, br, C_BLACK);
|
||||
}
|
||||
|
||||
void player_draw_debug(Player *player, uint step, const Level *level, uint layer_id) {
|
||||
/* This debug function displays more or less usefull
|
||||
* informations for debugging player movement.
|
||||
*/
|
||||
* informations for debugging player movement. */
|
||||
dprint(0, 0, C_BLACK, "x: %d", player->pos.x);
|
||||
dprint(0, 10, C_BLACK, "y: %d", player->pos.y);
|
||||
dprint(0, 20, C_BLACK, "vp: %d", VEC_PRECISION);
|
||||
|
|
Reference in New Issue