#include "player.h" #include "attack.h" #include "conf.h" #include "level.h" #include "lzy.h" #include "particle.h" #include "tools.h" static struct Player player; static void player_move(struct Vec2 spd); static struct Vec2 player_update_rem(); static int player_collide_pixel(int x, int y, tile_t id); static int player_collide(int x, int y, tile_t id, int h); static void player_attack(int x, int y, int type); static void player_cooldown_update(); static int jump_pressed; void player_init(int chara) { player.pos = (struct Vec2){84, 96}; player.spd = (struct FVec2){0.0f, 0.0f}; player.rem = (struct FVec2){0.0f, 0.0f}; player.dir = (struct Vec2){1, 0}; player.cooldown = (struct Cooldown){0, 0, 0, 0}; player.attack = 0; player.last_attack = 0; player.life = 0; player.id = chara; player.djump = 0; } void player_update(void) { const int on_ground = player_collide(player.pos.x, player.pos.y + 5, 1, 4); if (on_ground) player.djump = 1; const struct Vec2 level_dim = level_get_dim(); const struct Vec2 dir = {LZY_KeyDown(LZYK_RIGHT) - LZY_KeyDown(LZYK_LEFT), LZY_KeyDown(LZYK_DOWN) - LZY_KeyDown(LZYK_UP)}; player.spd.x *= (1 - PLAYER_FRIC); player.spd.x += dir.x * PLAYER_ACC; player.spd.y += GRAVITY * (player.last_attack == 4 && player.id == 1 ? -1 : 1); /* direction */ if (dir.y) { player.dir.y = dir.y; } if (dir.x) { player.dir.x = dir.x; } if (LZY_KeyDown(LZYK_O)) { if (on_ground) { player.spd.y = -JUMP_H; jump_pressed = 1; } else if (player.djump && !jump_pressed) { player.spd.y = -JUMP_H; player.djump = 0; particle_new(player.pos.x + PLAYER_W / 2, player.pos.y + PLAYER_H, 10, 5); } } if (jump_pressed && !LZY_KeyDown(LZYK_O)) { jump_pressed = 0; } if (player_collide(player.pos.x, player.pos.y + 5, 176, 4)) { player.spd.y = -16; } if (player_collide(player.pos.x, player.pos.y + 5, 153, 4)) { player.spd.y = -3 * 5 * (player.life > 50 ? (float)player.life / 100 + 0.5 : 1); player.spd.x = -player.dir.x * 5 * (player.life > 50 ? (float)player.life / 100 + 0.5 : 1); player.life += 10; } player_move(player_update_rem()); /* defining the direction of the shoot */ const struct Vec2 shoot = {(dir.x || dir.y) ? dir.x : player.dir.x, (dir.x || dir.y) ? dir.y : player.dir.y}; if (LZY_KeyDown(LZYK_X) && !player.last_attack) { player_attack(player.pos.x, player.pos.y, 1); } if (!LZY_KeyDown(LZYK_X)) { player.last_attack = 0; } player_cooldown_update(); if (player.pos.x > level_dim.x * TILE_S + 48 || player.pos.x < -72 || player.pos.y > level_dim.y * TILE_S + 48 || player.pos.y < -96) { player_init(player.id); } } static void player_attack(int x, int y, int type) { const int up = LZY_KeyDown(LZYK_UP); const int down = LZY_KeyDown(LZYK_DOWN); const int left = LZY_KeyDown(LZYK_LEFT); const int right = LZY_KeyDown(LZYK_RIGHT); if (down && !player.cooldown.down) { player.cooldown.down = attack(x + PLAYER_W / 2, y + PLAYER_H / 2 + 12, player.dir.x, 1, 2 + player.id * 4); player.attack = 2; player.last_attack = 2; return; } if (up && !player.cooldown.up) { player.cooldown.up = attack(x + PLAYER_W / 2, y + PLAYER_H / 2 - 12, player.dir.x, 1, 3 + player.id * 4); player.attack = 3; player.last_attack = 3; return; } if ((left || right) && !player.cooldown.side) { player.cooldown.side = attack(x + PLAYER_W / 2 + player.dir.x * 12, y + PLAYER_H / 2, player.dir.x, 1, 1 + player.id * 4); player.attack = 1; player.last_attack = 1; return; } if (!(up || down || left || right) && !player.cooldown.neutral) { player.cooldown.neutral = attack(x + PLAYER_W / 2, y + PLAYER_H / 2, player.dir.x, 1, 4 + player.id * 4); player.attack = 4; player.last_attack = 4; } } 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.x, player.pos.y, 1, 4)) { return; } int coll_shift = 0; const int sign_x = sign(spd.x); if (sign_x) { player.dir.x = sign_x; } if (spd.x) { player.pos.x += spd.x; if (player_collide(player.pos.x, player.pos.y, 1, 1)) { for (float i = 0.1f; i < 4; i += 0.1) { if (!player_collide(player.pos.x, player.pos.y + i, 1, 1)) { player.pos.y += i; coll_shift = 1; break; } if (!player_collide(player.pos.x, player.pos.y - i, 1, 1)) { player.pos.y -= i; coll_shift = 1; break; } } } if (player_collide(player.pos.x, player.pos.y, 1, 1)) { player.spd.x = 0.0f; player.rem.x = 0.0f; while (player_collide(player.pos.x, player.pos.y, 1, 1)) { player.pos.x -= sign_x; } } } const int sign_y = sign(spd.y); if (sign_y) { player.dir.y = sign_y; } if (spd.y && !coll_shift) { player.pos.y += spd.y; if (player_collide(player.pos.x, player.pos.y, 1, 1)) { for (float i = 0.1f; i < 4; i += 0.1) { if (!player_collide(player.pos.x + i, player.pos.y, 1, 1)) { player.pos.x += i; break; } if (!player_collide(player.pos.x - i, player.pos.y, 1, 1)) { player.pos.x -= i; break; } } } if (player_collide(player.pos.x, player.pos.y, 1, 1)) { player.spd.y = 0.0f; player.rem.y = 0.0f; while (player_collide(player.pos.x, player.pos.y, 1, 1)) { player.pos.y -= sign_y; } } } } void player_draw(int frame) { if (player.attack) { LZY_DrawTile(24 + TILESET_W * player.id + player.attack + (player.dir.x > 0 ? 0 : 1) * 6, player.pos.x, player.pos.y); } else { if (LZY_KeyDown(LZYK_X)) { LZY_DrawTile(24 + player.last_attack + TILESET_W * player.id + (player.dir.x > 0 ? 0 : 1) * 6, player.pos.x, player.pos.y); } else { LZY_DrawTile((frame % 30 > 15 ? 23 : 24) + TILESET_W * player.id + (player.dir.x > 0 ? 0 : 1) * 6, player.pos.x, player.pos.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) % TILESET_W; } return tile == id; } static int player_collide(int x, int y, tile_t id, int h) { const struct Vec2 pos_tl = (struct Vec2){x + h, y + h}; const struct Vec2 pos_br = (struct Vec2){x + PLAYER_S - h - 1, y + PLAYER_S - h - 1}; const struct Vec2 middle = (struct Vec2){x + PLAYER_S / 2, 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)) { return 1; } return 0; } void player_reset_attack() { player.attack = 0; } void player_cooldown_update() { if (player.cooldown.up > 0) player.cooldown.up -= 1; if (player.cooldown.down > 0) player.cooldown.down -= 1; if (player.cooldown.side > 0) player.cooldown.side -= 1; if (player.cooldown.neutral > 0) player.cooldown.neutral -= 1; } int player_get_life(void) { return player.life; }