[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:

 

26 sie 2010

wstęp do broni w grze

Napiszę teraz dlaczego w prawie każdej bitmapie występuje kolor różowy.  
Kolor różowy kod RGB(255,0,255) w allegro jest pomijany, tzn jeżeli mamy 2 obrazki: 

1. z białym tłem, jeżeli wyświetlimy tą bitmapę w programie to kolor biały(otaczające tło) także zostanie wyświetlony.

 2. z różowym tłem, jeżeli wyświetlimy tą bitmapę w programie to zostanie wyświetlona tylko bazooka, bez otaczającego ją różowego tła ponieważ kolor różowy kod RGB(255,0,255) jest pomijany.




Na początku bloga napisałem, że będą 4 rodzaje broni: bazooka, karabin maszynowy, laser i miotacz ognia. oto one:


1) bazooka:

Pocisk wystrzelony z tej broni będzie wyglądał tak: 

                                                                             



2) karabin maszynowy:
Pocisk wystrzelony z tej broni będzie wyglądał tak (zwykła kropka w paincie :P): 




3) laser:
  
Pocisk wystrzelony z tej broni będzie wyglądał tak (zwykła kreska w paincie :P): 




4) miotacz ognia:


Pocisk wystrzelony z tej broni będzie wyglądał tak : 



Oczywiście przy wystrzale z każdej broni będzie odtwarzany dźwięk, każda broń będzie inaczej się zachowywała, traciła mniej lub więcej żyć, a także planuję aby miotacz ognia pozwalał na niszczenie wrogich pocisków... Za jakiś czas wrzucę kod wraz z wszystkimi potrzebnymi plikami i jak zawsze napiszę nowego posta  wyjaśniającego wybrane fragmenty kodu.

23 sie 2010

Interfejs w grze

Kolej na obiecany interfejs...
Napewno pamiętacie grę doom, gdzie głowa głównego bohatera po stracie n-% żyć pokrywała sięcoraz bardzierj krwią... Chcę uzyskać podobny efekt, lecz będzie to niestety "kulawe graficznie" ponieważ, nie jestem grafikiem... W grze po stracie kolejnych 10% żyć robocik będzie zamalowywany coraz bardziej kolorem czerwonym....
tak więc na początek deklarujemy sobie 11 bitmap:


BITMAP *Statek_HP100 = NULL;
BITMAP *Statek_HP90 = NULL;
BITMAP *Statek_HP80 = NULL;
BITMAP *Statek_HP70 = NULL;
BITMAP *Statek_HP60 = NULL;
BITMAP *Statek_HP50 = NULL;
BITMAP *Statek_HP40 = NULL;
BITMAP *Statek_HP30 = NULL; 
BITMAP *Statek_HP20 = NULL;
BITMAP *Statek_HP10 = NULL;
BITMAP *Statek_HP0 = NULL;


I dla Statek_HP100 bitmapa będzie wyglądała tak:


 

dla Statek_HP90



*
*

i w końcu dla Statek_HP0 


W tym celu stworzyłem klasę Cmenu, w której będę umieszczał poszczególne elementy interfejsu gry... Oto ona:


class Cmenu
{
 public:
 int pozstathp_x, pozstathp_y;
 int pozmenu_x, pozmenu_y;
 int pos;
 void wyswietl_obrazki();

 Cmenu::Cmenu()
 {
   pozmenu_x=0;
   pozmenu_y=480;
   pozstathp_x=10;
   pozstathp_y=515;
   pos=0;
 }
};



 
void Cmenu::wyswietl_obrazki() 
{
 
masked_blit( menudolne, bufor,0,0,pozmenu_x,pozmenu_y,menudolne->w, menudolne->h);
 
  textprintf_ex(bufor,font,2,488,makecol(0,200,200),-1,"stanzyc: %d%%",zycia);

 
  masked_blit( Statek_HP100, bufor, 0,0, pozstathp_x,pozstathp_y,Statek_HP100->w, Statek_HP100->h);

   if(czas_odt_muz >161)
   {
      czas_odt_muz=0;
   }

   if( frame>=40)
   {  
     masked_blit( Statek_HP100, bufor, 0,0,

     pozstathp_x,pozstathp_y,Statek_HP100->w,Statek_HP100->h);

     if( (zycia > 80) && (zycia<=90) )
     {
        masked_blit( Statek_HP90,bufor,0,0,

        pozstathp_x,pozstathp_y,Statek_HP100->w, Statek_HP100->h); 
     }

     else if( (zycia > 70) && (zycia<=80) )
     {  
         masked_blit( Statek_HP80, bufor, 0,0, 

         pozstathp_x,pozstathp_y,Statek_HP100->w, Statek_HP100->h);  
     }
/*

i tak dalej az do zycia <=0
*/
   
  else if (zycia <= 0)
     {  
        masked_blit( Statek_HP0, bufor, 0,0,

        pozstathp_x,pozstathp_y,Statek_HP100->w, Statek_HP100->h); 
     }
  }  
}

 


