Arkanoid 3D krok po kroku

23.04.2010 - Olgierd Humeńczuk
TrudnośćTrudność

Zdarzenia

Nasza gra nie miałaby większego sensu gdybyśmy nie potrafili reagować na polecenia wydawane przez gracza. Powinniśmy zaimplementować zatem obsługę takich zdarzeń jak:

  • wciśnięcie klawisza klawiatury
  • zmiana pozycji myszki

Aby to zrobić użyjemy zdarzeń ( ang. events ) zdefiniowanych w bibliotece SDL. Oto kod funkcji odpowiedzialnej za obsługę zdarzeń:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bool processInput( void )
{
    // zmienna pomocnicza
    SDL_Event event;
    // czy są jakieś czekające na przetworzenie zdarzenia ?
    if ( SDL_PollEvent( &event ) )
    {
        // sprawdzenie typu zdarzenia
        switch( event.type )
        {
            // wyjście z aplikacji
            case SDL_QUIT:
                return false;
            // użytkownik nacisnął któryś z klawiszy na klawiaturze
            case SDL_KEYDOWN:
                // jeżeli nacisnał klawisz eskape zamykamy aplikacje
                if( event.key.keysym.sym == SDLK_ESCAPE )
                {
                    return false;
                }
            break;
            case SDL_MOUSEMOTION:
                // tutaj będzie kod odpowiedzialny za obsługę zdarzeń myszki
            break;
        }
    }
    return true; 
} 

Funkcja ta zwraca wartość false jeżeli aplikacja powinna się zakończyć i true w przeciwnym przypadku. Przyjrzyjmy się kolejnym jej fragmentom:

  • Alokacja pamięci na informacje o zdarzeniu ( linia 4 )
  • Odpytanie biblioteki czy czekają na nas jakieś nie przetworzone zdarzenia ( linia 6 )
  • Obsługa zdarzeń konkretnego typu: ( linie od 10 do 26 )
    • SDL_QUIT - zamknięcie aplikacji przez system lub użytkownika
    • SDL_KEYDOWN - wciśnięcie dowolnego klawisza na klawiaturze
    • SDL_MOUSEMOTION - zmiana położenia myszki ( lub innego kontrolera ją zastępującego )

Składamy wszystko razem

Wykorzystując przedstawione fragmenty, stworzymy teraz działającą aplikację, która stanowić będzie podstawę naszej gry. Program nasz będzie na razie tylko konstruował okno z podpiętym kontekstem Open GL oraz reagował na jego zamknięcie i wciśnięcie klawisza Escape.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @brief Główna metoda programu ( entry point )
* @param argc ilość argumentów przekazanych do programu
* @param argv tablica wartości argumentów
*/
int main( const int /*argc*/, const char** /*argv*/ )
{
    try
    {
        // wywołanie funkcji inicjującej
        initSDL();
        // wykorzystanie funkcji obsługi zdarzeń
        while( processInput() )
        {
            //tutaj obsługa pętli gry
        }
    }
    catch( const std::exception& e )
    { 
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
    SDL_Quit();
    return 0;
}

Open GL i renderowanie

Na tym etapie nasz program wyświetla jedynie czarne tło. Nauczmy się zatem jak wyświetlać podstawowe bryły geometryczne. Zaczniemy od ustawienia biblioteki Open GL w odpowiedni stan. Napiszmy nową funkcję o nazwie initOpenGL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    /**
    * @brief Iniclalizacja stanu poczatkowego niektorych
    *         wartosci Open GL.
    * @param width szerokosc ekranu
    * @param height wysokosc ekranu
    */
    void initOpenGL( int width, int height )
    {
        glMatrixMode( GL_PROJECTION );
        gluPerspective( 45.0f, width / ( GLfloat ) height, 0.1f, 100.0f );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
        glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 
    } 

  • Linia 9 to sposób na powiedzenie bibliotece Open GL że będziemy od tego momentu operować na macierzy rzutowania perspektywicznego. Macierz ta ogólnie mówiąc jest wykorzystywana do matematycznego przedstawienia wycinka przestrzeni ( w kształcie ostrosłupa ) widzianego przez obserwatora w naszym trójwymiarowym świecie i odwzorowania tego wycinka na ekranie.
  • Linia 10 to wywołanie funkcji z biblioteki pomocniczej GLU, której parametry to kolejno:
    • kąt widzenia obserwatora podawany w stopniach
    • stosunek szerokości do wysokości ekranu
    • odległość tzw. bliskiej płaszczyzny obcinania
    • odległość tzw. dalekiej płaszczyzny obcinania
  • Linia 11 to analogicznie do polecenia z linii 9 ustawienie Open GL na tryb pracy z macierzą widoku. Macierz widoku odpowiada za przekształcenia wyświetlanych obiektów. Możliwe do uzyskania przekształcenia to:
    • przesunięcie - glTranslate
    • skalowanie - glScale
    • obrót wokół wybranej osi - glRotate
  • Polecenie z linii 12 ładuje tzw. macierz jednostkową do ustawionej macierzy widoku.
  • Ostatnia linia to ustawienie sposobu prezentacji wielokątów tak aby renderowane były jedynie ich krawędzie. Gdy poznamy jak działa oświetlenie, będziemy wyświetlać wypełnione bryły, a na razie ograniczymy się jedynie do widoku ich krawędzi.

Aby lepiej zrozumieć wymienione wyżej pojęcia spójrzmy na rysunek przedstawiający widok przykładowej sceny składającej się z sześcianu. Na rysunku zobaczymy wspomniany sześcian ( kolor czerwony ) oraz wizualizację ostrosłupa obserwatora ( kolor prawie biały ). Ostrosłup obserwatora obejmuje wycinek przestrzeni który pojawi się na naszych ekranach w rezultacie operacji renderowania.


Rys. 2 Przykładowa scena. a.) środek układu współrzędnych zwany globalnym układem współrzędnych - pozycja obserwatora b.) obiekt sceny i jego lokalny układ współrzędnych

Rys. 3 Przykładowa scena, widok z góry.

  • na obu rysunkach strzałki w kolorze zielonym wskazują oś -Z, kolor czerwony to oś +X, natomiast niebieski to oś +Y
  • wymiary ostrosłupa widzenia w Open GL ( na rys. 2 i rys. 3 kolor prawie biały ) modyfikujemy za pomocą macierzy projekcji ( GL_PROJECTION_MATRIX, patrz funkcja gluPerspective ) natomiast położenie, orientację oraz wymiary wielokątów za pomocą macierzy widoku ( GL_MODELVIEW_MATRIX )
Tak naprawdę obserwator zawsze znajduje się w punkcie ( 0, 0, 0 ) i patrzy w kierunku -Z. Wynika to ze specyfiki operacji rzutowania i konstrukcji macierzy projekcji. Dlatego aby zmienić pozycję z której widzimy naszą scenę, oraz kierunek w jakim patrzymy będziemy musieli odpowiednio modyfikować macierz widoku. Z pomocą przyjdzie nam funkcja z biblioteki GLU - gluLookAt.

5
Twoja ocena: Brak Ocena: 5 (2 ocen)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com