Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Tutorial by Easykoder ®
www.easykoder.vot.pl
Biblioteki C++

Animacja

[lekcja] Rozdział 10. Tworzenie animacji ludzika w grze.
Zastanówmy się nad tym czego nam jeszcze do szczęścia brakuje? Ekran już nie miga, program działa w wyznaczonym tempie, nasz ludek porusza się... zaraz!... właśnie, przecież nasz ludek wcale się nie porusza! On się tylko przemieszcza, a to wielka różnica! Chcąc stworzyć jakąś grę, będziemy musieli wprowadzić jakieś ładne animacje do naszego projektu, nie będziemy przecież latać nieruchomym ludzikiem!

Z racji tego, że w Allegro wszystko jest proste, domyślacie się pewnie, że z animacją również nie będzie problemu? I oczywiście macie rację, bo czym jest animacja jeśli nie seryjnym wyświetlaniem odpowiednich obrazków w odpowiednim czasie? A skoro potrafimy już wyświetlać obrazki, to w czym problem? Stwórzmy więc program, który wyświetli jakąś animację.

Do naszego programu będziemy potrzebowali, kilku obrazków. U mnie są to kolejne klatki ludzika, który porusza swoimi rękoma, czyli zwykła animacja machania rękoma. Pamiętajmy o tym, że jeśli chcemy otrzymać dobrą animację powinna być płynna, czyli składać się z większej ilości klatek, na których widać jak najmniejsze przemieszczenia danego elementu. Mi nie zależy na jakości bo jest to program demonstracyjny... ;p tak więc u mnie zwykłe machnięcie rękoma znajduje się na 4 klatkach.

Przystąpmy więc do pracy. Jak zwykle pocięty kodzik wraz z potrzebnymi objaśnieniami. Na początku standard, czyli inicjowanie biblioteki, timera, ustawianie trybu graficznego.

C/C++
#include <allegro.h>
volatile long speed = 0;
void increment_speed()
{
    speed++;
}
END_OF_FUNCTION( increment_speed );
LOCK_VARIABLE( speed );
LOCK_FUNCTION( increment_speed );
int main()
{
    allegro_init();
    install_keyboard();
    set_color_depth( 16 );
    set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0 );
    install_timer();
    install_int_ex( increment_speed, BPS_TO_TIMER( 80 ) );

Teraz pora na zadeklarowanie BITMAP pod wszystkie klatki naszej animacji, no i oczywiście bufora.

C/C++
BITMAP * bufor = NULL;
BITMAP * ludek0 = NULL;
BITMAP * ludek1 = NULL;
BITMAP * ludek2 = NULL;
BITMAP * ludek3 = NULL;

Tworzymy bufor i ładujemy grafiki do naszych zmiennych. Nie sprawdzamy czy zostały utworzone, oszczędzając miejsce ;-p...

C/C++
bufor = create_bitmap( 640, 480 );
if( !bufor )
{
    set_gfx_mode( GFX_TEXT, 0, 0, 0, 0 );
    allegro_message( "Nie mogę utworzyć bufora !" );
    allegro_exit();
    return 0;
}

ludek0 = load_bmp( "bobek00.bmp", default_palette );
ludek1 = load_bmp( "bobek01.bmp", default_palette );
ludek2 = load_bmp( "bobek02.bmp", default_palette );
ludek3 = load_bmp( "bobek03.bmp", default_palette );

Następnie deklarujemy nasze zmienne takie jak: pozycja ludzika na ekranie oraz nową zmienną frame, dzięki której będziemy sprawnie operować wyświetlaniem odpowiedniej klatki.

C/C++
int ludek_x = 100, ludek_y = 100;
int frame = 0;

while( !key[ KEY_ESC ] )
{
    while( speed > 0 )
    {
       
        if( key[ KEY_LEFT ] ) ludek_x--;
       
        if( key[ KEY_RIGHT ] ) ludek_x++;
       
        if( key[ KEY_UP ] ) ludek_y--;
       
        if( key[ KEY_DOWN ] ) ludek_y++;
       
        speed--;
       
        frame++;
        if( frame > 80 ) frame = 0;
       
    }

Jak pamiętamy ustawiliśmy nasz timer na 80 cykli w ciągu sekundy ( BPS_TO_TIMER(80) ), więc w ciągu sekundy nasza zmienna frame osiągnie wartość 80 i potem znowu spadnie do zera. Nasza animacja składa się z 4 klatek, więc podzielimy teraz czas animacji przez ilość klatek, co daje nam 20. Więc jeśli chcemy, aby nasza animacja trwała sekundę, każdej z klatek przydzielamy odpowiedni (po 20) przedział framesów. Następnie wyświetlamy odpowiednią klatkę animacji.

C/C++
clear_to_color( bufor, makecol( 150, 150, 150 ) );

if( frame < 20 ) { draw_sprite( bufor, ludek0, ludek_x, ludek_y ); }
else if( frame >= 20 && frame < 40 ) { draw_sprite( bufor, ludek1, ludek_x, ludek_y ); }
else if( frame >= 40 && frame < 60 ) { draw_sprite( bufor, ludek2, ludek_x, ludek_y ); }
else if( frame >= 60 && frame < 80 ) { draw_sprite( bufor, ludek3, ludek_x, ludek_y ); }

blit( bufor, screen, 0, 0, 0, 0, 640, 480 );
}

Na koniec nie pozostaje nam nic innego jak posprzątać po naszym programie. Usuwamy więc nasz timer i wszystkie bitmapy.

C/C++
remove_int( increment_speed );
destroy_bitmap( ludek0 );
destroy_bitmap( ludek1 );
destroy_bitmap( ludek2 );
destroy_bitmap( ludek3 );
destroy_bitmap( bufor );
allegro_exit();
return 0;
}
END_OF_MAIN();

Tak naprawdę omówione wyżej wyświetlanie animacji, nie jest zbyt fachowe, co można zauważyć na pierwszy rzut oka ;-p Celem tej lekcji było przedstawienie ogólnej zasady animacji, która polega po prostu na wyświetleniu w odpowiednim czasie i miejscu odpowiedniej grafiki. I jak się okazało nie jest to takie trudne.

W powyższym przykładzie użyliśmy procedury draw_sprite(bufor, ludek2, ludek_x, ludek_y); której argumentami są: bitmapa, na której chcemy wyświetlić nasz obrazek; bitmapa którą chcemy wyświetlić; pozycja X obrazka; pozycja Y obrazka. Powyższa procedura jest jednak niezbyt użyteczna, o czym przekonasz się czytając różne przykłady z tej strony.

Tworząc bitmapy na potrzeby gry, nie będziemy ładować każdej z klatek do osobnej struktury BITMAP. Nie będziemy umieszczać ich nawet w tablicach. Gdyż wszystkie klatki animacji skleimy w jedną wielką bitmapę, z której będziemy pobierać interesujący nas fragment, za pomocą procedury blit lub masked_blit. Szybko zauważycie przewagę tego sposobu nad zaprezentowanym wyżej. Ale o tym kiedy indziej.

Kody źródłowe programów

Zadania do tej i innych lekcji znajdziesz na naszym repozytorium.

Prawa autorskie

Serwis otrzymał zgodę od autora na publikację niniejszego materiału.
Poprzedni dokument Następny dokument
Timery Dźwięk