{"id":474,"date":"2018-11-30T10:57:11","date_gmt":"2018-11-30T09:57:11","guid":{"rendered":"https:\/\/www.kompikownia.pl\/?p=474"},"modified":"2019-03-16T15:32:10","modified_gmt":"2019-03-16T14:32:10","slug":"symulator-pozaru-lasu-tworzymy-okienko","status":"publish","type":"post","link":"https:\/\/www.kompikownia.pl\/index.php\/2018\/11\/30\/symulator-pozaru-lasu-tworzymy-okienko\/","title":{"rendered":"Symulator po\u017caru lasu &#8211; tworzymy okienko"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">7<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span>\n<p>W poprzedniej cz\u0119\u015bci stworzyli\u015bmy \u201epodstawy podstaw\u201d dla naszego symulatora po\u017caru lasu. Napisali\u015bmy podstawowe klasy \u2013 Tree, kt\u00f3ry przechowuje w\u0142a\u015bciwo\u015bci pojedynczego drzewa\/po\u017caru, ForestMap odpowiedzialny za przechowywanie informacji o stanie ca\u0142ej planszy oraz szereg klas pomocniczych takich jak Coordinates czy SingleCell. Postawimy kolejny ma\u0142y krok. Stworzymy klas\u0119, kt\u00f3ra b\u0119dzie obs\u0142ugiwa\u0142a wy\u015bwietlanie drzew\/po\u017car\u00f3w na ekranie. Program b\u0119dzie tak\u017ce mo\u017cliwy do skompilowania, gdy\u017c stworzymy funkcj\u0119 main(). Program b\u0119dzie ju\u017c co\u015b wy\u015bwietla\u0142. Zapraszam do lektury \ud83d\ude42<\/p>\n\n\n\n<h2 class=\"western wp-block-heading\">Wymagane biblioteki<\/h2>\n\n\n\n<p>Podstawowy interfejs graficzny zostanie stworzony w bibliotece SDL2. Wynika to z za\u0142o\u017ce\u0144, kt\u00f3re poczynili\u015bmy w poprzedniej cz\u0119\u015bci. SDL2 jest dosy\u0107 prost\u0105 (ale nie najprostsz\u0105) bibliotek\u0105 w&nbsp;obs\u0142udze. Architektura SDL-a pasuje bardziej do j\u0119zyka C ni\u017c C++, co w naszym wypadku jest drobnym problemem. Dlaczego? Poniewa\u017c b\u0119dziemy musieli \u201eopakowa\u0107\u201d funkcje SDL-owe w&nbsp;\u0142adne i przyjemne w dalszym rozwoju klasy.<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">Instalacja SDL2<\/h3>\n\n\n\n<p>Biblioteka SDL2 domy\u015blnie nie jest wbudowana w \u017cadne \u015brodowisko programistyczne. Je\u015bli b\u0119dziemy chcieli jej u\u017cywa\u0107, musimy j\u0105 zainstalowa\u0107. Proces r\u00f3\u017cni si\u0119 w zale\u017cno\u015bci od IDE kt\u00f3rego u\u017cywamy. Na niekt\u00f3rych jest pro\u015bciej, na innych trudniej. Og\u00f3lnie, instalacja sprowadza si\u0119 do pobrania plik\u00f3w biblioteki ze strony SDL2. Je\u015bli chodzi o system operacyjny Windows, s\u0105 do wyboru dwie wersje. Je\u015bli u\u017cywasz Visual Studio, wybierasz wersj\u0119 SDL2-devel-VC.zip. W przeciwnym wypadku pobierasz wersj\u0119 pod MinGW. (SDL2-devel-2.0.9-mingw.zip)<\/p>\n\n\n\n<p>Po pobraniu instalujesz bibliotek\u0119 w twoim IDE. Przyjrzymy si\u0119 szczeg\u00f3\u0142owo procesowi instalacji w \u015brodowisku Codeblocks. Wybierasz architektur\u0119 biblioteki (32 lub 64 bity). Wersja 32 bitowa znajduje si\u0119 w folderze i686-w64-mingw32, a wersja 64 bitowa w folderze x86_64-w64-mingw32. Wybierasz do instalacji odpowiedni\u0105 wersj\u0119. Je\u015bli nie wiesz, kt\u00f3r\u0105 wybra\u0107 najbezpieczniej b\u0119dzie zainstalowa\u0107 wersj\u0119 32-bitow\u0105. Nast\u0119pnie kopiujesz zawarto\u015b\u0107 folderu lib do zawarto\u015bci folderu lib twojego kompilatora (w przypadku C::B b\u0119dzie to np.: folder C:\\Program Files(x86)\\Codeblocks\\MinGW\\lib). Zawarto\u015b\u0107 folderu include kopiujesz do folderu include twojego kompilatora (C:\\Program Files(x86)\\Codeblocks\\MinGW\\include). <\/p>\n\n\n\n<p>Ostatnim krokiem jest do\u0142o\u017cenie odpowiednich opcji do linkera. W naszym wypadku b\u0119dzie to tylko jedna opcja: -lSDL2.<\/p>\n\n\n\n<p>(Je\u015bli b\u0119dziesz potrzebowa\u0142 dok\u0142adniejszych instrukcji instalacji biblioteki SDL2, pisz. Z pewno\u015bci\u0105 postaram si\u0119 pom\u00f3c. By\u0107 mo\u017ce po\u015bwi\u0119c\u0119 instalacji tej biblioteki oddzielny artyku\u0142).<\/p>\n\n\n\n<p>Dobra. Zainstalowali\u015bmy SDL-a. Przyk\u0142adowy program typu \u201eHello World\u201d znajduje si\u0119 tutaj: <a href=\"https:\/\/gist.github.com\/fschr\/92958222e35a823e738bb181fe045274\">https:\/\/gist.github.com\/fschr\/92958222e35a823e738bb181fe045274<\/a>. Je\u015bli chcesz przetestowa\u0107, czy poprawnie skonfigurowa\u0142e\u015b swoje \u015brodowisko, skopiuj ten kod do swojego \u015brodowiska programistycznego i spr\u00f3buj go skompilowa\u0107. Wszystko si\u0119 uda\u0142o i nie ma \u017cadnych b\u0142\u0119d\u00f3w kompilacji, prawda? No to \u015bwietnie! Mo\u017cemy zaj\u0105\u0107 si\u0119 tworzeniem naszego symulatora :).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"414\" height=\"240\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/11\/Sdl-logo.png\" alt=\"logo sdl\" class=\"wp-image-408\"\/><\/figure><\/div>\n\n\n\n<h2 class=\"western wp-block-heading\">SDL2 \u2013 tworzymy klas\u0119 SDLMain<\/h2>\n\n\n\n<p>Wg wst\u0119pnych za\u0142o\u017ce\u0144, ca\u0142\u0105 obs\u0142ug\u0119 biblioteki SDL za\u0142atwi jedna klasa, kt\u00f3r\u0105 nazwiemy SDLMain. B\u0119dzie ona mia\u0142a kilka metod. Utw\u00f3rzmy plik nag\u0142\u00f3wkowy SDLMain.h. Zawrzemy w&nbsp;nim definicj\u0119 naszej nowej klasy.<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"co2\">#ifndef INCLUDE_SDLMAIN_H_<\/span><br \/>\n<span class=\"co2\">#define INCLUDE_SDLMAIN_H_<\/span><br \/>\n<span class=\"co2\">#include &quot;APoint.h&quot;<\/span><br \/>\n<span class=\"co2\">#include &lt;memory&gt;<\/span><br \/>\n<span class=\"co2\">#include &lt;SDL2\/SDL.h&gt;<\/span><br \/>\n<span class=\"kw2\">using<\/span> std<span class=\"sy4\">::<\/span><span class=\"me2\">unique_ptr<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw2\">class<\/span> SDLMain <span class=\"br0\">&#123;<\/span><br \/>\n<span class=\"kw2\">public<\/span><span class=\"sy4\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">void<\/span> init<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">void<\/span> clear<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">void<\/span> drawPoint<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> x,<span class=\"kw4\">int<\/span> y,PType type<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">void<\/span> gameLoop<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">void<\/span> setResolution<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> width,<span class=\"kw4\">int<\/span> height<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw2\">private<\/span><span class=\"sy4\">:<\/span><br \/>\n&nbsp; &nbsp; unique_ptr<span class=\"sy1\">&lt;<\/span>ForestMap<span class=\"sy1\">&gt;<\/span> map<span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; SDL_Window <span class=\"sy2\">*<\/span>win <span class=\"sy1\">=<\/span> <span class=\"kw2\">nullptr<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; SDL_Renderer<span class=\"sy2\">*<\/span> renderer <span class=\"sy1\">=<\/span> <span class=\"kw2\">nullptr<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; function<span class=\"sy1\">&lt;<\/span><span class=\"kw4\">void<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span>,<span class=\"kw4\">int<\/span>,PType<span class=\"br0\">&#41;<\/span><span class=\"sy1\">&gt;<\/span> func<span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"co2\">#endif<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<h3 class=\"western wp-block-heading\">Pliki nag\u0142\u00f3wkowe oraz og\u00f3lne porady<\/h3>\n\n\n\n<p>Zacznijmy od plik\u00f3w nag\u0142\u00f3wkowych. Na razie wiele tego nie ma. Includujemy tylko to, co b\u0119dzie nam niezb\u0119dne. <a href=\"https:\/\/github.com\/karol221-10\/forest_fire\/blob\/article-2\/Include\/APoint.h\">APoint.h<\/a>, jak pami\u0119tasz, przechowuje klasy kt\u00f3re utworzyli\u015bmy poprzednim razem. Memory udost\u0119pnia nam wska\u017aniki inteligentne. W linijce 12 pojawia si\u0119 upragniony SDL.<\/p>\n\n\n\n<p>W linijce 6 u\u017cywamy dyrektywy \u201eusing\u201d. Dlaczego? Aby za ka\u017cdym razem nie pisa\u0107 std przed definicj\u0105 wska\u017anika <a href=\"https:\/\/www.kompikownia.pl\/index.php\/2018\/09\/22\/inteligentne-wskazniki-unique_ptr\/\" target=\"_blank\" rel=\"noopener noreferrer\">unique_ptr<\/a>. Mogliby\u015bmy r\u00f3wnie dobrze napisa\u0107: using namespace std; Obecnie nic by to nie zmieni\u0142o. Ale przecie\u017c program si\u0119 rozwija. Mo\u017cemy do\u0142\u0105czy\u0107 biblioteki, kt\u00f3re b\u0119d\u0105 mia\u0142y klasy o nazwach takich samych jak te, kt\u00f3re s\u0105 np.: w bibliotece standardowej std. Wtedy mieliby\u015bmy wieloznaczno\u015b\u0107 i w konsekwencji powa\u017cne problemy. To jest naprawd\u0119 dobra praktyka programistyczna przy wi\u0119kszych projektach.<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">SDLMain \u2013 sedno sprawy \u2013 skladowe prywatne<\/h3>\n\n\n\n<p>Docieramy do linijki 7, w kt\u00f3rej zaczyna si\u0119 definicja nowej klasy. Najpierw zastan\u00f3wmy si\u0119, czym konkretnie zajmowa\u0107 si\u0119 b\u0119dzie klasa SDLMain?<\/p>\n\n\n\n<p>SDLMain b\u0119dzie odpowiedzialne za stworzenie okna, w kt\u00f3rym przeprowadzimy symulacj\u0119. Klasa ta b\u0119dzie zarz\u0105dza\u0142a okresem \u017cycia tego okna oraz wszystkim tym, co b\u0119dzie w nim rysowane. Nie b\u0119dziemy na razie rozwa\u017cali obs\u0142ugi klawiatury ani innych urz\u0105dze\u0144 wej\u015bcia\/wyj\u015bcia. W&nbsp;tej wersji postaramy si\u0119 tylko o to, aby program wy\u015bwietli\u0142 nam wszystkie punkty, kt\u00f3re dodamy na sztywno do mapy.<\/p>\n\n\n\n<p>Co wynika z powy\u017cszej analizy? Co b\u0119dzie nam potrzebne? Z pewno\u015bci\u0105 jakie\u015b zmienne, kt\u00f3rych SDL u\u017cywa do zarz\u0105dzania oknem oraz bazgraniem po nim. Sp\u00f3jrz na linijki: 16 i 17. To w\u0142a\u015bnie te zmienne. Domy\u015blnie s\u0105 wynullowane, aby\u015bmy nie mieli \u017cadnych niespodzianek.<\/p>\n\n\n\n<p>Skoro SDL2Main ma rysowa\u0107 punkty zawarte w ForestMap, to musi posiada\u0107 wska\u017anik do tej\u017ce klasy. Wska\u017anik typu <a href=\"https:\/\/www.kompikownia.pl\/index.php\/2018\/09\/22\/inteligentne-wskazniki-unique_ptr\/\" target=\"_blank\" rel=\"noopener noreferrer\">unique_ptr<\/a> jest zawarty w linijce 15. Dlaczego unique? Poniewa\u017c w tym momencie zak\u0142adamy, \u017ce SDLMain b\u0119dzie jedynym w\u0142a\u015bcicielem ForestMap. Czas \u017cycia ForestMap tak\u017ce b\u0119dzie powi\u0105zany z SDLMain. To jest logiczne. Przecie\u017c nie b\u0119dziemy przechowywali wsp\u00f3\u0142rz\u0119dnych drzew i po\u017car\u00f3w po tym jak u\u017cytkownik za\u017cyczy sobie, aby program zosta\u0142 zamkni\u0119ty, prawda?<\/p>\n\n\n\n<p>W sekcji element\u00f3w prywatnych zosta\u0142a tajemnicza linijka 18. Mimo i\u017c zapis wygl\u0105da dziwnie, nie jest to nic skomplikowanego. Jest to wska\u017anik na funkcj\u0119 niezwracaj\u0105c\u0105 nic i przyjmuj\u0105c\u0105 dwa argumenty typu int oraz jeden typu PType. Po co nam ten wska\u017anik? <a href=\"https:\/\/www.kompikownia.pl\/index.php\/2018\/11\/16\/symulator-pozaru-lasu-zalozenia-i-pierwsze-kroki\/\" target=\"_blank\" rel=\"noopener noreferrer\">Przypomnij sobie funkcj\u0119 drawAll z poprzedniej cz\u0119\u015bci<\/a>, a zrozumiesz \ud83d\ude42<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">SDLMain \u2013 sedno sprawy \u2013 elementy publiczne<\/h3>\n\n\n\n<p>Za co b\u0119d\u0105 odpowiada\u0142y poszczeg\u00f3lne metody klasy SDLMain?<\/p>\n\n\n\n<ul><li><strong>void init();<\/strong><b> &#8211;<\/b> jak sama nazwa wskazuje, s\u0142u\u017cy do inicjacji\/inicjalizacji czego\u015b. To w\u0142a\u015bnie tu b\u0119dziemy tworzyli obiekty oraz przypisywali im odpowiednie warto\u015bci. W metodzie init utworzymy tak\u017ce okienko.<\/li><li><strong>void clear();<\/strong><b> &#8211; <\/b>Obraz, po\u0142o\u017cenie oraz kolor punkt\u00f3w b\u0119dzie si\u0119 zmienia\u0142. Wszak \u2013 po\u017car nie jest stacjonarny i mo\u017ce si\u0119 przemieszcza\u0107. Wobec tego musimy co ka\u017cd\u0105 klatk\u0119 aktualizowa\u0107 obraz. Aby zaktualizowa\u0107 to, co wy\u015bwietlamy w okienku musimy najpierw skasowa\u0107 to, co by\u0142o w nim narysowane wcze\u015bniej. Za to b\u0119dzie odpowiedzialna omawiana metoda.<\/li><li><strong>void drawPoint(int x,int y,Ptype type);<\/strong><b> &#8211; <\/b>metoda rysuj\u0105ca drzewo o danym stanie (type) na podanych wsp\u00f3\u0142rz\u0119dnych (x,y). Sp\u00f3jrz na definicj\u0119 tej metody. Sygnatura jest ca\u0142kowicie zgodna ze wska\u017anikiem funkcji, kt\u00f3ra znajdowa\u0142a si\u0119 we w\u0142a\u015bciwo\u015bciach prywatnych klasy.<\/li><li><strong>void gameLoop();<\/strong> &#8211; metoda, kt\u00f3ra b\u0119dzie uruchamiana przy starcie programu i w kt\u00f3rej b\u0119dzie zawarte wszystko. Zacz\u0105wszy od przygotowania ekranu i narysowania na nim wszystkiego, co u\u017cytkownik ma widzie\u0107, a zako\u0144czywszy na obs\u0142udze zdarze\u0144 wej\u015bcia\/wyj\u015bcia (kt\u00f3rej na razie nie planujemy).<\/li><li><strong>void setResolution(int width,int height) <\/strong>Chcemy, aby u\u017cytkownik m\u00f3g\u0142 zmienia\u0107 zar\u00f3wno rozmiar okna jak i rozmiar pojedynczych punkt\u00f3w. Na zrealizowanie tego pomys\u0142u istnieje kilka sposob\u00f3w. My b\u0119dziemy bawili si\u0119 rozdzielczo\u015bci\u0105. Umo\u017cliwi nam ona wp\u0142yw na rozmiar pojedynczych punkt\u00f3w bez ingerencji w pozosta\u0142\u0105 cz\u0119\u015b\u0107 programu.<\/li><\/ul>\n\n\n\n<h2 class=\"western wp-block-heading\">SDLMain \u2013 implementujemy<\/h2>\n\n\n\n<p>Skoro wiemy, jakie metody chcemy utworzy\u0107, pora zaj\u0105\u0107 si\u0119 ich implementacj\u0105. Stw\u00f3rz plik SDLMain.cpp. Nad implementacj\u0105 poszczeg\u00f3lnych metod b\u0119dziemy zastanawiali si\u0119 w&nbsp;takiej samej kolejno\u015bci jak wy\u017cej.<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">Init<\/h3>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"kw4\">void<\/span> SDLMain<span class=\"sy4\">::<\/span><span class=\"me2\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; win <span class=\"sy1\">=<\/span> SDL_CreateWindow<span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Symulator po\u017caru lasu&quot;<\/span>,SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,<span class=\"nu0\">700<\/span>,<span class=\"nu0\">700<\/span>,SDL_WINDOW_SHOWN<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; renderer <span class=\"sy1\">=<\/span> SDL_CreateRenderer<span class=\"br0\">&#40;<\/span>win,<span class=\"sy2\">-<\/span><span class=\"nu0\">1<\/span>,SDL_RENDERER_ACCELERATED<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; func <span class=\"sy1\">=<\/span> bind<span class=\"br0\">&#40;<\/span><span class=\"sy3\">&amp;<\/span>SDLMain<span class=\"sy4\">::<\/span><span class=\"me2\">drawPoint<\/span>,<span class=\"kw3\">this<\/span>,placeholders<span class=\"sy4\">::<\/span>_1,placeholders<span class=\"sy4\">::<\/span>_2,placeholders<span class=\"sy4\">::<\/span>_3<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; map <span class=\"sy1\">=<\/span> make_unique<span class=\"sy1\">&lt;<\/span>ForestMap<span class=\"sy1\">&gt;<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>W metodzie init nie dzieje si\u0119 nic szczeg\u00f3lnego. Do zmiennej win przypisujemy wynik dzia\u0142ania funkcji <i>SDL_CreateWindow<\/i>. Podobnie post\u0119pujemy ze zmienn\u0105 <i>renderer<\/i>. Warta zwr\u00f3cenia uwagi jest linijka 14. Ze \u201ewska\u017anikiem na funkcj\u0119\u201d func \u201ebindujemy\u201d metod\u0119 <i>drawPoint<\/i>. Drugim argumentem bind jest this, gdy\u017c bindujemy metod\u0119 z konkretnego obiektu. Jest nim ten, w kt\u00f3rego wn\u0119trzu obecnie si\u0119 znajdujemy. Zastanawiaj\u0105ce mog\u0105 by\u0107 ostatnie 3 argumenty. Czym s\u0105 te placeholdery? Za ich pomoc\u0105 informujemy kompilator, \u017ce do bindowanej funkcji mo\u017cemy przekaza\u0107 trzy parametry. Wniosek z tego jest prosty: placeholder\u00f3w zwykle powinno by\u0107 tyle, ile argument\u00f3w przyjmuje funkcja.<\/p>\n\n\n\n<p>Na samym ko\u0144cu tworzymy ForestMap\u0119.<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\"><b>clear<\/b><\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">void SDLMain::clear() {\n\tSDL_SetRenderDrawColor(renderer,0,0,0,255);\n\tSDL_RenderClear(renderer);\n}\n<\/pre>\n\n\n\n<p>Czyszczenie ekranu w bibliotece SDL to tylko dwie linijki kodu. W pierwszej ustawiamy kolor, na kt\u00f3ry chcemy zamalowa\u0107 ekran. <i>SetRendererDrawColor<\/i> przyjmuje jako argumenty: renderer oraz cztery liczby typu int. Pewnie domy\u015blasz si\u0119, co one oznaczaj\u0105. Pierwsze trzy to kolor zapisany w formacie RGB. Natomiast ostatnia to stopie\u0144 przezroczysto\u015bci.<\/p>\n\n\n\n<p>Kolejna linijka tej metody to nic innego jak zrealizowanie plan\u00f3w za\u0142o\u017conych w poprzednim wierszu.<i> SDL_RenderClear(renderer)<\/i> wype\u0142nia ca\u0142y ekran kolorem, kt\u00f3ry przypisali\u015bmy rendererowi za pomoc\u0105 funkcji <i>SetRendererDrawColor.<\/i><\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">drawPoint<\/h3>\n\n\n\n<p>Funkcja <i>drawPoint<\/i> jak ju\u017c doskonale wiesz, odpowiada za rysowanie pojedynczego punktu. Jak b\u0119dziemy to realizowali?<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/>28<br \/>29<br \/>30<br \/>31<br \/>32<br \/>33<br \/>34<br \/>35<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"kw4\">void<\/span> SDLMain<span class=\"sy4\">::<\/span><span class=\"me2\">drawPoint<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> x,<span class=\"kw4\">int<\/span> y,PType type<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">switch<\/span><span class=\"br0\">&#40;<\/span>type<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">case<\/span> EXIST<span class=\"sy4\">:<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class=\"br0\">&#40;<\/span>renderer,<span class=\"nu0\">0<\/span>,<span class=\"nu0\">255<\/span>,<span class=\"nu0\">0<\/span>,<span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">case<\/span> FIRE<span class=\"sy4\">:<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class=\"br0\">&#40;<\/span>renderer,<span class=\"nu0\">255<\/span>,<span class=\"nu0\">0<\/span>,<span class=\"nu0\">0<\/span>,<span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy4\">;<\/span> <br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">case<\/span> BURN<span class=\"sy4\">:<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class=\"br0\">&#40;<\/span>renderer, <span class=\"nu0\">91<\/span>, <span class=\"nu0\">46<\/span>, <span class=\"nu0\">0<\/span>, <span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">break<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; SDL_RenderDrawPoint<span class=\"br0\">&#40;<\/span>renderer,x,y<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>W linijce 23 zaczyna si\u0119 switch. Odpowiada on za to, aby\u015bmy rysowali punkty w odpowiednim kolorze. W zale\u017cno\u015bci od stanu drzewa kolor zmieniamy od zielonego (zdrowe drzewo) przez czerwony (po\u017car) do ciemnobrunatnego (spalone drzewo). Kolor rysowania punkt\u00f3w ustawiamy t\u0105 sam\u0105 funkcj\u0105, kt\u00f3rej u\u017cywali\u015bmy w metodzie clear, czyli <i>SDL_SetRendererDrawColor.<\/i><\/p>\n\n\n\n<p>Samo ustawienie koloru p\u0119dzla nic nie da. Musimy jeszcze narysowa\u0107 punkt w buforze. S\u0142u\u017cy do tego funkcja <i>SDL_RenderDrawPoint<\/i>. Dzia\u0142anie realizowane jest w linijce 36.<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">gameLoop<\/h3>\n\n\n\n<p>Metoda ta jest naszym SDL-owym \u201emainem\u201d. To w\u0142a\u015bnie wewn\u0105trz niej w przysz\u0142o\u015bci znajdzie si\u0119 zar\u00f3wno obs\u0142uga zdarze\u0144 wej\u015bcia\/wyj\u015bcia, narz\u0119dzi kt\u00f3rymi mo\u017cemy wp\u0142ywa\u0107 na stan symulacji, jak i&nbsp;wielu innych rzeczy. Na razie mamy tylko niesko\u0144czon\u0105 p\u0119tl\u0119. Zmienna is_running typu bool pilnuje, aby program zako\u0144czy\u0142 si\u0119 wtedy kiedy u\u017cytkownik sobie tego za\u017cyczy. Dzia\u0142anie to zaimplementujemy w kolejnej cz\u0119\u015bci serii. Jak wygl\u0105da generowanie ka\u017cdej pojedynczej klatki?<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>36<br \/>37<br \/>38<br \/>39<br \/>40<br \/>41<br \/>42<br \/>43<br \/>44<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"kw4\">void<\/span> SDLMain<span class=\"sy4\">::<\/span><span class=\"me2\">gameLoop<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">bool<\/span> is_running <span class=\"sy1\">=<\/span> <span class=\"kw2\">true<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">while<\/span><span class=\"br0\">&#40;<\/span>is_running<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; clear<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; map<span class=\"sy2\">-<\/span><span class=\"sy1\">&gt;<\/span>drawAll<span class=\"br0\">&#40;<\/span>func<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderPresent<span class=\"br0\">&#40;<\/span>renderer<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; SDL_Delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">1000<\/span><span class=\"sy2\">\/<\/span><span class=\"nu0\">60<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>Najpierw czy\u015bcimy ekran z pozosta\u0142o\u015bci po poprzedniej klatce (linijka 30). Nast\u0119pnie rysujemy wszystkie punkty, kt\u00f3re znajduj\u0105 si\u0119 w <i>ForestMap<\/i>. Metoda <i>drawAll<\/i> przyjmuje wska\u017anik na funkcj\u0119 func. Do wska\u017anika jak pami\u0119tasz przypisali\u015bmy metod\u0119 <i>drawPoint<\/i>. To w\u0142a\u015bnie tej metody u\u017cywa <i>drawAll<\/i> do rysowania poszczeg\u00f3lnych punkt\u00f3w.<\/p>\n\n\n\n<p>Kolejna linijka to funkcja<i> SDL_RenderPresent()<\/i> SDL2 korzysta z tzw. podw\u00f3jnego buforowania. Oznacza to, \u017ce wszystko co rysujemy nie pojawia si\u0119 natychmiastowo na ekranie. Zamiast tego informacje w\u0119druj\u0105 do specjalnego bufora. Na monitorze nie zobaczymy \u017cadnych zmian, dop\u00f3ki nie wywo\u0142amy metody <i>SDL_RenderPresent<\/i>, kt\u00f3ra kopiuje zawarto\u015b\u0107 bufora na ekran.<\/p>\n\n\n\n<p>Wzbudzaj\u0105ca zdumienie mo\u017ce by\u0107 ostatnia linijka tej p\u0119tli. Po co nam <i>SDL_Delay<\/i>? Po co sztucznie op\u00f3\u017ania\u0107, spowalnia\u0107 program? Gdy usuniesz t\u0119 linijk\u0119, a nast\u0119pnie skompilujesz i&nbsp;uruchomisz program, zobaczysz co\u015b zdumiewaj\u0105cego. Mimo i\u017c b\u0119dzie wy\u015bwietlany jedynie czarny ekran, program b\u0119dzie bra\u0142 100% CPU! Dlaczego? Poniewa\u017c domy\u015blnie komputer b\u0119dzie stara\u0142 si\u0119 wygenerowa\u0107 tyle klatek na sekund\u0119, ile zdo\u0142a. <i>SDL_Delay<\/i> pozwala nam oszcz\u0119dzi\u0107 moc procesora wprowadzaj\u0105c sztuczne ograniczenie w postaci 60 klatek na sekund\u0119. B\u0119dzie to warto\u015b\u0107 wystarczaj\u0105ca raczej dla ka\u017cdego :).<\/p>\n\n\n\n<h3 class=\"western wp-block-heading\">setResolution<\/h3>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>45<br \/>46<br \/>47<br \/>48<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"kw4\">void<\/span> SDLMain<span class=\"sy4\">::<\/span><span class=\"me2\">setResolution<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> width,<span class=\"kw4\">int<\/span> height<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; SDL_RenderSetLogicalSize<span class=\"br0\">&#40;<\/span>renderer,width,height<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; SDL_RenderSetViewport<span class=\"br0\">&#40;<\/span>renderer,<span class=\"kw2\">nullptr<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>Zosta\u0142a nam ostatnia metoda do napisania. <i>SetResolution<\/i>, ustawiaj\u0105ca rozdzielczo\u015b\u0107 logiczn\u0105. Jest ona banalna. Sk\u0142ada jedynie z dw\u00f3ch linijek. W pierwszej ustawiamy logiczny rozmiar okna, a w&nbsp;kolejnej zmuszamy SDL-a do wzi\u0119cia naszych zmian pod uwag\u0119.<\/p>\n\n\n\n<h2 class=\"western wp-block-heading\">Metoda main! Uruchamiamy program \ud83d\ude42<\/h2>\n\n\n\n<p>Pora napisa\u0107 metod\u0119 main \ud83d\ude42 Wykasuj HelloWorld czy co\u015b innego, co tworzy twoje IDE domy\u015blnie przy tworzeniu projektu. Main b\u0119dzie prosty \u2013 sk\u0142ada si\u0119 jedynie z 12 linijek.<\/p>\n\n\n<div class=\"codecolorer-container cpp default\" style=\"overflow:auto;white-space:nowrap;width:90%;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"co2\">#include &lt;iostream&gt;<\/span><br \/>\n<span class=\"co2\">#include &quot;SDLMain.h&quot;<\/span><br \/>\n<span class=\"kw2\">using<\/span> <span class=\"kw2\">namespace<\/span> std<span class=\"sy4\">;<\/span><br \/>\n<br \/>\n<span class=\"kw4\">int<\/span> main<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; SDLMain sdl<span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; sdl.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; sdl.<span class=\"me1\">clear<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; sdl.<span class=\"me1\">gameLoop<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n\n\n\n<p>W linijce 7 tworzymy obiekt naszej klasy SDLMain. W kolejnej wywo\u0142ujemy metod\u0119 init() (mo\u017cna to upro\u015bci\u0107, gdy\u017c deFacto wszystko co robimy w metodzie init() mogliby\u015bmy umie\u015bci\u0107 w konstruktorze klasy SDLMain). Nast\u0119pnie czy\u015bcimy ekran i uruchamiamy p\u0119tl\u0119 naszej aplikacji. To tyle \ud83d\ude42<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"400\" height=\"414\" src=\"https:\/\/www.kompikownia.pl\/wp-content\/uploads\/2018\/11\/z1-1.jpg\" alt=\"Symulator po\u017caru lasu wynik dzia\u0142ania cz. 2\" class=\"wp-image-477\"\/><\/figure><\/div>\n\n\n\n<p>Powy\u017cszy screen przedstawia efekt naszych dwu-odcinkowych prac. Nic niezwyk\u0142ego, prawda? Ale podstawowa mechanika ju\u017c istnieje. Mo\u017cesz testowo doda\u0107 jakie\u015b drzewa\/po\u017cary. Powiniene\u015b zrobi\u0107 to w metodzie <i>init()<\/i> klasy SDLMain() za pomoc\u0105 metody add ForestMapy. Pobaw si\u0119, poeksperymentuj. Ju\u017c nied\u0142ugo rozbudujemy ten program.<\/p>\n\n\n\n<h2 class=\"western wp-block-heading\">Co dalej?<\/h2>\n\n\n\n<p>Zrobili\u015bmy ogromny post\u0119p w stosunku do poprzedniej cz\u0119\u015bci. Nasz program ju\u017c si\u0119 uruchamia! Gdy dodamy punkty na sztywno w programie to nawet co\u015b rysuje! Jest moc! W nast\u0119pnej cz\u0119\u015bci postaramy si\u0119 zaimplementowa\u0107 kilka podstawowych narz\u0119dzi, takich jak o\u0142\u00f3wek czy spray, za pomoc\u0105 kt\u00f3rych b\u0119dziemy mogli przygotowa\u0107 sobie obszar symulacji.<\/p>\n\n\n\n<p>Je\u015bli masz jakie\u015b uwagi, zapraszam do wyra\u017cenia swojej opinii \ud83d\ude42 Kompletny kod omawianego wy\u017cej projektu znajduje si\u0119 w <a href=\"https:\/\/github.com\/karol221-10\/forest_fire\/tree\/article-2\">tym<\/a> miejscu.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Czas czytania:<\/span> <span class=\"rt-time\">7<\/span> <span class=\"rt-label rt-postfix\">minut<\/span><\/span> W poprzedniej cz\u0119\u015bci stworzyli\u015bmy \u201epodstawy podstaw\u201d dla naszego symulatora po\u017caru lasu. Napisali\u015bmy podstawowe klasy \u2013 Tree, kt\u00f3ry przechowuje w\u0142a\u015bciwo\u015bci pojedynczego drzewa\/po\u017caru, ForestMap odpowiedzialny za przechowywanie informacji o stanie ca\u0142ej planszy &#8230;<\/p>\n","protected":false},"author":1,"featured_media":494,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31,34],"tags":[],"_links":{"self":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/474"}],"collection":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/comments?post=474"}],"version-history":[{"count":28,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/474\/revisions"}],"predecessor-version":[{"id":1275,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/posts\/474\/revisions\/1275"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media\/494"}],"wp:attachment":[{"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/media?parent=474"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/categories?post=474"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kompikownia.pl\/index.php\/wp-json\/wp\/v2\/tags?post=474"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}