Animacje
Podstawowe informacje
Przede wszystkim musisz wiedzieć, że taka animacja to nic innego jak pętla, która powoduje ciągłe rysowanie danego napisu, tyle, że za każdym razem w innym miejscu.
Na początek użytkownik musi mieć możliwość przerwania animacji w dowolnym momencie. W sekcji Interface stwórz dwie zmienne:
var DText : String; // tekst, który będzie wyświetlony na formie Done : Boolean; // jeżeli TRUE to animacja jest zakończona
Pierwsza z nich oznaczać będzie tekst, który będzie wyświetlany. Druga zmienna ma wartość True, jeżeli animacja została zakończona.
Do sekcji private dodaj dwie deklaracje procedur, które powodować będą wyświetlanie animacji, tyle, że dwóch różnych.
private procedure DrawAnim(X, Y : Integer); procedure SteepBySteep(X, Y : Integer);
Zajmijmy się pierwszą z procedur. Zawiera dwa parametry - X i Y. Wywołując procedurę musimy podać dwa parametry położenia początkowego napisu.
Piszemy potrzebną procedurę...
Najpierw zaprezentuje Ci pierwszą z procedur. Ma ona za zadanie przesuwanie tekstu z jednego krańca do drugiego. Tekst będzie 3D.
procedure TMainForm.DrawAnim(X, Y: Integer); var B : TBitmap; // Bitmapa i : Integer; begin B := TBitmap.Create; // utwórz bitmapę B.Height := 40; // wysokość bitmapy B.Width := Canvas.TextWidth(DText) * 10; // szerokość bitmapy B.Canvas.Font.Name := 'Courier New'; // czcionka B.Canvas.Font.Size := 14; // rozmiar czcionki B.Canvas.Brush.Color := Color; // kolor tła // stwórz obszar na którym bitmapa ma być wyświetlana B.Canvas.FillRect(Rect(0, 0, Canvas.TextWidth(DText) * 10, 40)); while not (Done) do // Jeżeli Done=False... begin // zacznij odtwarzanie animacji for i:= X to Width do // zacznij od punktu X to końca formy begin Application.ProcessMessages; // daj odetchnąć systemowi Sleep(10); // czekaj 1 milisekundę B.Canvas.Font.Color := clWhite; // kolor na biały B.Canvas.TextOut(10, 10, DText); // wyświetlenie tekstu B.Canvas.Brush.Style := bsClear; // tło na przezroczyste B.Canvas.Font.Color := clBlack; // kolor czcionki: czarny B.Canvas.TextOut(9, 9, DText); // wyświetl tekst jeszcze raz Canvas.Draw(I, Y, B); // wyświetl bitmapę if (Done) then // Jeżeli ktoś przerwał animacje ( Done=True )... Break; // ... to przerwij odtwarzanie animacji end; end; B.Free; // zwolnij pamięć dla zmiennej end;
Nie przerażaj się wielkością kodu tej procedury. Wszystko wyjaśnię po kolei. Animacja nie jest wyświetlana bezpośrednio na Canvasie, ale na bitmapie, która jest tworzona podczas wykonywania programu. Dlaczego? Gdyż dzięki temu nie dostrzeżesz niewygodnego efektu migania.
Najważniejsza część znajduje się na początku. Następuje tu bowiem stworzenie bitmapy oraz wyznaczenie jej szerokości oraz wysokości i koloru tła, czcionki. Później pętla - jedna zagnieżdżona w drugiej. Pętla while ma za zadanie sprawdzać, czy zmienna Done ma wartość True, czy False. Jeżeli FALSE ( kontynuuj animacje ) wykonywana jest pętla for, która ma z kolei za zadanie przesuwanie tekstu. Przesuwanie będzie następowało od wartości, która jest zadeklarowana pod zmienną X do samego końca formy. Zwróć uwagę na bardzo ważne polecenie, które jest w pętli - Application.ProcessMessages. Powoduje ono, że system się nie "zawisza" i można wykonywać inne czynności. Kolejne określa odstęp czasu jaki upłynie między przesunięciem się napisu o jeden punkt. Później następuje narysowanie tekstu czcionką białą, a następnie zmiana tej czcionki na czarną i PONOWNE narysowanie tego samego tekstu tyle, że przesuniętego o jeden punkt - daje to efekt cienia. No i na końcu narysowanie bitmapy na formie ( polecenie Draw ). Pozostaje jeszcze sprawdzenie, czy zmienna Done ma wartość True ( jeżeli tak to animacja zostaje przerwana poleceniem Break ).
Jeżeli chcesz, aby animacja została przerwana w dowolnym miejscu programu umieszczasz kod:
Done := TRUE;
Literka po literce
Jeszcze jeden przykład animacji - maszyna do pisania - jedna literka po drugiej pojawiają się na ekranie dając efekt pisanego tekstu. Będzie to prostszy przykład. Polega on na rozdzieleniu liter w danym wyrazie i rysowaniu jednej do drugiej. Jest to trochę skomplikowane z tego względu iż w czcionkach każda litera ma różną szerokość w pikselach. Rozwiązaniem jest zastosowanie czcionki Courier New, której litery mają taką samą szerokość.
procedure TMainForm.SteepBySteep(X, Y: Integer); var TextLength, I: Integer; begin Done := TRUE; // skończ poprzednia animacje TextLength := Length(DText); // pobierz długość tekstu with Canvas do begin for I := 1 to TextLength do // pętelka... begin Application.ProcessMessages; Sleep(100); // czekają 100 milisekund Brush.Style := bsClear; // styl na przezroczysty Font.Name := 'Courier New'; // czcionka Font.Color := clWhite; // kolor czcionki - biały Font.Size := 16; // rozmiar { Wyświetlaj tekst jedna litera po drugiej z przesunięciem } TextOut((X + i * 16), Y, DText[i]); Brush.Style := bsClear; Font.Color := clBlack; // wyswietl ten sam tekst w innym położeniu - efekt cienia TextOut((X + i * 16) -2, Y -2, DText[i]); end; end; end;
Na samym początku tej procedury pobierana jest ( do zmiennej TextLength ) długość tekstu w znakach. Później pętla wykonywana jest tyle razy ile znaków ma dany wyraz. Następnie polecenia, które już znasz, czyli przypisanie odpowiedniej czcionki oraz koloru i kroju. Później najtrudniejsza część zadania, czyli samo narysowanie litery. Należy określić wartość X ( w pierwszym parametrze ). Wszystko jest mnożone przez 16 i to daje odstęp i w rezultacie narysowanie litery. Później zmiana koloru czcionki i narysowanie litery jeszcze raz, tyle, że z przesunięciem co znowu daje efekt cienia.
To tylko proste animacje - kolejny krok to wykorzystanie OpenGL'a. Kurs taki możesz znaleźć w dziale Kursy.
Animacje tekstowe
Zanim skończę jeszcze trochę o animacjach. Tym razem tekstowa - maszyna do pisania. Tekst, litera po literze przelatujący na pasku aplikacji. Zrobimy tak, że na pasku linia po linii będzie mógł zostać wyświetlony cały tekst. Taką linię umieść w sekcji private:
procedure Go(const PText : TStrings);
Zauważ, że posiada ona parametr, który jest typu TStrings. A ten typ możesz przechowywać tekst z całych plików tekstowych (linia po linii). Zanim zaczniemy trzeba jeszcze dodać jedną zmienną w sekcji Implementation:
var Running : Boolean=TRUE; // zmienna okresla, czy animacja ma byc uruchomiona
Jak to zostało opisane w komentarzu określa (ta zmienna), czy animacja jest aktualnie uruchomiona, czy też nie.
Z początku sama procedura może trochę przestraszyć :)
procedure TMainForm.Go(const PText: TStrings); var PTextLong : Integer; // długość tekstu I : Integer; LinesCount : Integer; // ilość linii begin while (Running) do // dopóki zmienna będzie wartości true begin Application.ProcessMessages; if not Running then Break; // sprawdzaj, czy przypadkiem nic się nie zmieniło? for LinesCount := 0 to PText.Count -1 do // zaczynaj od pierwszej linii begin if not Running then Break; // znów sprawdź... PTextLong := Length(PText[LinesCount]); // pobierz długość linii Sleep(500); // odczekaj pół sekundy Caption := ''; // wymaz Caption for I := 0 to PTextLong do // wykonuj pętle literka po literce begin Application.ProcessMessages; Sleep(100); // z przerwa 100 milisekund if not Running then Break; // znów sprawdź! // wyswietl po kolei wszystkie litery Caption := Caption + PText.Strings[LinesCount][i]; end; end; end; end;
Jak tak się przyjrzysz to zauważysz, że procedura zawiera trzy pętle zagnieżdżone w sobie. Pierwsza z nich sprawdza, czy zmienna Running ma wartość True - jeżeli tak to animacja jest kontynuowana "w kółko". Często w tej procedurze występuje linia: if not Running then Break;
Sprawdza ten warunek, czy użytkownik nie chce zakończyć działania tej animacji. Jeżeli zmienna ma wartość True - pętla zostaje przerwana. Pierwsza pętla for rozpoczyna działanie na kolejnych liniach tekstu. Kolejna pętla wyświetla na pasku aplikacji kolejne litery. Wcześniej jednak następuje pobranie długości linii ( w znakach ). Później wymazanie tekstu na pasku i same serce animacji:
Caption := Caption + PText.Strings[LinesCount][i];
Powoduje to polecenie dodawanie kolejnych liter na pasku. To wszystko. Jeżeli masz jakieś pytania dotyczące tej procedury lub czegoś nie rozumiesz ( czegoś nie wyjaśniłem ) - pisz.
Oto sama procedura wykonywująca powyższą ( Go ):
procedure TMainForm.btnGoClick(Sender: TObject); var sText : TStrings; begin btnStop.Visible := True; // pokazanie przycisku umozliwiajacego zatrzymanie sText := TStringList.Create; try with sText do begin { dodanie kolejnych linii, ktore po kolei beda wyswietlane } Add('4programmers.net'); Add('to witryna dla początkujących jak i zaawansowanych programistów.'); Add('Znajdziesz na niej wiele kodów źródłowych, programów oraz artykułów.'); Add('Nie wspominam tutaj o kursach, których jest ponad 30...'); Add('Zajrzyj: WWW.4PROGRAMMERS.NET'); end; Go(sText); // wywolaj procedure z parametrem finally sText.Free; end; end;
Cóż można tu powiedzieć. Na początek stworzenie odpowiedniej zmiennej i dodanie do niej kolejnych linii tekstu. Na końcu wywołanie procedury. Możesz poniżej ściągnąć kod źródłowy programu, prezentującego tą procedurę.
6 komentarzy
Ty frajerze jebany ty się ucz łatwiejszych rzeczy ty skórwysynu zajebany bo ten program który podałeś nie działa.
Objaśnij najpierw jak tą procedurę uzyskać bo żeby procedury pojawiły się w sekcji private to trzeba kliknąć jakiś komponent i dlaczego w sekcji uses dajesz zmienne var ty skurwysynu głupi.
Odpisz na email rysiekjamrozik@op.pl
Boże, amatorzy, uczcie się najpierw łatwiejszych rzeczy, jak nie rozumiesz dlaczego Ci wyskakują takie błędy i co one oznaczają, to musiałeś skopiować i wkleić kod, a to nie na tym ma polegać. Na przykładzie zobacz jak to ktoś napisał i zrób samemu. Jak będziesz bezmyślnie kopiował to niczego się nie nauczysz...
Ziziok, a może chodziło o tego vara już istniejącego co jest kilkanaście linijek niżej??
Nie czytałem całego arta, więc się nie wymądrzam, ale chyba w tym może być błąd...
Wiem, że to JA coś żle robię, więc proszę nie krzyczeć, tylko powoli wytłumaczyć. Jak wklejam w interface var to mi wyskakuje (przy kompilacji) błąd:
[Error] Unit1.pas(8): Declaration expected but 'USES' found
[Error] Unit1.pas(13): Undeclared identifier: 'TForm'
[Error] Unit1.pas(31): ';' expected but '.' found
[Error] Unit1.pas(38): Undeclared identifier: 'Canvas'
[Error] Unit1.pas(42): Undeclared identifier: 'Application'
[Error] Unit1.pas(42): Missing operator or semicolon
[Error] Unit1.pas(43): Undeclared identifier: 'Sleep'
[Error] Unit1.pas(44): Undeclared identifier: 'Brush' itp. itd.
Później, gdzie wkleić :
procedure DrawAnim(X, Y : Integer);
procedure SteepBySteep(X, Y : Integer);
Gdy wpisuję Priate {private declarations} wyskakuje kolejny błąd... :(
Działa bez zarzutu.
Wystarczy skopiować, zmienić nazwę formatki, dodać przycisk o nazwie BtnGo, kliknąć na BtnGo i usunąć zdublowane zdarzenie.
Pozostałe czynności - według wyżej podanego opisu.
Od wpisu alfyczarnej upłynęło sporo czasu, mam nadzieję, że przez ten długi czas czegoś się nauczył, ale nie programowania, bo ta dziedzina jest zastrzeżona dla ludzi o określonym poziomie inteligencji.