W funkcji wyswietl_obrazki() chodzi o to aby od frame=0 do frame=40 wyswietlało nie zamalowanego robocika, a od frame=41 do frame=80 robocika z zamalowana czescia na czerwony kolor. (Niby miał to wyjść efekt popsutej poszczególnej części ale niestety nie mam talentu i wyszło jak wyszło...) Efekt jest taki: jesli mamy mniej niz 91% zyc czerwone czesci robocika zaczynaja nam migac.

w konstruktorze podałem współrzędne elementów interfejsu gry. Żeby było jasne menu_dolne  ma wymiary 800*120 i w konstruktorze jego pozycja Y to pozmenu_y=480, bo Nasza gra ma rozdzielczość 600...  a menu_dolne wygląda tak:


 różowy kolor w bitmapie oznacza, że w grze będzie niewidoczny...

Skoro napisałem o deklarowaniu bitmap to napiszę jak wczytac taka bitmape do programu, a także o tym samym tylko dla dźwięku...

dla Statek_HP100:
podajemy nazwe wczesniej zadlklarowana czyli Statek_HP100 i za pomocą tej instrukcji w cudzyslowie "" podajemy ścieżkę do pliku

Statek_HP100=load_bmp("BMP/Statek_HP/Statek_HP100.bmp",default_palette); 

musimy także pamiętać aby na końcu programu zwolnić używaną pamięć przez bitmapę instrukcją: 

destroy_bitmap(Statek_HP100); 


Warto w programie dodać taką instrukcję, uchroni nas przed jakimś poważnym błędem, a nawet zawieszeniem systemu. Stanie siętak jeśli po uruchomieniu programu zabraknie takiego pliku o tej nazwie we wskazanym przez Nas katalogu :

  if (!Statek_HP100)
{
   set_gfx_mode(GFX_TEXT,0,0,0,0);
   allegro_message("brak pliku .bmp");
   allegro_exit();
   return 0;
}
 



i to by było na tyle. Teraz kolej na dźwięk deklarujemy go w ten sposob:

SAMPLE *dzwiek = NULL;  

definiujemy w podobny sposób jak bitmapy podając ścieżkę:

dzwiek = load_sample("wybuch.wav"); 


I teraz musimy zatrzymać ten dźwięk instrukcją:

 stop_sample(dzwiek); 


i zwolnić z pamięci:

destroy_sample(dzwiek); 

i analogicznie ja kw bitmapach warto dodać instrukcję:

if (!dzwiek)
{
   set_gfx_mode(GFX_TEXT,0,0,0,0);
   allegro_message("brak pliku .wav");
   allegro_exit();
   return 0;
}
 
 
Aha w klasie Cmenu są jeszcze wyświetlane życia za pomocą funkcji:

textprintf_ex(bufor,font,2,490,makecol(0,200,200),-1,"stan zyc: %d%%", zycia); 

1-arg jest to gdzie wyświetlamy ten napis czylu u nas w buforze
2- czcionka
3 i 4 współrzędne
 makecol(0,200,200) ustalamy kolor w systemie RGB
 i nasz tekst: "stan zyc: %d%%", gdzie %d  używamy z C :p i %% aby wyświetlić % (ponieważ % jest znakiem specjalnym i żeby go wyświetlićmusimy go powtórzyć)
-i na koniec zmienna integer u nas zycia



To by było na tyle. W porównaniu do wersji 1.00 zrezygnowałem z nieefektownego elementu wybuchu, w jakiejś wersji dopracuję i dodam ponownie :).  Do pobrania kod wraz z plikami potrzebnymi do uruchomienia gry ver.1.01
Jeżeli macie pytania, propozycje to piszcie w komentarzach, napewno odpowiem :) 
Gra na tym etapie wygląda następująco: