Gra sterowana kamerą - pomaluj płot

19.05.2013 - Filip Mróz
TrudnośćTrudność

Pełny ekran

Aktualnie nasza gra ma dużą wadę, mianowicie rozgrywana jest w małym okienku. W tej częsci dodamy pełnoekranowość.

Gotowy kod z tej części można znaleźć w paczce ze źródłami w katalogu: Wersja_3_Ekran

Chcemy zrobić to jak najmniejszym kosztem czyli bez wprowadzania zewnętrznej biblioteki do wyświetlania. Możemy to zrobić poprzez dopasowanie obrazu do rozmiaru okna, a następnie ustawiając odpowiednio położenie oraz rozmiar okna w taki sposób, żeby zajmował cały ekran.

Najpierw musimy ustalić rozdzielczość ekranu. Możemy ją pobrać z systemu albo wpisać odpowiednią wartość ręcznie. W przypadku systemu Windows możemy użyć metody GetSystemMetrics znajdującej się w windows.h. Dopiszmy w main.cpp deklarację sprawdzając, czy mamy odpowiedni do tego kompilator:

#ifdef _WIN32 
    #include <windows.h>
#elif defined  __unix__
 
#endif
int screenX, screenY;
main.cpp

Po połączeniu się z kamerą przygotujmy używane okno:

printf("Kamera podlaczona!\n");
stanGry.gracz.nazwa = "Filip";
 
#ifdef _WIN32 
	screenX = GetSystemMetrics(SM_CXSCREEN);
	screenY = GetSystemMetrics(SM_CYSCREEN);
#elif defined  __unix__
	screenX = 640;
	screenY = 480;
#endif
 
cvNamedWindow("Maluj plot!", CV_WINDOW_NORMAL);
cvMoveWindow("Maluj plot!", -5, -5);
cvResizeWindow("Maluj plot!", screenX, screenY);
 
stanGry.rozpocznijGre(20);
$ \dots $
main.cpp

Parametr CV_WINDOW_NORMAL oznacza, że wyświetlany obraz zostanie rozciągnięty na całe okno. Po uruchomieniu widzimy, że obraz został rozciągnęty na cały ekran.

Jest jednak mały problem. Jeśli nasz ekran ma proporcje inne niż obraz z kamery, to wyświetlany obraz zostanie zniekształcony. Załóżmy, że musimy się martwić tylko szerokimi ekranami (np. laptopa). Wtedy rozwiązanie polega na dodaniu czarnych pasów po bokach obrazu tak, aby jego rozmiar miał odpowiednie proporcje.

Zaimplementujmy funkcję wyswietlZachowujacProporcje, która wykona odpowiednie operacje i wyświetli obraz:

Mat poprawionyWyswietlanyObraz;
void wyswietlZachowujacProporcje(Mat obrazek) {
    double dodatek = (double)screenX/screenY*obrazek.rows - obrazek.cols;
 
    poprawionyWyswietlanyObraz = Mat(obrazek.rows,obrazek.cols+dodatek,obrazek.type(),Scalar_<uchar>(0));
    Mat kawalek = Mat(poprawionyWyswietlanyObraz,Range(0,obrazek.rows),Range(dodatek/2,dodatek/2+obrazek.cols));
    obrazek.copyTo(kawalek);
    imshow("Maluj plot!",poprawionyWyswietlanyObraz);
}
main.cpp

Na początku wyliczamy dodatek, który powie nam ile czarny pikseli chcemy dodać. Następnie tworzymy czarny obraz o odpowiednich proporcjach. W kolejnej linii za pomocą konstruktora Mat tworzymy podmacierz tego obrazu (coś w rodzaju okienka w obrazie), który wypełniamy zawartością obrazek.

Teraz w głównej pętli main.cpp zastąpimy zwykły sposób wyświetlania obrazu tym, który właśnie zaimplementowaliśmy:

    $ \dots $
    stanGry.wyswietlStanGry(wyswietlanyObraz);
    wyswietlZachowujacProporcje(wyswietlanyObraz);
    //imshow("Maluj plot!",wyswietlanyObraz);
    if(stanGry.graTrwa() == false) break;
}
main.cpp

Powiększmy jeszcze widzialny obraz poprzez ukrycie paska zadań i zobaczmy jak to teraz wygląda:

Widzimy, że udało nam się zachować proporcje, nie tracąc przy tym efektu pełnego ekranu.

Pewną niedogodnością jest to, że obraz z kamery nie jest taki jak odbicie w lustrze. Gdy poruszamy się w prawo, postać na ekranie porusza się w lewo, co może przeszkadzać w grze. Zaradzimy temu odbijając lustrzanie obraz zaraz po jego pobraniu z kamery:

kamera >> aktualnyObraz;
flip(aktualnyObraz,aktualnyObraz,1);
stanGry.uaktualnijStanGry(aktualnyObraz);
main.cpp

Metoda flip odbija obraz w sposób określony przez trzeci argument, w tym przypadku względem osi Y.

5
Twoja ocena: Brak Ocena: 5 (2 ocen)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com