#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, 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); void player_init(void) { player.pos = (struct Vec2){160, 100}; player.spd = (struct FVec2){0.0f, 0.0f}; 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 player_update(void) { player_get_input(); const int dir = k_right - k_left; if (player.jumping && (!k_jumpdown || player.spd.y > 0)) { player.airbreak = 1; } if (k_jump && !player.jumping) { player.spd.y = -PLAYER_JUMP; player.jumping = 1; 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; player_move(player_update_rem()); if (player_collide((struct Vec2){player.pos.x, player.pos.y + 1}, 1, 0)) { player.jumping = 0; } } void player_hook(void) { player.hook_pos = hook_closest(&player.pos); player.hooking = 1; } void player_draw(void) { 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) { k_up = input_down(K_UP); k_down = input_down(K_DOWN); k_left = input_down(K_LEFT); 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 player_update_rem(void) { struct FVec2 spdrem = (struct FVec2){player.spd.x + player.rem.x, player.spd.y + player.rem.y}; struct Vec2 ispd = (struct Vec2){spdrem.x, spdrem.y}; player.rem.x = spdrem.x - (float)ispd.x; player.rem.y = spdrem.y - (float)ispd.y; return ispd; } static void player_move(struct Vec2 spd) { if (player_collide(player.pos, 1, 0)) { return; } player_update_rem(); if (spd.x) { const int sign_x = sign(spd.x); player.pos.x += spd.x; if (player_collide(player.pos, 1, 0)) { player.spd.x = 0.0f; player.rem.x = 0.0f; while (player_collide(player.pos, 1, 0)) { player.pos.x -= sign_x; } } } if (spd.y) { const int sign_y = sign(spd.y); player.pos.y += spd.y; if (player_collide(player.pos, 1, 0)) { player.spd.y = 0.0f; player.rem.y = 0.0f; while (player_collide(player.pos, 1, 0)) { player.pos.y -= sign_y; } } } } static int player_collide_pixel(int x, int y, tile_t id) { const tile_t tile = level_get_px(x, y); if (!tile) { return 0; } if (id == 1) { return (tile - 1) % TILESET_W < 8; } return tile == id; } static int player_collide(struct Vec2 pos, tile_t id, int h) { const struct Vec2 pos_tl = (struct Vec2){pos.x + h, pos.y + h}; const struct Vec2 pos_br = (struct Vec2){pos.x + PLAYER_S - h - 1, pos.y + PLAYER_S - h - 1}; const struct Vec2 middle = (struct Vec2){pos.x + PLAYER_S / 2, pos.y + PLAYER_S / 2}; if (player_collide_pixel(pos_tl.x, pos_tl.y, id) || player_collide_pixel(pos_br.x, pos_br.y, id) || player_collide_pixel(pos_tl.x, pos_br.y, id) || player_collide_pixel(pos_br.x, pos_tl.y, id) || player_collide_pixel(middle.x, pos_tl.y, id) || player_collide_pixel(middle.x, pos_br.y, id) || player_collide_pixel(pos_tl.x, middle.y, id) || player_collide_pixel(pos_br.x, middle.y, id)) { return 1; } return 0; }