/* * sprite_anim — запустить кадровую авто-анимацию: кадры first..last * вдоль оси ленты (вертикальная; ANIM_HORIZ — вдоль X), смена раз в * speed кадров, mode = ANIM_LOOP / ANIM_PINGPONG / ANIM_ONCE. * * Всё дорогое считается ЗДЕСЬ один раз (не в тике): шаг оси = размер * кадра, осевое смещение first — циклом сложений (без __mulint). * Ставит текущий кадр на first, сбрасывает SPR_ANIM_DONE, подключает * тикер (_spr_tick_fn) — до первого вызова sprite_anim/sprite_moveto * код тикера в программу не линкуется. Требование: индексы ≤ 127, * first ≤ last. Move-статусы (SPR_MOVE_*) не трогаются. */ #include "../_bgi.h" #include void sprite_anim(sprite_t *s, uint8_t first, uint8_t last, uint8_t speed, uint8_t mode) { uint8_t f = s->an_flags & (SPR_MOVE_ON | SPR_MOVE_DONE); uint8_t step = (mode & ANIM_HORIZ) ? s->w : s->h; int lo = 0; uint8_t i; for (i = 0; i < first; i++) lo += step; /* first*step без умножения */ if (!speed) speed = 1; s->an_step = step; s->an_lo = lo; s->an_first = first; s->an_last = last; s->an_frame = first; s->an_speed = speed; s->an_timer = speed; f |= SPR_ANIM_ON; if (mode & ANIM_HORIZ) f |= _SPR_ANIM_HORZ; if ((mode & 0x03u) == ANIM_PINGPONG) f |= _SPR_ANIM_PP; if ((mode & 0x03u) == ANIM_ONCE) f |= _SPR_ANIM_ONCE; s->an_flags = f; /* Ось — на кадр first (обычный путь sprite_frame: dirty при смене). */ if (mode & ANIM_HORIZ) sprite_frame(s, lo, s->sy); else sprite_frame(s, s->sx, lo); _spr_tick_fn = _sprite_tick; }