P015 - Prosta gra zręcznościowa - BOMBOWIEC |
---|
Programy uruchomiono w środowisku Bloodshed Dev-C++ 4.9.9.2 |
Uwaga, program p015 wykorzystuje bibliotekę newconio, którą stworzyliśmy na wcześniejszych zajęciach koła. Do projektu należy dołączyć plik newconio.cpp oraz plik nagłówkowy newconio.h. Bez tych plików program nie uruchomi się.
// I Liceum Ogólnokształcące // im. K. Brodzińskiego // w Tarnowie //-------------------------- // Koło informatyczne 2006/7 //-------------------------- // Program: P015-01 //-------------------------- #include "newconio.h" #include <iostream> using namespace std; // Procedura wyświetla ekran tytułowy gry //--------------------------------------- void ekran_tytulowy() { textattr(7); clrscr(); textcolor(15); center(10,_pl("KOŁO INFORMATYCZNE '2006")); textcolor(14); center(12,"I LO w Tarnowie"); textcolor(11); center(14,"B O M B O W I E C"); textcolor(7); center(24,_pl("--- Naciśnij dowolny klawisz ---")); while(!getch()) ; } // Procedura generuje miasto //-------------------------- void generuj_miasto() { textattr(0); clrscr(); fillrectattr(0xb0,0,0,79,23); // niebo nad miastem fillrectattr(0x20,0,24,79,24); // trawnik pod miastem for(int i = 10; i < 70; i++) // miasto fillrect('_',(i%6)<<4,i,23-rand()%10,i,23); } // Funkcja sprawdza, czy miasto zawiera jakieś budynki //---------------------------------------------------- bool miasto_zburzone() { for(int i = 10; i < 70; i++) if(getchxy(i,23) == '_') return false; return true; } // Procedura gry //-------------- void bombarduj() { int wynik,sx,sy,bx,by; char key; wynik = sx = sy = 0; bx = by = 24; while(true) // Pętla zdarzeń { textattr(0xb1); gotoxy(sx,sy); cout << ">"; if(kbhit()) { while(!(key = getch())) ; if((by == 24) && (key == ' ')) { by = sy+1; bx = sx; } } if(by < 24) { textattr(0xbc); gotoxy(bx,by); if(getchxy(bx,by) == ' ') cout << '*'; else { cout << char(177); wynik++; } } textattr(0x2e); gotoxy(0,24); cout << wynik; delay(70); if(by < 24) { putchxy(' ',bx,by); by++; } putchxy(' ',sx,sy); sx++; if(sx==80) { sx = 0; sy++; } if(getchxy(sx,sy) != ' ') { textattr(0xec); gotoxy(sx,sy); cout << "X"; textattr(0xb0); center(5,"+++ ZAGINIONY W AKCJI +++"); break; } if(miasto_zburzone()) { textattr(0xb1); center(5,"*** NOWY AS LOTNICTWA BOMBOWEGO ***"); break; } } } // Funkcja sprawdza, czy gracz chce kontynuować rozgrywkę //------------------------------------------------------- bool dalsza_gra() { char key; textattr(0xbc); center(7,_pl("Jeśli chcesz zagrać jeszcze raz, naciśnij klawisz [T].")); while(!(key = getch())) ; return (key == 't') || (key == 'T'); } // Program główny //--------------- main() { _cinit(); srand((unsigned)time(NULL)); cursoroff(); ekran_tytulowy(); do { generuj_miasto(); bombarduj(); } while(dalsza_gra()); cursoron(); } |
Widok okienka konsoli
w uruchomionym programie
Gra bombowiec pochodzi z lat 80 ubiegłego wieku. Zasada jest bardzo prosta. Gracz jest pilotem bombowca, który lata ponad bombardowanym miastem (wiem, pomysł niezbyt humanitarny). Naciskając spację gracz zrzuca bombę, która burzy jeden budynek. Dopóki bomba spada, nie można zrzucić następnej bomby. Samolot po każdym przelocie obniża swój lot (prawdopodobnie skończyło mu się paliwo). Jeśli gracz nie zburzy wszystkich budynków, to samolot w końcu uderzy w jeden z nich i gra się zakończy.
Problemem w tej grze jest konstrukcja tzw. pętli zdarzeń (ang. event loop). Pętla ta wykonuje się co 70 milisekund i obsługuje szereg zdarzeń występujących w grze:
- lot samolotu
- reakcję na naciśnięcie klawisza spacji
- spadek bomby
- uderzenie samolotu w blok
- zburzenie wszystkich bloków w mieście
Pętla zdarzeń znajduje się w funkcji bombarduj() i jest następująca:
void bombarduj() { int wynik,sx,sy,bx,by; char key; |
Na początku funkcji bombarduj deklarujemy kilka zmiennych: wynik - zwiększana o 1 po zburzeniu każdego segmentu domu sx,sy - współrzędne samolotu bx,by - współrzędne bomby key - naciśnięty klawisz |
wynik = sx = sy = 0; bx = by = 24; |
Zerujemy wynik oraz sx i sy. Współrzędna samolotu 0,0 odpowiada lewemu
górnemu narożnikowi okna konsoli. Pozycją neutralną dla bomby jest ostatni wiersz okna konsoli, czyli wiersz o numerze 24. |
while(true) // Pętla zdarzeń { |
Rozpoczynamy pętlę zdarzeń. Jest to pętla nieskończona, która wykonuje się w kółko. Przerwana będzie, gdy samolot uderzy w blok lub gdy całe miasto zostanie zburzone. |
textattr(0xb1); gotoxy(sx,sy); cout << ">"; |
Na pozycji sx,sy wyświetlamy samolocik. |
if(kbhit()) { while(!(key = getch())) ; if((by == 24) && (key == ' ')) { by = sy+1; bx = sx; } } |
Teraz obsługujemy klawiaturę. Wykorzystujemy funkcję kbhit() z
biblioteki newconio. Funkcja ta zwraca true, jeśli został naciśnięty
klawisz na klawiaturze. Nie usuwa jednak tego klawisza z bufora
klawiatury. Klawisz odczytujemy w pętli while. Pętla działa dotąd, aż key zawiera kod różny od 0. Jeśli pierwszy odczyt za pomocą getch() zwróci 0, to naciśnięty klawisz jest klawiszem funkcyjnym i należy ponowić odczyt bufora klawiatury, aby odczytać jego kod matrycowy. Do tego celu potrzebujemy właśnie tej pętli while. Po odczycie klawisza sprawdzamy, czy bomba jest nieaktywna oraz, czy naciśniętym klawiszem jest spacja. Jeśli w obu przypadkach będzie to prawda, ustawiamy pozycję pionową bomby tuż pod samolotem, a pozycję poziomą w tej samej kolumnie co samolot. |
if(by < 24) { textattr(0xbc); gotoxy(bx,by); if(getchxy(bx,by) == ' ') cout << '*'; else { cout << char(177); wynik++; } } |
Następnie obsługujemy spadek bomby. Jeśli pozycja pionowa bomby nie jest pozycją neutralną 24, to bomba jest w powietrzu. W oknie konsoli na pozycji bx,by umieszczamy znak *, jeśli pozycja ta zawierała wcześniej spację lub znak kratki o kodzie 177, jeśli pozycja zawierała segment domu. W tym drugim przypadku dodatkowo zwiększamy wynik. |
textattr(0x2e); gotoxy(0,24); cout << wynik; |
Aktualny wynik wyświetlamy na początku ostatniego wiersza |
delay(70);
|
Czekamy przez 70 milisekund |
if(by < 24) { putchxy(' ',bx,by); by++; } |
Jeśli bomba jest w powietrzu, umieszczamy na jej pozycji znak spacji - w ten sposób kasujemy obraz bomby. Zwiększamy jej pionową pozycję - w następnym obiegu pętli bomba będzie wyświetlona o wiersz niżej. |
putchxy(' ',sx,sy); sx++; if(sx==80) { sx = 0; sy++; } |
Kasujemy obraz samolotu. Zwiększamy o 1 pozycję w poziomie sx. Jeśli samolot wyleciał poza prawą krawędź okna, pozycję sx zerujemy i zwiększamy o 1 pozycję w pionie sy. Spowoduje to w następnym obiegu pętli pojawienie się samolotu z lewej strony okienka konsoli, ale w wierszu niższym - samolocik opada. |
if(getchxy(sx,sy) != ' ') { textattr(0xec); gotoxy(sx,sy); cout << "X"; textattr(0xb0); center(5,"+++ ZAGINIONY W AKCJI +++"); break; } |
Sprawdzamy, czy na nowej pozycji samolocik nie uderzył w budynek. Jeśli tak, na pozycji samolotu wypisujemy literkę X oraz odpowiedni tekst. Pętla zdarzeń jest przerywana. |
if(miasto_zburzone()) { textattr(0xb1); center(5,"*** NOWY AS LOTNICTWA BOMBOWEGO ***"); break; } } } |
Sprawdzamy, czy miasto zostało zburzone. Jeśli tak, wypisujemy odpowiedni komunikat i przerywamy pętlę zdarzeń. |
Pozostała część programu nie powinna sprawić większych kłopotów.
Zastanów się, jak w pętli zdarzeń można dodać dodatkową opcję - naciśnięcie klawisza ESC (kod 27) zawsze kończy bieżącą rozgrywkę, czyli przerywa wykonywanie pętli zdarzeń.
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe