Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor: 'Rares'
http://rares.tk
Biblioteki C++

Obsługa myszy

[lekcja] Rozdział 8. Podstawy obsługi myszki.

Obsługa myszy

Na poprzedniej lekcji nauczyliśmy się obsługiwać klawiaturę w SDL-u. Teraz przyszedł czas na następny kontroler, którego używa się w grach. Chodzi o myszkę. Zanim zaczniemy musisz przygotować sobie dwie rzeczy: przycisk w formacie bmp oraz kursor, także w bmp, którego użyjemy do drugiego programu. Najpierw zaczniemy z kursorem SDL-owym, więc powinieneś mieć na razie tylko przycisk. Oczywiście możesz skorzystać z gotowych grafik, które znajdziesz w folderze "Lekcja 7". Teraz czas na kod:

C/C++
#include <SDL.h>
SDL_Surface * ekran = NULL;
SDL_Surface * przycisk = NULL;
SDL_Rect przyciskDane;
SDL_Rect przyciskCel;
SDL_Event zdarzenie;
int myszkaX, myszkaY;
bool wyjscie = false;
int main( int argc, char * args[] )
{
    SDL_Init( SDL_INIT_EVERYTHING );
    ekran = SDL_SetVideoMode( 800, 600, 32, SDL_SWSURFACE | SDL_DOUBLEBUF );
    przycisk = SDL_LoadBMP( "przycisk.bmp" );
    przyciskDane.w = 200;
    przyciskDane.h = 50;
    przyciskCel.x = 300;
    przyciskCel.y = 275;
    while( !wyjscie )
    {
        SDL_FillRect( ekran, NULL, 0 );
        SDL_BlitSurface( przycisk, & przyciskDane, ekran, & przyciskCel );
        SDL_Flip( ekran );
        while( SDL_PollEvent( & zdarzenie ) )
        {
            if( zdarzenie.type == SDL_MOUSEMOTION )
            {
                myszkaX = zdarzenie.motion.x;
                myszkaY = zdarzenie.motion.y;
            }
            if( zdarzenie.type == SDL_MOUSEBUTTONDOWN )
            {
                if( zdarzenie.button.button == SDL_BUTTON_LEFT &&
                ( myszkaX >= przyciskCel.x && myszkaX <=
                przyciskCel.x + przyciskDane.w ) &&( myszkaY >=
                przyciskCel.y && myszkaY <= przyciskCel.y +
                przyciskDane.h ) )
                {
                    wyjscie = true;
                }
            }
            if( zdarzenie.key.keysym.sym == SDLK_ESCAPE ) wyjscie =
                 true;
           
        }
    }
    SDL_FreeSurface( przycisk );
    return 0;
}

Kod w pewnym miejscu może być trudny do rozczytania, ale to wina programu długiej instrukcji sprawdzającej. Możesz zajrzeć do kodu źródłowego z folderu dostarczonego wraz z tą lekcją, bo na pewno tam będziesz mógł lepiej rozczytać. Ok, przejdźmy do omówienia.

C/C++
SDL_Surface * przycisk = NULL;
SDL_Rect przyciskDane;
SDL_Rect przyciskCel;

Na początku deklarujemy powierzchnię potrzebną przyciskowi, a następnie dwie zmienne prostokątów. Jedna definiuje dane na temat przycisku, które są nam potrzebne, czyli szerokość i wysokość. Druga ma na celu trzymanie danych o położeniu przycisku na płaszczyźnie (oś X i Y). Potem wczytujemy przycisk do powierzchni.

C/C++
przyciskDane.w = 200;
przyciskDane.h = 50;
przyciskCel.x = 300;
przyciskCel.y = 275;

Pierwszym dwóm zmiennym przypisujemy szerokość i wysokość przycisku. Przycisk przygotowany przeze mnie ma wymiary 200x50 pikseli. Następnym dwóm zmiennym przypisujemy dane o położeniu przycisku w osiach X i Y. W tym programie przycisk jest umiejscowiony na środku okna. Aby policzyć sobie, gdzie umieścić jakiś obiekt, tak aby był w centrum potrzebujemy dwóch, bardzo logicznych wzorów:

Dla osi X: (szerokość okna - szerokość obiektu) / 2, oraz
dla osi Y: (wysokość okna - wysokość obiektu) / 2.

Przejdźmy dalej.
Po skopiowaniu przycisku na ekran i wejściu do głównej pętli pojawia się nowa funkcja:

C/C++
if( zdarzenie.type == SDL_MOUSEMOTION )
{
    myszkaX = zdarzenie.motion.x;
    myszkaY = zdarzenie.motion.y;
}

Sprawdzamy tutaj, czy typem zdarzenia, które wystąpiło nie jest ruch myszką. Jeśli tak przypisujemy dwóm zmiennym dane.

Pierwsza zmienna myszkaX to zdefiniowana przez nas wcześniej zmienna przechowująca pozycję myszki w osi X, a druga myszkaY to analogicznie zmienna przechowująca pozycję myszki w osi Y.

Zdefiniowaliśmy je, po to, aby było nam wygodniej operować na tych zmiennych w programie, w końcu myszkaX jest o wiele krótszą w zapisie zmienną niż zdarzenie.motion.x. Powyższa zmienna oraz zdarzenie.motion.y przechowują aktualną pozycję myszki na płaszczyźnie. Przypisujemy je do naszych zmiennych, i co ważne musimy je przypisywać co każdy obieg pętli.

C/C++
if( zdarzenie.type == SDL_MOUSEBUTTONDOWN )
{
    //[?]
    {
        wyjscie = true;
    }
}

Jak pewnie się domyślasz tutaj sprawdzamy, czy typem akcji, jaki zaszedł nie było wciśnięcie przycisku myszy.

Teraz czas na tą najdłuższą jak dotąd instrukcję warunkową. Jest tak długa, że rozdzielę ją na kilka części.

C/C++
if( zdarzenie.button.button == SDL_BUTTON_LEFT )

Najpierw musimy sprawdzić czy został wciśnięty ten przycisk myszy, którego my zamierzaliśmy użyć.

W tym programie klikać możemy tylko lewym przyciskiem myszy. Oczywiście możesz zamienić lewy na prawy przycisk. Wtedy należy zamienić LEFT na RIGHT. Możesz także obsłużyć dwa przyciski myszy:

C/C++
if( zdarzenie.button.button == SDL_BUTTON_LEFT
|| zdarzenie.button.button == SDL_BUTTON_RIGHT )

Następnie sprawdzamy czy kliknięcie nastąpiło w miejscu, w którym znajduje się przycisk. Najpierw sprawdzamy oś X. Zaczynamy od lewej strony, więc musi to mieć taką formę:

&&( myszkaX >= przyciskCel.x && myszkaX <= przyciskCel.x + przyciskDane.w )

Jeśli położenie myszki w osi X (myszkaX) było większe lub równe pozycji przycisku na ekranie i jednocześnie jej położenie było mniejsze lub równe pozycji przycisku + szerokości przycisku (co w sumie daje prawą pozycję prawej strony przycisku).
Analogicznie z osią Y:

&&( myszkaY >= przyciskCel.y && myszkaY <= przyciskCel.y + przyciskDane.h ) )

Jeśli powyższe stwierdzenie jest prawdziwe to zmieniamy wartość zmiennej wyjscie na prawdziwą (true).

Potem możemy dodać dla pewności instrukcję sprawdzającą, czy nie został wciśnięty przycisk escape (to tak dla pewności, jeśli mysz nie będzie działała).
To tyle. Teraz dodamy do programu nasz własny kursor.

Najpierw przygotuj sobie grafikę kursora lub skorzystaj z mojej, dostarczonej z kursem (folder "Lekcja 7").

C/C++
#include <SDL.h>
SDL_Surface * ekran = NULL;
SDL_Surface * przycisk = NULL;
SDL_Surface * kursor = NULL;
SDL_Rect przyciskDane;
SDL_Rect przyciskCel;
SDL_Rect kursorDane;
SDL_Event zdarzenie;
int myszkaX, myszkaY;
bool wyjscie = false;
int main( int argc, char * args[] )
{
    SDL_Init( SDL_INIT_EVERYTHING );
    ekran = SDL_SetVideoMode( 800, 600, 32, SDL_SWSURFACE | SDL_DOUBLEBUF );
    przycisk = SDL_LoadBMP( "przycisk.bmp" );
    kursor = SDL_LoadBMP( "kursor.bmp" );
    przyciskDane.w = 200;
    przyciskDane.h = 50;
    przyciskCel.x = 300;
    przyciskCel.y = 275;
    kursorDane.x = 0;
    kursorDane.y = 0;
    while( !wyjscie )
    {
        SDL_FillRect( ekran, NULL, 0 );
        SDL_ShowCursor( SDL_DISABLE );
        SDL_BlitSurface( przycisk, & przyciskDane, ekran, & przyciskCel );
        SDL_BlitSurface( kursor, NULL, ekran, & kursorDane );
        SDL_Flip( ekran );
        while( SDL_PollEvent( & zdarzenie ) )
        {
            if( zdarzenie.type == SDL_MOUSEMOTION )
            {
                kursorDane.x = zdarzenie.motion.x;
                kursorDane.y = zdarzenie.motion.y;
            }
            if( zdarzenie.type == SDL_MOUSEBUTTONDOWN )
            {
                if( zdarzenie.button.button == SDL_BUTTON_LEFT &&
                ( kursorDane.x >= przyciskCel.x && kursorDane.x <=
                przyciskCel.x + przyciskDane.w ) &&( kursorDane.y >=
                przyciskCel.y && kursorDane.y <= przyciskCel.y +
                przyciskDane.h ) )
                {
                    wyjscie = true;
                }
            }
            if( zdarzenie.key.keysym.sym == SDLK_ESCAPE ) wyjscie =
                 true;
           
        }
    }
    SDL_FreeSurface( przycisk );
    SDL_FreeSurface( kursor );
    return 0;
}

Na początku doszły dwie nowe zmienne: powierzchnia przechowująca grafikę kursora oraz prostokąt przechowujący dane o położeniu myszki. Potem wczytujemy obrazek kursora i zerujemy dane jego położenia. Następną ważną rzeczą jest wyłączenie domyślnego kursora SDL, by na ekranie znajdował się tylko nasz:
SDL_ShowCursor( SDL_DISABLE );

Wystarczy wywołać funkcję pokazania kursora z flagą wyłączenia. Jeśli chcesz, aby kursor się pojawił przekazujesz funkcji flagę SDL_ENABLE.
Potem kopiujemy go na powierzchnię okna.
SDL_BlitSurface( kursor, NULL, ekran, & kursorDane );

Interesują nas tylko dane położenia kursor, więc drugi argument zostawiamy w spokoju. Następnie przypisujemy zmiennym x i y z prostokątu naszego kursora zmienne x i y myszki.

Ostatnią zmianą jest podmiana zmiennych w instrukcji warunkowej sprawdzającej gdzie nastąpiło kliknięcie. Wystarczyło podmienić zmienne myszkaX na kursorDane.x, a myszkaY na kursorDane.y.

I to wszystko. Jak widzisz obsługa myszy w SDL-u jest banalna, a zmiana wyglądu kursora jeszcze prostsza. W przyszłości, będziesz operował SDL-em dużo sprawniej i bardziej skomplikowanie. Niedługo nauczysz się tworzyć proste menu, w którym trzeba będzie użyć myszki. Ale to później.

I jeszcze jedno. Być może zauważyłeś, że tło kursora ma kolor czarny. Z pewnością chciałbyś zmienić je na przezroczyste. Tak samo z postacią którą kontrolowałeś podczas obsługi klawiatury. Oczywiście to też omówimy i poprawimy. I to już na kolejnej lekcji.
Poprzedni dokument Następny dokument
Obsługa klawiatury Kurs SFML 1.6, C++