[POBIERZ] kod źródłowy i inne pliki potrzebne do uruchomienia gry  [POBIERZ] 

Zachęcam do komentowania :) Mile widziane sugestie i pytania, na które chętnie odpowiem

17 sie 2010

Klasy robocika i wroga

Jak już na początku wspomiałem praca nad gierką ma mi pomóc zrozumieć obiektowość i przyszedł czas na utworzenie pierwszych klas, a wraz z nimi funkcji, którymi będziemy sterowali naszą postacią. W porównaniu do poprzedniego posta i kodu tutaj uprzątniemy wszystkie zmienne i funkcje "walające się po programie" i zamkniemy je do "pudełka" abyśmy się w przyszłości nie pogubili. (myślę, że gra będzie miała min 1500 linii kodu). Tak więc zaczynamy
Nasza 1 klasa będzie przedstawiała naszego robocika, którym kierujemy:

class Cpostac
 {
 public:
 int pozs_x, pozs_y;
 int pozpoc_x, pozpoc_y;
 void chodzenie();
 void strzelanie();
 void ograniczniki();

 Cpostac::Cpostac()
 {
   pozs_x=250;
   pozs_y=400;
   zycia=100;
 }
};


pozs_x, pozs_y; oznaczają współrzędne robocika a pozpoc_x, pozpoc_y oznaczają współrzędne jego pocisku i w konstruktorze ustalamy współrzędne robocika, jakie będzie miał po uruchomienu gry jak i jego życia. Liczba 100 będzie odpowiednia(ale o tym wspomnę kiedy indziej)
a tutaj mamy definicję metod:

void Cpostac::chodzenie()
{
  if( key[KEY_LEFT]) { pozs_x=pozs_x-2; }
  if( key[KEY_RIGHT]) { pozs_x=pozs_x+2; }
  if( key[KEY_UP]) { pozs_y=pozs_y-1; }
  if( key[KEY_DOWN]) { pozs_y=pozs_y+1; }
}

void Cpostac::ograniczniki()
{
  if(pozs_y>408) { pozs_y=408; }
  if(pozs_y<340) { pozs_y=340; }
  if(pozs_x<0) { pozs_x=0; }
  if(pozs_x>748) { pozs_x=748; }
}

void Cpostac::strzelanie()
{
  pozpoc_x=pozs_x+15;
  pozpoc_y=pozs_y-15;
}

 
 Mała zmiana, teraz gra będzie się nam wyświetlała nie w oknie, lecz na całym ekranie dlatego zmieniłem wartości funkcji void Cpostac::ograniczniki() aby były dostosowane do tej rozdzielczości...

oto funkcja, dzięki której nasza gra jest fullscreen
set_gfx_mode(GFX_AUTODETECT,800,600,0,0); 

 ________________________________________________________________________
Pora na klasę wroga

class Cwrog_easy
{
 public:
 int pozwro_x, pozwro_y;
 int pozpocwro_x, pozpocwro_y;  
 void poruszanie_wroga();
 void strzelanie_wroga();  
 
 Cwrog_easy::Cwrog_easy()
 {
   pozwro_x=rand()%740;
   pozwro_y=0;
 }
};

tutaj omówieniu wymaga  linijka w konstruktorze:
pozwro_x=rand()%550; 
oznacza ona, że pozycja x zostanie wylosowana losowo z przedziału 0-740 (po to aby nasz wróg nie spadał tylko z 1 miejsca)

i funkcje składowe:

void Cwrog_easy::poruszanie_wroga()
{
  pozwro_y++;
  if( (pozwro_y>430) || (pozwro_y==0) )
  {
    pozwro_x=rand()%740;
    pozwro_y=0;
  }
}

void Cwrog_easy::strzelanie_wroga()
{
  if( (pozpocwro_y>460) || (pozpocwro_y==0) )
  {
    pozpocwro_x=pozwro_x+7;
    pozpocwro_y=pozwro_y+25;
  }
  pozpocwro_y=pozpocwro_y+3;
}

 
Omówienie void Cwrog_easy::poruszanie_wroga():
ta funkcja jak inne będzie wywoływana w main() po przebiegu pętli  while( !key[KEY_ESC])  czyli dopóki nie naciśniemy escape i aby nasz wróg się poruszał to po każdym obiegu pętli dodajemy 1 pozwro_y++;.
 Jeżeli nasza postać dojdzie do dołu ekranu to ponownie losujemy jej współrzęną x, a ustawiamy na 0;

