eb9ca0179d
Реализация §9г по требованиям пользователя: - sprite_anim(first,last,speed,mode): ANIM_LOOP / ANIM_PINGPONG / ANIM_ONCE (one-shot замирает на last), | ANIM_HORIZ для горизонтальных лент. Смена кадра в тике = ±an_step к оси ленты — без умножений (осевое смещение first считается в setup циклом). - sprite_moveto(tx,ty,max_step,interval): Брезенхэм порциями ≤max_step вдоль большей оси (меньшая — err-аккумулятором, нелинейные шаги Y сами собой), деления нет. - Одновременность кадровой и tween — независимые поля/биты. - Статус: sprite_anim_status() — битовое поле SPR_ANIM_ON/DONE + SPR_MOVE_ON/DONE; sprite_anim_frame() — текущий индекс кадра; sprite_moving(). - Стопы: sprite_anim_stop(frame | -1 = текущий); sprite_move_stop(0 = замереть / 1 = прыжок в цель + DONE). - Тикер _sprite_tick — проход 0 sprite_update через funcptr _spr_tick_fn (DCE: без sprite_anim/moveto код не линкуется, цена — один if на кадр; +40 Б программе с движком, sprite_t +18 Б). tests/spranim (MAME dev, все PASS): LOOP/PINGPONG (разворот на границе без удвоения краёв)/ONCE+DONE; пример (0,0)→(100,50), шаг 5, интервал 4 → ровно 80 кадров, Y идёт 3/2/3/2; стопы обоих видов. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
55 lines
2.0 KiB
C
55 lines
2.0 KiB
C
/*
|
|
* 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 <sprite.h>
|
|
|
|
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;
|
|
}
|