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>
47 lines
1.6 KiB
C
47 lines
1.6 KiB
C
/*
|
||
* sprite_moveto — запустить tween-перемещение к (tx,ty): раз в interval
|
||
* кадров тикер делает до max_step итераций Брезенхэма (большая ось —
|
||
* итерация = пиксель; меньшая подтягивается err-аккумулятором).
|
||
* Пример: (0,0)→(100,50), max_step 5, interval 4 → 20 шагов × 4 кадра
|
||
* = 80 кадров (1.6 с), Y идёт 2/3/2/3.
|
||
*
|
||
* Дельты/знаки/аккумулятор считаются здесь один раз. Если цель ==
|
||
* текущая позиция — сразу SPR_MOVE_DONE (тикер не включается).
|
||
* Кадровые статусы (SPR_ANIM_*) не трогаются.
|
||
*/
|
||
#include "../_bgi.h"
|
||
#include <sprite.h>
|
||
|
||
void sprite_moveto(sprite_t *s, int tx, int ty,
|
||
uint8_t max_step, uint8_t interval)
|
||
{
|
||
int dx = tx - s->x;
|
||
int dy = ty - s->y;
|
||
|
||
s->mv_sgnx = 1;
|
||
if (dx < 0) { dx = -dx; s->mv_sgnx = -1; }
|
||
s->mv_sgny = 1;
|
||
if (dy < 0) { dy = -dy; s->mv_sgny = -1; }
|
||
|
||
s->an_flags &= (uint8_t)~SPR_MOVE_DONE;
|
||
if (dx == 0 && dy == 0) {
|
||
s->an_flags = (s->an_flags & (uint8_t)~SPR_MOVE_ON) | SPR_MOVE_DONE;
|
||
return;
|
||
}
|
||
|
||
s->mv_tx = tx;
|
||
s->mv_ty = ty;
|
||
s->mv_dx = dx;
|
||
s->mv_dy = -dy;
|
||
s->mv_err = dx - dy;
|
||
|
||
if (!max_step) max_step = 1;
|
||
if (!interval) interval = 1;
|
||
s->mv_step = max_step;
|
||
s->mv_speed = interval;
|
||
s->mv_timer = interval;
|
||
|
||
s->an_flags |= SPR_MOVE_ON;
|
||
_spr_tick_fn = _sprite_tick;
|
||
}
|