Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor: Michał Kozakiewicz (michal3)
Biblioteki C++

Zdarzenia i kolejka zdarzeń

[lekcja]

Omówienie

W tej części kursu opowiem Ci czym są zdarzenia oraz czym jest kolejka zdarzeń. Bardzo ważne jest aby omówić te zagadnienie na samym początku nauki biblioteki Allegro 5, ponieważ wykorzystuję się to w praktycznie każdym programie. Jeżeli wcześniej nie spotkałeś się z tym, nie martw się. Te zagadnienie jest bardzo proste.

Wprowadzenie do zagadnienia

Czym jest zdarzenie (z angielskiego event)? Wyobraź sobie to tak. Siedzisz sobie spokojnie w biurze przy komputerze i pracujesz, nagle szef krzyczy że masz mu zrobić kawę. Czyli krótko mówiąc, coś przyszło ci zrobić, wystąpiło zdarzenie. W tej sytuacji możesz, wykonać polecenie szefa lub udać że nie słyszysz. Jeśli wykonasz polecenie szefa, wszystko będzie powolutku toczyć się dalej. Jeżeli jednak nie wykonasz tego, takich zdarzeń nazbiera się dużo (w jakieś kolejności) i w końcu szef cie wyrzuci. Dodając, twój szef jest źródłem zdarzeń. Jak to teraz przełożyć na informatykę?

W bibliotece Allegro 5 wygląda to tak że, twój program działa i wykonuje swoją pracę. Nagle gdy zaczynasz przesuwać myszkę, wciskać klawisze klawiatury itp. występują zdarzenia (eventy). Użytkownik przekazuje programowi polecenia jakie chce żeby on wykonał. Wtedy twój program musi zareagować na to co się dzieje, wykonać jakąś czynność (obsłużyć event). W końcu gdyby program tego nie wykonał, zirytowany użytkownik wyłączył by go czy nawet skasował.

Tak więc:

Event - jest zdarzeniem generowanym przez źródło zdarzeń (event source).
Event Source - jest tym skąd pochodzą zdarzenia, czyli przykładowo mysz, klawiatura, display.
Event Queue - jest miejscem w którym gromadzą się zdarzenia które trzeba wykonać.

Taki system jest bardziej efektywny niż zajęcie procesora ciągłym sprawdzaniem każdego możliwego wystąpienia, dopiero wtedy reagowania.

Od teorii do praktyki

Aby zaprezentować główne działanie eventow, posłużę się tylko kilkoma funkcjami i obiektami.

ALLEGRO_EVENT_QUEUE * al_create_event_queue( void )

Funkcja tworzy (allokuje pamieć na) kolejkę zdarzeń, będą w niej przetrzymywane po wystąpieniu eventy.
Funkcja w razie poprawnego działania zwraca wskaźnik na obiekt
ALLEGRO_EVENT_QUEUE
, w przypadku błędu zwraca wartość
NULL
.

ALLEGRO_EVENT_QUEUE

Obiekt który pozwoli nam przetrzymywać zgromadzone zdarzenia. My będziemy odbierać wskaźnik na pamięć gdzie on będzie się znajdywać.

void al_register_event_source( ALLEGRO_EVENT_QUEUE * queue, ALLEGRO_EVENT_SOURCE * source )

Tą funkcją zarejestrujemy w odpowiedniej kolejce źródło z którego ma czytać zdarzenia.

ALLEGRO_EVENT_SOURCE * al_get_display_event_source( ALLEGRO_DISPLAY * display )

Tę funkcje znajdziemy w sekcji Display oficjalnej dokumentacji. Służy ona do tego, aby pobrać wskaźnik na źródło zdarzeń określonego display'a.
Przykładowo wybrałem tę, może być również funkcja pobierająca źródło event'owe od klawiatury itd.

void al_wait_for_event( ALLEGRO_EVENT_QUEUE * queue, ALLEGRO_EVENT * ret_event )

Funkcja ta pobiera z samej góry kolejki event, który trafił do niej jako pierwszy. Następnie wpisuje go do obiektu
ALLEGRO_EVENT * ret_event
, jeżeli wskaźnik ret_event jest wartością inną niż NULL.
Jeżeli event zostanie wpisany do tego obiektu, zostaje skasowany z góry kolejki. Jeżeli wartość ret_event jest równa NULL, event z góry kolejki zostaje zniszczony.

