Gra 2D, część 3: Wyświetlanie przewijanej mapy

18.01.2010 - Łukasz Milewski
TrudnośćTrudność

Selektywne przewijanie mapy

Zapewne widzisz już, że przy podchodzeniu do krawędzi gra wygląda nienaturalnie (szczególnie przy cofaniu się poza m_max_x_pos). Spróbujmy to poprawić.

Na początek powinniśmy zdefiniować, kiedy mapa powinna się przewijać, a kiedy nie. W klasie Player (plik Player.h) definiujemy taką metodę:

Pokaż/ukryj kod
1
2
3
4
5
6
7
8
9
10
11
    bool MoveMap() {
        const size_t screen_tiles_count = 
            Engine::Get().Renderer()->GetHorizontalTilesOnScreenCount();
        const size_t half_screen_tiles_count = screen_tiles_count/2;
 
        return 
            m_x >= m_max_x_pos 
            && 
            m_x < (m_level_width - 1) - half_screen_tiles_count;
    }
  

Mapa porusza się, gdy gracz nie próbuje się cofnąć (m_x >= m_max_x_pos) oraz gdy jesteśmy oddaleni od końca poziomu o więcej niż połowę ekranu (m_x < (m_level_width - 1) - half_screen_tiles_count). Pamiętajmy o dodaniu nagłówka #include "Engine.h", skoro teraz używamy Engine w klasie Player.

Sam warunek to nie wszystko. Trzeba go jeszcze gdzieś wykorzystać :-) Najprostszy sposób to drobna modyfikacja metody App::Draw (plik App.cpp). Zrobimy to tak, że w klasie App zapamiętasz pole, które będzie oznaczało ostatnią pozycję, przy której mapa powinna się przesunąć. Tę wartość będziemy uaktualniali w metodzie App::Draw. Użyjemy jej do rysowania mapy zamiast pozycji gracza. Modyfikujemy kod:

1
2
3
void App::Draw() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

aby wyglądał tak:

1
2
3
4
5
6
7
void App::Draw() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
 
    if (m_player->MoveMap()) {
        m_stored_player_pos_x = m_player->GetX();
    }

Pole m_stored_player_pos_x typu double należy dodać do klasy App i ustawić na 1.0 w konstruktorze.

Wracając do metody Draw, zamień teraz:

1
2
3
4
5
6
7
8
        glTranslatef(-(m_player->GetX() 
                       * 
                       Engine::Get().Renderer()->GetTileWidth() - 0.45),
                     0, 0);
        glMatrixMode(GL_MODELVIEW);
 
        m_level_view.SetLevel(m_level, m_player->GetX());
        m_level_view.Draw(m_player->GetX());

na:

1
2
3
4
5
6
7
8
        glTranslatef(-(m_stored_player_pos_x
                       * 
                       Engine::Get().Renderer()->GetTileWidth() - 0.45),
                    0, 0);
        glMatrixMode(GL_MODELVIEW);
 
        m_level_view.SetLevel(m_level, m_stored_player_pos_x);
        m_level_view.Draw(m_stored_player_pos_x);

Poprawiamy błędy

Moglibyśmy w tym momencie skończyć, ale przez powyższą zmianę powstał drobny problem. Spróbujmy przejść postacią gracza do prawej krawędzi mapy i cofnąć się. Okazuje się, że możesz to zrobić tylko o połowę ekranu (tak, jak chcieliśmy). Niestety, widzimy cały ekran, więc wydaje się, że gracz utknął na środku. Musimy lekko poprawić metodę Player::Update. Zmiana powinna sprawdzać ten przypadek (gracz jest dalej niż długość poziomu - połowa długości ekranu) i wówczas nie modyfikować m_max_x_pos.

Dopisz kawałek za linijkami:

1
2
3
4
5
    const size_t half_screen_tiles_count = 
         (Engine::Get().Renderer()->GetHorizontalTilesOnScreenCount()-1)/2;
    if (m_x < m_max_x_pos - half_screen_tiles_count) {
        m_x = m_max_x_pos - half_screen_tiles_count; 
    } 

aby całość wyglądała tak:

1
2
3
4
5
6
7
8
    const size_t half_screen_tiles_count = 
        (Engine::Get().Renderer()->GetHorizontalTilesOnScreenCount()-1)/2;
    if (m_x < m_max_x_pos - half_screen_tiles_count) {
        m_x = m_max_x_pos - half_screen_tiles_count; 
    } 
    if (m_x > m_level_width - half_screen_tiles_count - 2) {
        m_max_x_pos = m_level_width - half_screen_tiles_count - 2;
    }

Gratulacje

Świetnie! Właśnie udało nam się zaimplementować nietrywialną obsługę scrollowanej mapy. Aby ugruntować tę wiedzę wykonajmy poniższe zadania.

Kod końcowy - znajdziesz go tutaj

Masz pytanie, uwagę? Zauważyłeś błąd? Powiedz o tym na forum.

Zadania

  1. Dodaj kolejny typ kafla - np. różowy kwadrat. Zmień plik poziomu tak, aby było kilka takich kafli.
  2. Dodaj przesuwane tło. Stwórz nową klasę Background. Ta klasa powinna rysować coś w tle (np. duży obrazek). Zadbaj o to, aby tło przesuwało się wraz z mapą.
  3. Dodaj do tła paralaksę. Tło powinno składać się z kilku warstw (myślimy o nich, jakby były poukładane od najbliższych do najdalszych). Im warstwa jest bliżej, tym wolniej się przesuwa i tym większe elementy zawiera.

Poprzedni artykuł - poruszanie postacią Następny artykuł - Hall of Fame

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

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com