diff --git a/CMakeLists.txt b/CMakeLists.txt index a4928ab..d92e5cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(SOURCES src/input.c src/tools.c src/level.c + src/hook.c ) set(ASSETS_cg diff --git a/include/hook.h b/include/hook.h new file mode 100644 index 0000000..725d302 --- /dev/null +++ b/include/hook.h @@ -0,0 +1,18 @@ +#pragma once +#include "type.h" + +#define HOOK_T 9 + +struct Hook { + struct Vec2 pos; +}; + +struct Hook_table { + int n; + struct Hook *hooks; +}; + +void hook_table_init(void); +int hook_nb(void); +struct Vec2 hook_closest(struct Vec2 *pos); +void hook_debug_draw(void); diff --git a/include/level.h b/include/level.h index 4a1ee47..d80a794 100644 --- a/include/level.h +++ b/include/level.h @@ -11,3 +11,6 @@ void level_init(void); void level_draw(void); tile_t level_get_px(int x, int y); tile_t level_get_tile(int x, int y); +int level_count(tile_t tile); +int level_search_i(tile_t tile, int occ); +struct Vec2 level_search_s(tile_t tile, int occ); diff --git a/include/player.h b/include/player.h index bae44a0..9f1dea7 100644 --- a/include/player.h +++ b/include/player.h @@ -6,7 +6,8 @@ struct Player { struct FVec2 spd; struct FVec2 rem; struct Vec2 spawn; - int jumping, airbreak; + struct Vec2 hook_pos; + int jumping, airbreak, hooking; }; void player_init(void); diff --git a/include/tools.h b/include/tools.h index ca38d8d..cc4db86 100644 --- a/include/tools.h +++ b/include/tools.h @@ -1,3 +1,4 @@ #pragma once int sign(int x); +int length(int x1, int y1, int x2, int y2); diff --git a/src/hook.c b/src/hook.c new file mode 100644 index 0000000..957be93 --- /dev/null +++ b/src/hook.c @@ -0,0 +1,68 @@ +#include "hook.h" +#include "conf.h" +#include "level.h" +#include "tools.h" +#include +#include +#include + +static struct Hook_table hook_table = {.hooks = NULL}; +static void hook_table_free(void); + +void +hook_table_init(void) +{ + hook_table_free(); + + hook_table.n = level_count(HOOK_T); + hook_table.hooks = malloc(hook_table.n * sizeof(struct Hook)); + + for (int i = 0; i < hook_table.n; ++i) { + hook_table.hooks[i].pos = level_search_s(HOOK_T, i + 1); + } + /*hook_table.hooks[0].pos = level_search_s(HOOK_T, 1);*/ +} + +void +hook_table_free(void) +{ + if (hook_table.hooks != NULL) { + hook_table.hooks = NULL; + } +} + +int +hook_nb(void) +{ + return hook_table.n; +} + +struct Vec2 +hook_closest(struct Vec2 *pos) +{ + /* search the closest hook */ + struct Vec2 shortest = {0, 0}; + if (hook_table.n) { + shortest = hook_table.hooks[0].pos; + float sh_dist = length(shortest.x, shortest.y, pos->x, pos->y); + for (int i = 0; i < hook_table.n; ++i) { + const struct Hook h = hook_table.hooks[i]; + const float dist = + length(h.pos.x, h.pos.y, pos->x, pos->y); + if (dist < sh_dist) { + shortest = h.pos; + sh_dist = dist; + } + } + } + shortest = (struct Vec2){shortest.x * TILE_S + TILE_S / 2, shortest.y * TILE_S + TILE_S / 2}; + return shortest; +} + +void +hook_debug_draw(void) +{ + dprint(10, 20, C_WHITE, "%d", hook_table.n); + dprint(30, 20, C_WHITE, "%d", hook_table.hooks[0].pos); + dprint(50, 20, C_WHITE, "%d", hook_table.hooks[0].pos); +} diff --git a/src/level.c b/src/level.c index b84e80a..d28fbe8 100644 --- a/src/level.c +++ b/src/level.c @@ -1,5 +1,6 @@ #include "level.h" #include "conf.h" +#include "hook.h" #include "player.h" #include #include @@ -22,6 +23,7 @@ level_init(void) level_free(); level_load(); + hook_table_init(); player_init(); } @@ -53,6 +55,50 @@ level_get_tile(int x, int y) return level.data[x + y * level.w]; } +int +level_count(tile_t tile) +{ + int i = 0; + for (int t = 0; t < level.h * level.w - 1; ++t) { + if (level.data[t] == tile) { + ++i; + } + } + return i; +} + +int +level_search_i(tile_t tile, int occ) +{ + for (int t = 0; t < level.h * level.w - 1; ++t) { + if (level.data[t] == tile) { + if (!(occ - 1)) { + return t; + } else { + --occ; + } + } + } + return 0; +} + +struct Vec2 +level_search_s(tile_t tile, int occ) +{ + for (int m = 0; m < level.h; ++m) { + for (int n = 0; n < level.w; ++n) { + if (level.data[n + m * level.w] == tile) { + if (!(occ - 1)) { + return (struct Vec2){n, m}; + } else { + --occ; + } + } + } + } + return (struct Vec2){0, 0}; +} + static void level_free(void) { diff --git a/src/main.c b/src/main.c index d4a5765..481f507 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include "main.h" #include "draw.h" +#include "hook.h" #include "input.h" #include "level.h" #include "player.h" @@ -45,5 +46,6 @@ draw(void) dclear(C_BLACK); level_draw(); player_draw(); + hook_debug_draw(); dupdate(); } diff --git a/src/player.c b/src/player.c index cfe776a..db983a7 100644 --- a/src/player.c +++ b/src/player.c @@ -1,14 +1,17 @@ #include "player.h" #include "conf.h" #include "draw.h" +#include "hook.h" #include "input.h" #include "level.h" #include "tools.h" -static int k_up, k_down, k_left, k_right, k_jump, k_jumpdown; +static int k_up, k_down, k_left, k_right, k_jump, k_jumpdown, k_hook; static struct Player player; static void player_get_input(void); static void player_move(struct Vec2 spd); +static void player_hook(void); +static void player_hook_draw(void); static struct Vec2 player_update_rem(); static int player_collide_pixel(int x, int y, tile_t id); static int player_collide(struct Vec2 pos, tile_t id, int h); @@ -21,6 +24,8 @@ player_init(void) player.rem = (struct FVec2){0.0f, 0.0f}; player.jumping = 1; player.airbreak = 1; + player.hooking = 0; + player.hook_pos = (struct Vec2){50, 50}; } void @@ -39,6 +44,11 @@ player_update(void) player.airbreak = 0; } + player.hooking = 0; + if (k_hook) { + player_hook(); + } + player.spd.x *= (1 - PLAYER_FRIC); player.spd.x += dir * PLAYER_ACC; player.spd.y += GRAVITY + GRAVITY * player.airbreak; @@ -51,13 +61,30 @@ player_update(void) } } +void +player_hook(void) +{ + player.hook_pos = hook_closest(&player.pos); + player.hooking = 1; +} + void player_draw(void) { - draw_rectangle(player.pos.x, player.pos.y, PLAYER_S, PLAYER_S, C_BLACK); + if (player.hooking) { + player_hook_draw(); + } + draw_rectangle(player.pos.x, player.pos.y, PLAYER_S, PLAYER_S, C_WHITE); dprint(10, 10, C_BLACK, "%d", player_collide(player.pos, 1, 0)); } +void +player_hook_draw(void) +{ + dline(player.pos.x + PLAYER_S / 2, player.pos.y + PLAYER_S / 2, + player.hook_pos.x, player.hook_pos.y, C_RED); +} + static void player_get_input(void) { @@ -67,6 +94,7 @@ player_get_input(void) k_right = input_down(K_RIGHT); k_jump = input_pressed(K_A); k_jumpdown = input_down(K_A); + k_hook = input_down(K_B); } static struct Vec2 diff --git a/src/tools.c b/src/tools.c index c6c0dd8..0ef58d4 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1,7 +1,18 @@ #include "tools.h" +#include +#include int sign(int x) { return (x > 0) - (x < 0); /* from jtmm2 */ } + +int +length(int x1, int y1, int x2, int y2) +{ + const int dist_x = abs(x1 - x2); + const int dist_y = abs(y1 - y1); + const float dist = sqrt(dist_x * dist_x + dist_y * dist_y); + return dist; +}