if( (pozwro_y>430) || (pozwro_y==0) )
{
  pozwro_x=rand()%740;
  pozwro_y=0;
}  


 Omówienie void Cwrog_easy::strzelanie_wroga();
 Ta funkcja odpowaida za strzelanie naszego wroga. Nasz wróg będzie sprzelał cały czas tzn dopóki pocisk nie opuści ekranu, a jak opuści to przypisujemy pociskowi nowe współrzędne:

if( (pozpocwro_y>460) || (pozpocwro_y==0) )
{
  pozpocwro_x=pozwro_x+7;
  pozpocwro_y=pozwro_y+25; 
}

tak jak w poprzeniej funkcji musimy wprawić nasz pocisk w ruch i po każdym przebiegu pętli dodajemy 3 aby pocisk leciał trochę szybciej od wroga  pozpocwro_y=pozpocwro_y+3;


Wkrótce pokażę klasę odpowiadającą za "menu"(tak ją nazwałem tutaj będą informacje o stanie gry amunicja, życia, pkt itp) i jak wygląda kod gry... Jak ktoś podczas czytania był spostrzegawczy i zauważył pozpocwro_y>460 (czyli jak coś wyjdzie poza ekran) i jest tutaj liczba 460, a nie 600 jak nasza rozdzielczość 800/600 a to dlatego, że w dolnej części będzie wyświetlane menu i musimy zabrać trochę miejsca z całego ekranu na menu czyli  120 pikseli...
Oto screen z wersji (ver.1.01)




5 komentarzy:

  1. A czy nie lepiej byłoby zrobić klasę Robot i klasa Postac i Wrog by dziedziczyły po niej?

    OdpowiedzUsuń
  2. tzn klasa Cpostac odpowiada za robocika, a Cwrog zrobiłem od początku, ponieważ chcę od niej dziedziczyć i tak w powstałych klasach pochodnych modyfikować zycia, poruszanie sie i strzelanie wrogow po to by bylo wiecej rodzajow wrogow ;p

    P.S. Sorry ze caly czas pisze wrogow ale jakos sie przyzywczailem ;p

    OdpowiedzUsuń
  3. Stecboss zauważ, że zarówno Robot jak i Wrog mają podobne pola. Czyli :
    - pozycja_X,
    - pozycja_Y,
    - pozycja_poczatkowa_X;
    - pozycja_koncowa_Y;

    do tego metody :
    - chodzenie / poruszanie (to samo ;) )
    - strzelanie

    Wiedząc to , polecałbym zrobić abstrakcyjną klasę (z pustymi metodami) np. basePostac, i z niej by dziedziczył Wróg i Robot, jeśli wrogów ma być wiele rodzai, nic nie szkodzi na przeszkodzie aby stworzyć taką hierarchię klas :
    basePostac => Wrog_easy => Wróg_koncowy np. statek bla bla bla

    Wybiegając niewiele w przyszłość klasa zarówno Wroga jak i Robota ma jakieś grafiki i dźwięki przypisane do niej, w pewien sposób też to można spróbować zaimplementować w basePostać ;)

    OdpowiedzUsuń
  4. Nie wiem czy bedziesz zamierzal rozszerzac to o "wiecej" wrogow niz jeden, ale moze warto zastnowic sie nad implemntacja wzorca flyweight: http://www.blackwasp.co.uk/Flyweight.aspx

    nie wiem tylko czy taka opcja bedzie Ci potrzeba. Tak czy siak chlopaki dobrze mowia iz czesc rzeczy da sie wyciagnac do wspolnej calosci (co zreszta tez jest czescia fw).

    Dodatkowo, daloby sie jakos zachowac formatowanie i/lub kolorystyke kodu? albo chociazby zmienic czcionke na couriner new - dosc ciezko sie go czyta :( dzieki!

    OdpowiedzUsuń
  5. Macie rację :) Można tak zrobić aby Cpostac i Cwrog dziedziczyly z 1 klasy...
    Ten podział na inne nazwy zmiennych składowych wział się z tego, że na początku bloga napisałem pierwszy kod strukturalnie i zmienne musiały się od siebie różnić...
    Teraz zrobię 1 klasę i te 2 będą po niej dziedziczyły, dzięki za dobry pomysł :)
    Aha i poprawiłem czytelność kodu :))

    OdpowiedzUsuń