Musisz zadeklarować sobie macierz dwuwymiarową, gdzie jeden wymiar oznacza indeks klatki, a drugi indeks "stawu" - ruchomego punktu; Poniżej masz przykładową definicję takiej macierzy:
const
GUY_POINTS_COUNT = 5;
FRAMES_COUNT = 6;
const
TOP_INDEX = 0;
LEFT_KNEE = 1;
LEFT_FOOT = 2;
RIGHT_KNEE = 3;
RIGHT_FOOT = 4;
const
GUY_FRAMES: array [0 .. FRAMES_COUNT - 1, 0 .. GUY_POINTS_COUNT - 1] of TPoint =
(
// TOP_INDEX | LEFT_KNEE | LEFT_FOOT | RIGHT_KNEE | RIGHT_FOOT
((X: 23; Y: 0), (X: 14; Y: 26), (X: 02; Y: 45), (X: 35; Y: 26), (X: 44; Y: 47)), // FRAME 0
((X: 23; Y: 0), (X: 17; Y: 27), (X: 04; Y: 45), (X: 32; Y: 27), (X: 36; Y: 47)), // FRAME 1
((X: 23; Y: 0), (X: 24; Y: 27), (X: 14; Y: 43), (X: 28; Y: 27), (X: 29; Y: 47)), // FRAME 2
((X: 23; Y: 0), (X: 29; Y: 27), (X: 22; Y: 43), (X: 24; Y: 27), (X: 24; Y: 47)), // FRAME 3
((X: 23; Y: 0), (X: 31; Y: 27), (X: 31; Y: 43), (X: 20; Y: 28), (X: 16; Y: 47)), // FRAME 4
((X: 23; Y: 0), (X: 33; Y: 26), (X: 38; Y: 45), (X: 13; Y: 27), (X: 05; Y: 47)) // FRAME 5
);
Każda kolumna zawiera współrzędne danego punktu ciała w poszczególnych klatkach, a każdy wiersz zawiera wszystkie punkty jednej klatki (po jednym punkcie dla każdego punku ciała - oznaczone komentarzami); Współrzędne punktów musisz sobie ustalić sam - ja dobrałem współrzędne pięciu punktów ("miednica", lewe kolano, lewa stopa, prawe kolano i prawa stopa) dla sześciu klatek;
Teraz do klasy formularza dodajesz pole typu np. TBitmap
, które tworzysz w konstruktorze formularza; Ustawiasz mu odpowiedni rozmiar i kolor tła; Dodajesz także pole przechowujące indeks aktualnej klatki, po czym w konstruktorze formularza przypisujesz mu wartość 0
(czyli indeks pierwszej klatki);
Następnie dodajesz do formularza komponent klasy TTimer
i ustawisz mu odpowiedni interwał (w zależności od tego ile klatek ma być wyświetlanych na sekundę); W zdarzeniu OnTimer
tego komponentu oprogramowujesz rysowanie jednej klatki; Wszystko rysujesz na tymczasowej klatce (dodatkowe pole klasy formularza) - linie wszystkich kawałków ludzika, ewentualnie możesz dodać kwadraciki w miejscach stawów, aby polepszyć efekt; W przykładowej aplikacji wygląda to tak:
procedure TForm1.tmrAnimationTimer(Sender: TObject);
procedure BodyLine(ACanvas: TCanvas; const AFirst, ASecond: TPoint);
begin
// line from AFirst to ASecond with offset
ACanvas.MoveTo(FRAME_OFFSET + AFirst.X, FRAME_OFFSET + AFirst.Y);
ACanvas.LineTo(FRAME_OFFSET + ASecond.X, FRAME_OFFSET + ASecond.Y);
end;
procedure BodyPoint(ACanvas: TCanvas; const APoint: TPoint);
begin
// draw rectangle at body point
ACanvas.Rectangle(FRAME_OFFSET + APoint.X - 2, FRAME_OFFSET + APoint.Y - 2,
FRAME_OFFSET + APoint.X + 1, FRAME_OFFSET + APoint.Y + 1);
end;
begin
with FFrame do
begin
// clear background
Canvas.FillRect(Canvas.ClipRect);
// draw all body lines
Canvas.Pen.Color := clGray;
BodyLine(Canvas, GUY_FRAMES[FFrameIdx, TOP_INDEX], GUY_FRAMES[FFrameIdx, LEFT_KNEE]);
BodyLine(Canvas, GUY_FRAMES[FFrameIdx, LEFT_KNEE], GUY_FRAMES[FFrameIdx, LEFT_FOOT]);
BodyLine(Canvas, GUY_FRAMES[FFrameIdx, TOP_INDEX], GUY_FRAMES[FFrameIdx, RIGHT_KNEE]);
BodyLine(Canvas, GUY_FRAMES[FFrameIdx, RIGHT_KNEE], GUY_FRAMES[FFrameIdx, RIGHT_FOOT]);
// draw all body points
Canvas.Pen.Color := clRed;
BodyPoint(Canvas, GUY_FRAMES[FFrameIdx, TOP_INDEX]);
BodyPoint(Canvas, GUY_FRAMES[FFrameIdx, LEFT_KNEE]);
BodyPoint(Canvas, GUY_FRAMES[FFrameIdx, LEFT_FOOT]);
BodyPoint(Canvas, GUY_FRAMES[FFrameIdx, RIGHT_KNEE]);
BodyPoint(Canvas, GUY_FRAMES[FFrameIdx, RIGHT_FOOT]);
// copy temporary frame
imgGuy.Picture.Bitmap.Assign(FFrame);
// clear temporary frame
Canvas.FillRect(Canvas.ClipRect);
end;
// increment frame index
Inc(FFrameIdx);
if FFrameIdx = FRAMES_COUNT then
FFrameIdx := 0;
end;
Po ich namalowaniu "kopiujesz" tymczasową klatkę do komponentu metodą Assign
(czy rysujesz ją bezpośrednio na formularzu), po czym ją czyścisz metodą FillRect
(Brush
tymczasowej klatki ustalasz na początku przy jej tworzeniu w pamięci w konstruktorze klasy okna); Po skopiowaniu klatki inkrementujesz licznik aktualnej klatki i sprawdzasz, czy się przekręcił; Jeśli tak - przypisujesz mu wartość 0
, aby animacja ruszyła od początku;
To wszystko - przykładowe klatki animacji dla samych nóg:
Jak widać nie wygląda źle; Możesz sobie jeszcze dodać kilka fiuczerów do np. manipulowania ilością wyświetlanych klatek na sekundę (dodać komponent np. klasy TSpinEdit
) lub inne dodatki jak np. linia podłoża:
Do swojej wersji musisz zwiększyć ilość punktów (zwiększyć drugi wymiar macierzy GUY_FRAMES
i odpowiednio ustawić stałą GUY_POINTS_COUNT
) i ew. ilość klatek dla większej płynności animacji; W załaczniku dodaję aplikację widniejącą na powyższym obrazku - zobacz sobie jak działa i dostosuj pod swoje wymagania.