#include "sandbag.h" #include "attack.h" #include "level.h" #include "conf.h" #include "tools.h" #include "lzy.h" #include "particle.h" static struct Sandbag sandbag; static void sandbag_move(struct Vec2 spd); static struct Vec2 sandbag_update_rem(); static int sandbag_collide_pixel(int x, int y, tile_t id); static int sandbag_collide(int x, int y, tile_t id, int h); void sandbag_init(void) { sandbag.pos = (struct Vec2){300, 96}; sandbag.spd = (struct FVec2){0.0f, 0.0f}; sandbag.rem = (struct FVec2){0.0f, 0.0f}; sandbag.dir = (struct Vec2){1, 0}; sandbag.hitstun = 0; sandbag.iced = 0; sandbag.life = 0; sandbag.active = 1; } void sandbag_update(int frame) { const struct Vec2 level_dim = level_get_dim(); if(!sandbag.active) return; const struct Attack *attack = attack_table_collide(sandbag.pos.x, sandbag.pos.y, 24, 24, 0); if(attack != NULL) { sandbag.spd.x = attack->dir.x * 5 * (sandbag.life > 50 ? (float)sandbag.life / 50 : 1); sandbag.spd.y = -attack->dir.y * 5 * (sandbag.life > 50 ? (float)sandbag.life / 100 + 0.5 : 1); if(!sandbag.hitstun) { sandbag.life += attack->dam; LZY_Sleep(10); }; sandbag.hitstun = 5; if(attack->ice) {sandbag.iced = 30;} } sandbag.spd.x *= (1 - AIR_FRIC) / (sandbag.iced ? 2 : 1); sandbag.spd.y += GRAVITY; if (sandbag.spd.x) { sandbag.dir.x = sign(sandbag.spd.x); } sandbag_move(sandbag_update_rem()); if(sandbag.hitstun > 0) {sandbag.hitstun -= 1;} if(sandbag.iced > 0) {sandbag.iced -= 1;} if(sandbag.hitstun && frame % 2 && sandbag.life > 80) { particle_new(sandbag.pos.x + 12, sandbag.pos.y + 12, 10 + rand() % 2, 5); } if(frame % 4 && sandbag.life > 120) { particle_new(sandbag.pos.x + 12, sandbag.pos.y + 12, 12 + (frame % 8) / 2 % 2, 2); } if(sandbag.pos.x > level_dim.x * TILE_S + 48 || sandbag.pos.x < -72 || sandbag.pos.y > level_dim.y * TILE_S + 48 || sandbag.pos.y < -96) { sandbag_init(); } } static struct Vec2 sandbag_update_rem(void) { struct FVec2 spdrem = (struct FVec2){sandbag.spd.x + sandbag.rem.x, sandbag.spd.y + sandbag.rem.y}; struct Vec2 ispd = (struct Vec2){spdrem.x, spdrem.y}; sandbag.rem.x = spdrem.x - (float)ispd.x; sandbag.rem.y = spdrem.y - (float)ispd.y; return ispd; } static void sandbag_move(struct Vec2 spd) { if (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 4)) { return; } /* OOB */ const struct Vec2 level_dim = level_get_dim(); int coll_shift = 0; const int sign_x = sign(spd.x); if (sign_x) {sandbag.dir.x = sign_x;} if (spd.x) { sandbag.pos.x += spd.x; if (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { for(float i = 0.1f; i < 4; i+= 0.1) { if(!sandbag_collide(sandbag.pos.x, sandbag.pos.y + i, 1, 1)) { sandbag.pos.y += i; coll_shift = 1; break; } if(!sandbag_collide(sandbag.pos.x, sandbag.pos.y - i, 1, 1)) { sandbag.pos.y -= i; coll_shift = 1; break; } } } if(sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { if(abs(sandbag.spd.x) > 16) { sandbag.spd.x = - sandbag.spd.x / 4; } else { sandbag.spd.x = 0.0f; } sandbag.rem.x = 0.0f; while (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { sandbag.pos.x -= sign_x; } } } const int sign_y = sign(spd.y); if (sign_y) {sandbag.dir.y = sign_y;} if (spd.y && !coll_shift) { sandbag.pos.y += spd.y; if (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { for(float i = 0.1f; i < 4; i += 0.1) { if(!sandbag_collide(sandbag.pos.x + i, sandbag.pos.y, 1, 1)) { sandbag.pos.x += i; break; } if(!sandbag_collide(sandbag.pos.x - i, sandbag.pos.y, 1, 1)) { sandbag.pos.x -= i; break; } } } if(sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { if(abs(sandbag.spd.y) > 16) { sandbag.spd.y = - sandbag.spd.y / 4; } else { sandbag.spd.y = 0.0f; } sandbag.rem.y = 0.0f; while (sandbag_collide(sandbag.pos.x, sandbag.pos.y, 1, 1)) { sandbag.pos.y -= sign_y; } } } } void sandbag_draw(int frame) { if(!sandbag.active) return; if(sandbag.hitstun) { LZY_DrawTile(39, sandbag.pos.x, sandbag.pos.y); } else { LZY_DrawTile(38, sandbag.pos.x, sandbag.pos.y); } if(sandbag.iced > 0) { LZY_DrawTile(16, sandbag.pos.x, sandbag.pos.y); } } static int sandbag_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 sandbag_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 (sandbag_collide_pixel(pos_tl.x, pos_tl.y, id) || sandbag_collide_pixel(pos_br.x, pos_br.y, id) || sandbag_collide_pixel(pos_tl.x, pos_br.y, id) || sandbag_collide_pixel(pos_br.x, pos_tl.y, id)) { return 1; } return 0; } int sandbag_get_life(void) { return sandbag.life; }