diff --git a/assets/Extras/Explosion.png b/assets/Extras/Explosion.png new file mode 100644 index 00000000..39590995 Binary files /dev/null and b/assets/Extras/Explosion.png differ diff --git a/assets/Extras/SwordSwing.png b/assets/Extras/SwordSwing.png index bd8a7836..7ecede26 100644 Binary files a/assets/Extras/SwordSwing.png and b/assets/Extras/SwordSwing.png differ diff --git a/assets/Extras/TrippleSwing.png b/assets/Extras/TrippleSwing.png new file mode 100644 index 00000000..8ca0409a Binary files /dev/null and b/assets/Extras/TrippleSwing.png differ diff --git a/src/player.c b/src/player.c index 1313f347..5923941c 100644 --- a/src/player.c +++ b/src/player.c @@ -442,13 +442,74 @@ handle_next_move(UpdateData *data) } static void -use_skill(Skill *skill, SkillData *skillData) +update_skill_animations(Player *player) +{ + LinkedList *next = player->skillAnimations; + LinkedList *prev = NULL; + while (next != NULL) { + Animation *a = next->data; + if (!a->running) { + next->data = NULL; + if (prev) { + prev->next = next->next; + } else { + player->skillAnimations = next->next; + } + LinkedList *tmp = next; + next = next->next; + free(tmp); + continue; + } + animation_update(a); + prev = next; + next = next->next; + } +} + +static void +render_skill_animations(Player *player, Camera *cam) +{ + LinkedList *next = player->skillAnimations; + while (next != NULL) { + Animation *a = next->data; + animation_render(a, cam); + next = next->next; + } +} + +static void +destroy_skill_animations(LinkedList *skillAnimations) +{ + LinkedList *next = skillAnimations; + LinkedList *tmp; + while (next != NULL) { + tmp = next; + next = next->next; + free(tmp); + } +} + +static void +use_skill(Player *player, Skill *skill, SkillData *skillData) { skill->active = false; skill->use(skill, skillData); if (skill->actionRequired) action_spent(skillData->player); skill->resetCountdown = skill->resetTime; + + if (skill->animation) { + Animation *a = skill->animation; + + // Copy the orientation and position of the sword animation for the skill animation + // \see player_turn + a->sprite->pos = player->swordAnimation->sprite->pos; + a->sprite->flip = player->swordAnimation->sprite->flip; + a->sprite->angle = player->swordAnimation->sprite->angle; + + animation_run(a); + linkedlist_append(&player->skillAnimations, skill->animation); + } } static void @@ -487,7 +548,7 @@ check_skill_activation(UpdateData *data) skill->active = (selected - 1) == i && !skill->active && skill->resetCountdown == 0; if (skill->active && skill->instantUse) { SkillData skillData = { player, matrix, VECTOR2D_NODIR }; - use_skill(skill, &skillData); + use_skill(player, skill, &skillData); } } } @@ -515,7 +576,7 @@ check_skill_trigger(UpdateData *data) return false; SkillData skillData = { player, matrix, nextDir }; - use_skill(player->skills[activeSkill], &skillData); + use_skill(player, player->skills[activeSkill], &skillData); return true; } @@ -525,16 +586,16 @@ build_sword_animation(Player *p, SDL_Renderer *renderer) { animation_load_texture(p->swordAnimation, "Extras/SwordSwing.png", renderer); animation_set_frames(p->swordAnimation, (AnimationClip[]) { - { 0, 0, 16, 16, 20 }, - { 16, 0, 16, 16, 20 }, - { 32, 0, 16, 16, 20 }, - { 48, 0, 16, 16, 20 }, - { 64, 0, 16, 16, 20 } + { 0, 0, 32, 32, 20 }, + { 32, 0, 32, 32, 20 }, + { 64, 0, 32, 32, 20 }, + { 96, 0, 32, 32, 20 }, + { 128, 0, 32, 32, 20 } }); p->swordAnimation->loop = false; p->swordAnimation->sprite->dim = GAME_DIMENSION; - p->swordAnimation->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 }; + p->swordAnimation->sprite->clip = (SDL_Rect) { 0, 0, 32, 32 }; p->swordAnimation->sprite->rotationPoint = (SDL_Point) { 16, 16 }; } @@ -625,6 +686,8 @@ player_create(class_t class, Camera *cam) player->sprite->dim = GAME_DIMENSION; player->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 }; + player->skillAnimations = NULL; + return player; } @@ -736,6 +799,7 @@ void player_render_toplayer(Player *player, Camera *camera) { animation_render(player->swordAnimation, camera); + render_skill_animations(player, camera); } void @@ -788,6 +852,7 @@ player_update(UpdateData *data) player->projectiles = remaining; animation_update(player->swordAnimation); + update_skill_animations(player); uint32_t damage_taken = player->stats.maxhp - player->stats.hp; player->bleed_emitter->enabled = (int) damage_taken >= player->stats.maxhp / 2; @@ -821,6 +886,8 @@ player_destroy(Player *player) player->skills[i] = NULL; } + destroy_skill_animations(player->skillAnimations); + particle_emitter_destroy(player->bleed_emitter); free(player); diff --git a/src/player.h b/src/player.h index 0fd16803..3dcd6593 100644 --- a/src/player.h +++ b/src/player.h @@ -101,6 +101,7 @@ typedef struct Player { PlayerStateData stateData; PlayerEffects effects; ParticleEmitter *bleed_emitter; + LinkedList *skillAnimations; } Player; Player* diff --git a/src/skill.c b/src/skill.c index 9b77ae9d..7817cffb 100644 --- a/src/skill.c +++ b/src/skill.c @@ -18,6 +18,7 @@ #include #include +#include "defines.h" #include "texturecache.h" #include "skill.h" #include "util.h" @@ -306,6 +307,7 @@ create_default(const char *s_label, Sprite *s) skill->use = NULL; skill->levelcap = 1; skill->tooltip = NULL; + skill->animation = NULL; return skill; } @@ -402,7 +404,6 @@ skill_use_flurry(Skill *skill, SkillData *data) return false; } - animation_run(data->player->swordAnimation); Monster *monster = data->matrix->spaces[targetPos.x][targetPos.y].monster; mixer_play_effect(TRIPPLE_SWING); if (monster) { @@ -433,7 +434,7 @@ skill_use_flurry(Skill *skill, SkillData *data) } static Skill * -create_flurry(void) +create_flurry(Camera *cam) { Texture *t = texturecache_add("Extras/Skills.png"); Sprite *s = sprite_create(); @@ -444,6 +445,25 @@ create_flurry(void) Skill *skill = create_default("Flurry", s); skill->levelcap = 2; skill->use = skill_use_flurry; + skill->tooltip = tooltip_create(flurry_tooltip, cam); + skill->animation = animation_create(8); + + Animation *a = skill->animation; + animation_load_texture(a, "Extras/TrippleSwing.png", cam->renderer); + animation_set_frames(a, (AnimationClip[]) { + { 0, 0, 32, 32, 20 }, + { 32, 0, 32, 32, 20 }, + { 64, 0, 32, 32, 20 }, + { 96, 0, 32, 32, 20 }, + { 128, 0, 32, 32, 20 }, + { 160, 0, 32, 32, 20 }, + { 192, 0, 32, 32, 20 }, + { 224, 0, 32, 32, 20 } + }); + a->loop = false; + a->sprite->dim = GAME_DIMENSION; + a->sprite->clip = (SDL_Rect) { 0, 0, 32, 32 }; + a->sprite->rotationPoint = (SDL_Point) { 16, 16 }; return skill; } @@ -1016,8 +1036,7 @@ skill_create(enum SkillType t, Camera *cam) Skill *skill; switch (t) { case FLURRY: - skill = create_flurry(); - skill->tooltip = tooltip_create(flurry_tooltip, cam); + skill = create_flurry(cam); break; case VAMPIRIC_BLOW: skill = create_vampiric_blow(); @@ -1076,5 +1095,7 @@ skill_destroy(Skill *skill) sprite_destroy(skill->icon); if (skill->tooltip) tooltip_destroy(skill->tooltip); + if (skill->animation) + animation_destroy(skill->animation); free(skill); } diff --git a/src/skill.h b/src/skill.h index 6cf0232a..2524c6d0 100644 --- a/src/skill.h +++ b/src/skill.h @@ -20,6 +20,7 @@ #define SKILL_H_ #include +#include "animation.h" #include "roommatrix.h" #include "sprite.h" #include "vector2d.h" @@ -60,6 +61,7 @@ typedef struct Skill_t { bool (*available)(Player*); bool (*use)(struct Skill_t*, SkillData*); Tooltip *tooltip; + Animation *animation; } Skill; Skill*