Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor: Piotr Szawdyński
Biblioteki C++

Sterowanie ruchem obiektów

[lekcja] Rozdział 4. Modyfikowanie kierunku ruchu obiektów w czasie rzeczywistym - sterowanie ruchem obiektów.
Ruch dla gier jest tym czym powietrze dla ludzi. Choć ludzie nie muszą o powietrzu wiedzieć nic by funkcjonować, Ty jako programista o ruchu w grach musisz wiedzieć wszystko. Ruch w grach ma niejedno oblicze. W poprzednim rozdziale przedstawiłem ruch w ujęciu w którym wiedzieliśmy dokładnie dokąd chcemy aby obiekt się nam przemieścił. W tym rozdziale zapoznamy się z inną filozofią, tj. wiemy w którym kierunku chcemy iść, ale nie wiemy jak długo.

Ruch w danym kierunku

Przypomnijmy sobie naszą strukturę z poprzedniego rozdziału:
C/C++
struct RObiekt
{
    double x;
    double y;
    double fPredkosc;
   
    //tu konstruktor i jakieś metody
};
Do tej pory przemieszczaliśmy co klatkę obiekt z maksymalną prędkością fPredkosc w osi X oraz w osi Y. Oznacza to, że jeżeli będziemy teraz chcieli co klatkę poruszać się w określonym kierunku to prędkość poruszania się w danej osi nie może być większa niż ta wartość. Taka informacja niesie za sobą pewne konsekwencje:
  • zanim obiekt zostanie przesunięty powinniśmy najpierw zebrać informacje w jakim kierunku chcemy go przemieścić;
  • kilkukrotne wywołanie przemieszczenia obiektu w tej samej klatce może spowodować zbyt szybkie przemieszczanie obiektu.
Gdy rozpoczynasz kodowanie gry to zazwyczaj nie wiesz w którym miejscu będziesz modyfikował położenie obiektów. W trakcie realizacji projektu często okazuje się, że mamy potrzebę modyfikowania położenia obiektów w różnych miejscach - raz będzie to mechanizm realizujący sztuczną inteligencję komputera, innym razem będzie to konieczność obsłużenia kolizji. Kontrolowanie każdorazowe poprawnej prędkości przemieszczenia obiektu nie powinno być więc realizowane w każdym miejscu gdzie będziemy mieli potrzebę zmiany pozycji. Mechanizm zapewniający poprawność przemieszczenia obiektów powinien być w jednym miejscu - wspólny dla całej logiki gry. Właściwym miejscem na realizację tego przedsięwzięcia jest oczywiście nasz obiekt, czyli struktura RObiekt. Aby mechanizm przemieszczania spełnił nasze wymagania będzie wymagana jego mała przebudowa w następujący sposób:
C/C++
struct RObiekt
{
    double x;
    double y;
    double fPredkosc;
   
    double ruchX; //dodano
    double ruchY; //dodano
};
Dodane dwa nowe pola struktury będą odpowiadały za tzw. potrzebę przemieszczenia obiektu w danym kierunku. Można te wartości interpretować jako prędkość z którą chcielibyśmy przemieścić nasz obiekt w danym kierunku. Wartość tych zmiennych możemy aktualizować do oporu w trakcie jednej klatki - ważne jest, aby później zaktualizować pozycję obiektu tylko jeden raz na klatkę. Implementację metody przemieszczającej obiekt warto zaszyć wewnątrz struktury RObiekt.

Implementacja przemieszczania obiektów

Napiszmy teraz metody, które spełnią nasze oczekiwania dotyczące przemieszczania obiektu. Obiekt nie może się poruszać szybciej niż wartość pola struktury fPredkosc. Ponadto mamy mieć możliwość wielokrotnej zmiany decyzji w którym kierunku obiekt powinien się poruszyć. Metody, które realizują powyższe założenia mogą wyglądać tak:
C/C++
void RObiekt::aktualizujPolozenie() //wywołujemy raz na klatkę
{
    //Ograniczamy prędkość przemieszczania obiektu w osi X i Y do właściwej wartości:
    if( ruchX > fPRedkosc )
         ruchX = fPredkosc;
   
    if( ruchX <- fPredkosc )
         ruchX = - fPredkosc;
   
    if( ruchY > fPRedkosc )
         ruchY = fPredkosc;
   
    if( ruchY <- fPredkosc )
         ruchY = - fPredkosc;
   
    //Przemieszczamy obiekt:
    x += ruchX;
    y += ruchY;
   
    //Ruch został wykonany - resetuj kierunek przemieszczenia:
    ruchX = 0;
    ruchY = 0;
}

void RObiekt::przesun( int deltaX, int deltaY ) //można wywoływać wiele razy na klatkę
{
    ruchX = deltaX;
    ruchY = deltaY;
}
Po dodaniu powyższych metod do naszego kodu należy jeszcze zadbać o to by je wywoływać w odpowiednim miejscu. Przed rysowaniem wszystkich obiektów na scenie dodamy następujący kod:
C/C++
for( VObiektyT::const_iterator i = vObiekty.begin(); i != vObiekty.end(); ++i )
     i->aktualizujPolozenie();

Kod ten zapewni nam oczywiście przemieszczanie wszystkich obiektów na scenie. Zauważ, że w tym miejscu nie zajmujemy się już problemem 'gdzie obiekt ma się przemieścić', ponieważ każdy obiekt sam 'wie' gdzie ma się przesunąć.

Wprawianie wybranych obiektów w ruch

Kwestia, która pozostała nam jeszcze do omówienia to ustalanie kierunku w którym ma się obiekt przemieszczać. Sprawa jest banalna bowiem wystarczy wywołać napisaną wcześniej metodę przesun w dowolnym miejscu kodu dla wybranego obiektu. Tak więc przesunięcie obiektu może wyglądać tak:
C/C++
vObiekty[ 0 ].przesun( 0.5, 1.5 );
Pamiętaj, że w metodzie przesun określasz prędkość z jaką ma się obiekt poruszać, a nie położenie do którego ma obiekt dojść.

Zadanie domowe

Zastosuj nowo omówioną wiedzę poprzez napisanie programu w którym będziesz przemieszczał wybrany przez Ciebie obiekt za pomocą strzałek na klawiaturze. Jeżeli nie wiesz jak sprawdzać stan wciśniętych klawiszy w bibliotece SFML, zapoznaj się z rozdziałem » Kurs SFML 1.6, C++Bezpośredni dostęp do klawiatury, myszy i joysticka lekcja.
Poprzedni dokument Następny dokument
Wprawianie obiektów gry w ruch Kurs SDL, C++