#include "anim.h" #include #include /* Definition of simple and direction animations. */ #define ANIM1(name) \ extern anim_frame_t frames_ ## name[]; \ anim_t anims_ ## name = { 1, { frames_ ## name }}; #define ANIM_2DIRECTIONAL(prefix, suffix) \ extern anim_frame_t frames_ ## prefix ## _left ## suffix[]; \ extern anim_frame_t frames_ ## prefix ## _right ## suffix[]; \ anim_t anims_ ## prefix ## suffix = { 2, { \ frames_ ## prefix ## _left ## suffix, \ frames_ ## prefix ## _right ## suffix, \ }}; \ #define ANIM_4DIRECTIONAL(prefix, suffix) \ extern anim_frame_t frames_ ## prefix ## _up ## suffix[]; \ extern anim_frame_t frames_ ## prefix ## _right ## suffix[]; \ extern anim_frame_t frames_ ## prefix ## _down ## suffix[]; \ extern anim_frame_t frames_ ## prefix ## _left ## suffix[]; \ anim_t anims_ ## prefix ## suffix = { 4, { \ frames_ ## prefix ## _up ## suffix, \ frames_ ## prefix ## _right ## suffix, \ frames_ ## prefix ## _down ## suffix, \ frames_ ## prefix ## _left ## suffix, \ }}; /* Make suffix optional */ #define ANIM2(prefix, ...) \ ANIM_2DIRECTIONAL(prefix, __VA_OPT__(_ ## __VA_ARGS__)) #define ANIM4(prefix, ...) \ ANIM_4DIRECTIONAL(prefix, __VA_OPT__(_ ## __VA_ARGS__)) /* Basic skills */ ANIM1(skill_hit); ANIM2(skill_projectile); ANIM1(skill_teleport); ANIM1(skill_shock); ANIM1(skill_judgement); ANIM1(skill_launch); /* Directional skills */ ANIM4(skill_swing); ANIM4(skill_impale); ANIM4(skill_bullet); ANIM4(skill_magic); /* Enemies */ ANIM_ENEMIES(ANIM2) /* Player */ ANIM4(player, Idle); ANIM4(player, Walking); ANIM4(player, Attack); ANIM4(player, Hit); ANIM4(player, KO); ANIM4(player, IdleKO); /* HUD */ ANIM1(hud_xp_Idle); ANIM1(hud_xp_Shine); ANIM1(hud_xp_Explode); ANIM1(hud_backpack_Idle); ANIM1(hud_backpack_Open); ANIM1(hud_backpack_InventoryOpen); ANIM1(hud_backpack_InventoryIdle); ANIM1(hud_backpack_InventoryClose); /* Items */ ANIM1(item_life); ANIM1(item_chest); ANIM1(item_potion_atk); ANIM1(item_potion_cooldown); ANIM1(item_potion_def); ANIM1(item_potion_frz); ANIM1(item_potion_hp); ANIM1(item_potion_spd); ANIM1(item_stick1); ANIM1(item_stick2); ANIM1(item_sword1); ANIM1(item_sword2); ANIM1(item_armor1); ANIM1(item_buff); /* Animation functions. */ fixed_t (anim_duration)(anim_t const *anim) { anim_frame_t const *frame = anim->start[0]; int ms = 0; int i = 0; while(frame == anim->start[0] + i) { ms += frame->duration; frame = frame->next; i++; } return fix(ms) / 1000; } bool anim_in(anim_frame_t const *frame, anim_t const *anim, int index) { if(index >= anim->directions || !frame || !anim) return false; anim_frame_t *f = anim->start[index]; for(int i = 0; f == anim->start[index] + i; i++) { if(f == frame) return true; f = f->next; } return false; } void anim_frame_render(int x, int y, anim_frame_t const *frame) { if(!frame) return; dsubimage(x - frame->cx, y - frame->cy, frame->sheet, frame->x, frame->y, frame->w, frame->h, DIMAGE_NONE); } void anim_frame_subrender(int x, int y, anim_frame_t const *frame, int left, int top, int width, int height) { if(!frame) return; if(width < 0) width = frame->w; if(height < 0) height = frame->h; /* Basic clipping */ if(left < 0) width += left, left = 0; if(top < 0) height += top, top = 0; width = min(width, frame->w - left); height = min(height, frame->h - top); dsubimage(x - frame->cx, y - frame->cy + top, frame->sheet, frame->x + left, frame->y + top, width, height, DIMAGE_NONE); } bool anim_state_update(anim_state_t *state, fixed_t dt) { if(!state->frame) return false; state->elapsed += fround(dt * 1000); if(state->elapsed < state->frame->duration) return false; // TODO: FIXME: This is incorrect if the next animation is just behind bool transitioning = (state->frame->next != state->frame + 1); /* Switch to next frame */ state->elapsed -= state->frame->duration; state->frame = state->frame->next; return transitioning; }