Gra 2D, część 14: Lepszy respawn i kilka szczegółów

01.10.2012 - Marcin Milewski
TrudnośćTrudność

Najpierw bonus, potem strzelaj

Czy rozsądnie jest od razu dawać graczowi broń do ręki? Niech lepiej chwilę potrudzi się rozprawiając się z przeciwnikami innymi metodami. W tej części artykułu dodamy do naszej gry nowy bonus -- pojedynczy strzał. Gracz będzie mógł strzelać dopiero po jego znalezieniu.

Animacje bonusów związanych z pojedynczym oraz podwójnym strzałem.

Zaczynamy od zdefiniowania nowego bonusu, więc otwieramy plik Types.h i dodajemy nowy element do wyliczenia EntityType:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Plik: Types.h
namespace ET {
    enum EntityType {
        UNKNOWN,
 
        Mush,
        PlayerBullet,
        SingleShot,                               // NOWE
        TwinShot,
 
        COUNT
    };
}  

Następnie przenosimy się do klasy Player. Najpierw dodajemy pole-flagę m_shooting_enabled, która powie nam czy gracz może strzelać (nieważne w jaki sposób, przez strzelanie rozumiemy tu wystrzelenie dowolnej liczby pocisków). Należy pamiętać o zainicjowaniu tego pola w konstruktorze.

1
2
3
4
5
6
7
8
9
10
11
// Plik: Player.h
    bool m_shooting_enabled;     // czy gracz może strzelać
 
// Plik: PLayer.cpp
Player::Player(...)
    : // (...)
      m_bullet_pay(0),
      m_is_immortal(false),
      m_lifes(lifes),
      m_shooting_enabled(false),                  // NOWE
      m_twin_shot_enabled(false),  

Następnie dodajemy metody, które:

  • Włączają/wyłączają możliwość strzelania - EnableShooting, DisableShooting
  • Zwracają informacje o możliwości strzelania (włączone/wyłączone) -- CanShoot, CannotShoot

1
2
3
4
5
// Plik: Player.h
    void EnableShooting()          { m_shooting_enabled = true; }
    void DisableShooting()         { m_shooting_enabled = false; }
    bool CanShoot() const          { return m_shooting_enabled; }
    bool CannotShoot() const       { return !CanShoot(); }  

Aktulizujemy metodę EnableTwinShot, która jest wywoływana w momencie wzięcia przez gracza bonusu z podwójnym strzelaniem. Zmiana polega na tym, że nawet jeżeli bohater nie mógł wcześniej strzelać jednym nabojem, to nie powinno mu to przeszkadzać w strzelaniu dwoma jeżeli tylko wziął odpowiedni upgrade.

1
2
// Plik: Player.h
    void EnableTwinShot()    { EnableShooting(); m_twin_shot_enabled = true; }

Klasa Player zapewnia nam już odpowiedni interfejs związany ze strzelaniem. Przenosimy się więc do pliku Game.cpp, gdzie będziemy z niego korzystać. Pierwsza zmiana, to sprawdzenie czy gracz jest uzbrojony i tylko wtedy zezwolenie na strzał.

1
2
3
4
5
6
// Plik: Game.cpp, metoda ProcessEvents
    } else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_s) {
        if (m_player->CanShoot()) {                                      // NOWE
            m_player->FireBullet();
        }                                                                // NOWE
    }  

Następnie dodajemy reakcję na kolizję bohatera z encją bonusu. Definiujemy także liczbę punktów, które wpłyną na konto gracza przy tej okazji. W ramach przypomnienia, krótki opis schematu działania poniższego kodu:

  1. Sprawdzamy jakiego typu jest encja
  2. Sprawdzamy czy bohater z nią koliduje
  3. Obsługujemy kolizję (np. EnableShooting)
  4. Oznaczamy encję jako martwą (SetIsDead)
  5. Nie chcemy żadnego odbicia od encji (continue)
W celu obejrzenia kompletnej metody CheckPlayerEntitiesCollisions, należy otworzyć plik Game.cpp.

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
29
30
31
// Plik: Game.cpp, metoda CheckPlayerEntitiesCollisions
        const int score_for_bonus = 40;   // punkty za wzięcie bonusu    // NOWE
 
        if (entity_type == ET::PlayerBullet) {
            // postać nie koliduje ze swoimi pociskami
            continue;
        } else if (entity_type == ET::SingleShot) {                      // NOWE
            // gracz wziął bonus "zwykłe strzelanie"                     // NOWE
            if (m_player->GetAabb().Collides(entity->GetAabb())) {       // NOWE
                m_player->AddScores(score_for_bonus);                    // NOWE
                m_player->EnableShooting();                              // NOWE
                entity->SetIsDead(true);                                 // NOWE
            }                                                            // NOWE
            continue;                                                    // NOWE
        } else if (entity_type == ET::TwinShot) {
            // gracz wziął bonus "podwójne strzelanie"
            if (m_player->GetAabb().Collides(entity->GetAabb())) {
                m_player->AddScores(score_for_bonus);
                m_player->EnableTwinShot();
                entity->SetIsDead(true);
            }
            continue;
        }
 
        // Nieśmiertelna postać nie koliduje z innymi jednostkami,
        // ale może zbierać np. upgrade'y (patrz wyżej).
        if (m_player->IsImmortal()) {
            continue;
        }
 
        // (...)  

Do pełnej implementacji bonusu brakuje jeszcze klasy ShootingUpgrade, sprite'a oraz aktualizacji fabryki jednostek. Za chwilę zrobimy to przy okazji innego elementu, ale jeśli chcesz, możesz spróbować teraz, czy poradzisz sobie z tym samodzielnie.

0
Twoja ocena: Brak

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com