[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

29 sie 2010

Bronie w grze Cz.1

W poprzednim poście powierzchownie opisałem 4 rodzaje broni jakimi nasz robocik będzie dysponował. Narazie będzie miał niewyczerpalną amunicję ale z czasem się to zmieni... 
Odrazu napiszę, że kody żródłowe z poprzednich wersji troszeczkę się będą różniły od siebie, ponieważ jak zaznaczyłęm na początku uczę się obiektowości i cały czas przerabiam klasy dodając lub przenosząc pola i metody do innych powstających klas. 
Kody nie różnią się od siebie diametralnie, lecz różnice są zauważalne. Jak ktoś(o ile komuś się zechce :P)  będzie analizował kod i nie będzie czegoś rozumiał lub miał pytania proszę o pytanue w komentarzu pod danym postem to rozwieję wątpliwości :)
Myślałem jak by zrobićklasę odpowiadającą za bronie i wymyśliłem coś takiego:


class Cshots
{
   public:
   int pozpoc_x, pozpoc_y;

   void strzelaniee(int, int);

   Cshots::Cshots ()
   {
      pozpoc_x=0;
      pozpoc_y=0;  
    }  
};



void Cshots::strzelaniee(int pozx, int pozy)
{
     pozpoc_x=pozx+15;
     pozpoc_y=pozy-15;  
}



Klasa sama w sobie nic nie robi ustawia tylko początkową pozycję pocisku (x i y) dopiero w main zabawa się zaczyna :P
Tworzymy sobie 4 obiekty użyję 4 różnych kolorów(każdy kolor odpowada za dany obiekt) bo trochę jest tego kodu w main() 

Cshots strzal_bazooka;
Cshots strzal_machinegun;
Cshots strzal_laser;
Cshots strzal_flamethrower;
 

Teraz pokażę jak się będzie zmieniało w grze bronie. 
Deklarujemy i definiujemy sobie zmienną: int bron=1;
Liczby od 1 do 4 będą odpowiadały za poszczególne bronie: 

1-bazooka
2-karabin maszynowy
3-laser
4-miotacz ognia 


I analogicznie na klawiaturze będziemy zmieniali bronie za pomocą klawiszy 1,2,3,4

if(key[KEY_1])
{
     bron=1;
}

if(key[KEY_2])
{
     bron=2;
}

if(key[KEY_3])  
{
     bron=3;
}

if(key[KEY_4])
{
     bron=4;
}
_________________________________________________________________  


Strzelać będziemy spacją

if( key[KEY_SPACE]) 
{

   if(bron==1)
   {
       if( (strzal_bazooka.pozpoc_y<0) || (strzal_bazooka.pozpoc_y==0) )
      {
          strzal_bazooka.strzelaniee(ludek.pozs_x, ludek.pozs_y ); 
          play_sample(dzwiek, 200,200,1000,0);  
          ammo_bazo--;
      }
   }

   if(bron==2)
   {
       if( (strzal_machinegun.pozpoc_y<0) || (strzal_machinegun.pozpoc_y==0) )
       {
          strzal_machinegun.strzelaniee(ludek.pozs_x, ludek.pozs_y ); 
          play_sample(machingunn, 200,200,1000,0);  
       }   
   } 

   if(bron==3)
   {
       if( (strzal_laser.pozpoc_y<0) || (strzal_laser.pozpoc_y==0) )
       {
          strzal_laser.strzelaniee(ludek.pozs_x, ludek.pozs_y ); 
          play_sample(laserr, 200,200,1000,0);  
       }
   } 

   if(bron==4)
   {
        if( (strzal_flamethrower.pozpoc_y<0) ||(strzal_flamethrower.pozpoc_y==0) )
       {
          strzal_flamethrower.strzelaniee(ludek.pozs_x, ludek.pozs_y ); 
          play_sample(flamethrow, 200,200,1000,0);  
       }
   } 
}


Wytłumaczę tą część kodu. Strzelanie w grze będzie wyglądało w następujący sposób: po wybraniu broni (1,2,3,4) i naciśnięciu spacji z robocika wyleci pocisk z broni, którą mamy aktywowaną. wystrzelenie pocisku będzie możliwe jeżeli jego pozycja y będzie mniejsza od 0 lub równa 0 tzn jeżeli opuści ekran gry, lub jeżeli trafimy w jakiś cel. Na ekranie będzie mógł się znajdować tylko 1 pocisk z poszczególnej broni, aby wystrzelić kolejny pocisk musi wyjść poza ekran lub musimy w coś trafić... 
Widzimy także np:
 play_sample(flamethrow, 200,200,1000,0);  
tutaj odtwarzamy jakis dźwięk akurat dobrałem takie, które przypominają wystrzały z tych broni.

 Omówię jeszcze funkcję z klasy
void Cshots::strzelaniee(int pozx, int pozy)
{
     pozpoc_x=pozx+15;
     pozpoc_y=pozy-15;  
}


Do tej funkcji przesyłamy 2 argumenty pozycję x i y robocika aby pocisk wystrzelony z robocika wyleciał nie ze środka robocika ale z jego "głowy" ładniej to wygląda :P  
Tak więc tą funkcją nadajemy pozycję x i y pocisku troszeczkę zmodyfikowaną z pozycji robocika.
i wywołujemy tak:

strzal_flamethrower.strzelaniee(ludek.pozs_x, ludek.pozs_y ); 
_________________________________________________________________