ALLEGRO_EVENT

Obiekt w którym przetrzymywany będzie jeden pobrany event, który aktualnie jest do obsłużenia.

void al_destroy_event_queue( ALLEGRO_EVENT_QUEUE * queue )

Funkcje tę wywołujemy, aby zwolnic pamięć wcześniej allokowaną dla kolejki.

Przykład użycia powyższych informacji

Zwróć uwagę na komentarze, tłumaczą kod.

C/C++
#include <stdio.h>
#include <allegro5/allegro.h>

int main( int argc, char * argv[] )
{
    ALLEGRO_DISPLAY * display = NULL;
   
    /* Tworzymy zmienną w której przechowamy adres kolejki */
    ALLEGRO_EVENT_QUEUE * kolejka = NULL;
   
    /* Tworzymy zmienną w której przetrzymamy event do obsłużenia */
    ALLEGRO_EVENT ev1;
   
    if( !al_init() )
    {
        fprintf( stderr, "Failed to initialize allegro!\n" );
        return - 1;
    }
   
    /* Allokujemy pamięć dla kolejki i sprawdzamy czy funkcja nie zwróciła błędu */
    kolejka = al_create_event_queue();
    if( kolejka == NULL )
    {
        fprintf( stderr, "Failed to create event queue!\n" );
        return - 1;
    }
   
    display = al_create_display( 640, 480 );
    if( display == NULL )
    {
        fprintf( stderr, "Failed to create display!\n" );
        return - 1;
    }
   
    /* Skoro mamy kolejkę i display, rejestrujemy display jako źródło eventów */
    al_register_event_source( kolejka, al_get_display_event_source( display ) );
   
    al_clear_to_color( al_map_rgb( 20, 75, 80 ) );
    al_flip_display();
   
    /* Pętla w której będzie pracować program */
    while( 1 )
    {
        /* Jeżeli wystąpi event, wysyłamy go do zmiennej ev1 */
        al_wait_for_event( kolejka, & ev1 );
       
        /* Jeżeli wystąpił event, będzie posiadać określony typ; Sprawdzamy czy typ jest równy wartości,
                 * która mówi nam że został wciśnięty przycisk exit */
        if( ev1.type == ALLEGRO_EVENT_DISPLAY_CLOSE )
        {
            /* Jeżeli prawda, przerwij pętle while */
            break;
        }
    }
   
    al_destroy_display( display );
   
    /* Zwalniamy pamięć po kolejce */
    al_destroy_event_queue( kolejka );
    return 0;
}

Przykład pozwala na obsłużenie wciśnięcia przycisku exit. Oczywiście można zarejestrować jako źródło eventów np. klawiaturę, następnie sprawdzać czy zostały wciśnięte klawisze.
Należy wtedy sprawdzić w oficjalnej dokumentacji jak zainstalować sterownik klawiatury, dodać źródło do kolejki. Następnie sprawdzić za pomocą instrukcji if typ klawiatury, następnie klawisz.

Zaglądamy do dokumentacji

Czas rozejrzeć się po więcej możliwości. Zaglądamy do oficjalnej dokumentacji w zakładce Events

W sekcji A znajdują się funkcje. W sekcji B znajdują się typy eventów.

Dostajemy funkcje do sprawdzenia czy źródło eventów jest zarejestrowane, do skasowania źródła z kolejki. Możemy pauzować kolejkę, sprawdzać czy jest spauzowana. Dostajemy inne funkcje do sprawdzenia czy wystąpił event i do jego pobrania. Nawet dostajemy możliwość stworzenia własnego źródła eventów, następnie generowania eventów które wpiszemy do określonej kolejki.

Typów jest dużo więcej. Możemy obsłużyć joystick, reagować na wciśnięcie lub puszczenie klawisza. Reagować na ruch myszy, wciskanie klawiszy myszy. Wykrycie dotyku, dla urządzeń z taką możliwością. Odebranie timerów, czyli regularnie pojawiających się eventów które regulują procesy w programie. Czy nawet sprawdzenia co dzieje się z oknem programu.

Możliwości jakie dostarczają eventy jest ogrom. Głównie z ich użyciem korzysta się z biblioteki Allegro 5. Myślę że udowodniłem Ci, że warto ten temat nauczyć się na początku.
Poprzedni dokument Następny dokument
Pierwsze okno Timery, regulacja czasu