From 8dc31ce32ffaa0e742c5d9c77c524adb7ea2bfb3 Mon Sep 17 00:00:00 2001 From: KikooDX Date: Tue, 22 Dec 2020 10:53:01 +0100 Subject: [PATCH] Functionnal collision and movement code, it's pretty slow though (see TODO in player.c) --- include/collide.h | 10 +++----- include/conf.h | 2 +- make_levels.sh | 2 +- src/collide.c | 62 +++++++---------------------------------------- src/main.c | 4 +-- src/player.c | 44 ++++++++++++++++----------------- 6 files changed, 38 insertions(+), 86 deletions(-) diff --git a/include/collide.h b/include/collide.h index 2534393..ba3fed1 100644 --- a/include/collide.h +++ b/include/collide.h @@ -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 */ diff --git a/include/conf.h b/include/conf.h index c7bfd23..648ad38 100644 --- a/include/conf.h +++ b/include/conf.h @@ -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} diff --git a/make_levels.sh b/make_levels.sh index 00131ce..2977c58 100755 --- a/make_levels.sh +++ b/make_levels.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh cd levels ./create_demo.lua > 0.jtmm2 ./generate_c.lua > ../src/gen_levels.c diff --git a/src/collide.c b/src/collide.c index 87d1cac..b8170e8 100644 --- a/src/collide.c +++ b/src/collide.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); -} diff --git a/src/main.c b/src/main.c index c936b35..3233200 100644 --- a/src/main.c +++ b/src/main.c @@ -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"*/ diff --git a/src/player.c b/src/player.c index c75d88f..5dfdd3e 100644 --- a/src/player.c +++ b/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);