Dobrze by było gdybyśmy wiedzieli którą broń mamy aktywowaną... Proponuję wrócić do poprzednich 2 postów, tam jest klasa Cmenu i i bitmapy, które teraz wykorzystam.
W prawym dolnym rogu będziemy wyświetlali naszą aktualną broń 

if(bron==1)
{
    masked_blit( menu_bazooka, bufor, 0,0, 674, 515, menu_bazooka->w,    menu_bazooka->h);
}

else if(bron==2)
{
    masked_blit( menu_machinegun, bufor, 0,0, 674, 515, menu_machinegun->w, menu_machinegun->h);
}

else if(bron==3)
{
    masked_blit( menu_laser, bufor, 0,0, 665, 515, menu_laser->w, menu_laser->h);
}

else if(bron==4)
{
    masked_blit( menu_flamethrower, bufor, 0,0, 665, 515, menu_flamethrower->w, menu_flamethrower->h);
}

 


_________________________________________________________________
musimy jeszcze wyświetlić nasze pociski:

if( (frame>=0) && (frame<=80) )
{
   draw_sprite(bufor, mach_gun,
strzal_machinegun.pozpoc_x,    strzal_machinegun.pozpoc_y);
}

if( (frame>=0) && (frame<=80) )
{
   draw_sprite(bufor, pocisk,
strzal_bazooka.pozpoc_x, strzal_bazooka.pozpoc_y);
}

if( (frame>=0) && (frame<=80) )
{
   draw_sprite(bufor, laser,
strzal_laser.pozpoc_x, strzal_laser.pozpoc_y);
}


if( (frame>=0) && (frame<=80) )
{
   draw_sprite(bufor, flame,
strzal_flamethrower.pozpoc_x,    strzal_flamethrower.pozpoc_y);
}

 


_________________________________________________________________ 
i wprawić nasze pociski w ruch tj. po każdym obiegu głównej pętli  while( !key[KEY_ESC]) zmieniamy współrzędną y o pewną wartość. Im większa wartość tym szybciej będzie leciał pocisk. Uważam, że te wartości jak narazie są odpowiedznie, może z biegiem czasu ulegną zmianie :P 

strzal_flamethrower.pozpoc_y=strzal_flamethrower.pozpoc_y-10;
strzal_laser.pozpoc_y=strzal_laser.pozpoc_y-30;
strzal_machinegun.pozpoc_y=strzal_machinegun.pozpoc_y-40;
strzal_bazooka.pozpoc_y=strzal_bazooka.pozpoc_y-5;
 


W następnym poście zrobię kolizję.  Do pobrania kod wraz z plikami potrzebnymi do uruchomienia gry ver.1.02
Jeżeli macie pytania, propozycje to piszcie w komentarzach, napewno odpowiem :)
Gra na tym etapie wygląda następująco:

 

1 komentarz:

  1. Super Seba ;] widzę, że robisz spore postępy ;) Teraz zważywszy na długoletnią znajomość dam Ci troszkę konstruktywnej krytyki :P

    Myślę, że powinieneś spróbować wszystko rozwiązać bardziej obiektowo, bardziej tak jak w realnym świecie. Co mam na myśli... już wyjaśniam.

    Można zrobić tak, aby klasa BROŃ miała zarówno wewnętrzne pola które będą trzymać link do dźwięku, link do obrazka, pozycję oraz powinna udostępniać m.in. metody Strzel, Wyświetl itd, czyli wszystko co robisz z BRONIĄ odbywało się w danym obiekcie.
    To funkcja Strzel powinna wewnątrz sprawdzać czy pozycja >= 0 i wtedy odtwarzać dźwięk i robić co tam jeszcze powinna. Dzięki takim zabiegom kod Maina będzie dużo bardziej czytelny, a i szukając błędów łatwiej będzie też wszystko znaleźć. Błąd ze strzelaniem ? nie szukasz błędu po całym kodzie, ale wiesz, że babol jest gdzieś w klasie Broń, funkcja Strzel ;)


    Do samych broni polecałbym również użycia Enuma np. TypBroni który zawiera Bazooke itd przy większej ilości broni, znów wszystko będzie czytelniejsze, bo nie musisz pamiętać co to jest broń 1,2,3 ? tylko aktywnaBron = TypBroni.Bazooka; i każdy wie o co kaman :D


    Jeśli przeniesiesz "ciało" metody do klasy i stworzysz enum, można pójść (ale nie trzeba) o krok dalej i stworzyć np. Listę (nie wiem czy jest w C++, ew. tablicę) wszystkich broni, po co ? hmm nawet po to, aby jeszcze bardziej oczyścić kod i pozbyć się paru ifów.

    Dzięki takiemu zabiegowi ten spory kod z if(KET[SPACE]) można zastąpić jedną linijką. Nie sprawdzamy, która broń jest aktywna i nie obchodzi nas co dzieje się po wykonaniu Strzel, oraz wiemy, że Bazooka to obiekt klasy Broń, czyli musi mieć metodę (bądź niektórzy wolą) funkcję Strzel, można to wykorzystać i napisać :

    if(KEY[SPACE])
    {
    ListaBroni[(int)aktywnaBron].Strzel();
    }

    rzutowanie niestety musi być enum=>int

    Dziękuje i pozdrawiam :D Seba jesteś na dobrej drodze :D

    OdpowiedzUsuń