abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 16:11 | Komunita

    Minetest (Wikipedie), tj. multiplatformní open source voxelový herní engine a hra inspirovaná Minecraftem, se přejmenovává na Luanti.

    Ladislav Hagara | Komentářů: 0
    dnes 15:44 | IT novinky

    Minulý týden byl představen (YouTube) Rocky Linux from CIQ (RLC) aneb Rocky Linux s komerční podporou od společnosti CIQ. Cena podpory je 25 000 dolarů ročně bez ohledu na počet jader CPU, serverů nebo virtuálních počítačů.

    Ladislav Hagara | Komentářů: 0
    dnes 14:22 | IT novinky

    Byla aktualizována časová osa podpory Manifest V2 v Chrome, tj. verze API rozšíření webových prohlížečů. V průběhu týdnů budou rozšíření Chrome používající tuto verzi deaktivována a uživatelům budou doporučeny alternativy používající Manifest V3. Uživatelé Chrome si mohou pomocí "chrome://extensions/" zjistit, kterých rozšíření se to týká. Například také uBlock Origin. Podporu Manifest V2 v Chrome bude možné dočasně prodloužit nastavením ExtensionManifestV2Availability.

    Ladislav Hagara | Komentářů: 0
    dnes 12:33 | Nová verze

    Sada nástrojů Distrobox pro spouštění libovolných linuxových distribucí v terminálu pomocí kontejnerů byla vydána ve verzi 1.8.0.

    Ladislav Hagara | Komentářů: 0
    dnes 10:55 | Komunita

    Byly zpracovány a zveřejněny videozáznamy z konference LinuxDays 2024. Přistupovat k nim lze přímo z programu, kde jsou také odkazy na prezentace, nebo z YouTube.

    Ladislav Hagara | Komentářů: 4
    včera 22:22 | Nová verze

    Byla vydána nová verze 1.4 svobodného multiplatformního vektorového grafického editoru Inkscape. Podrobný přehled novinek i s náhledy a animovanými gify v poznámkách k vydání.

    Ladislav Hagara | Komentářů: 0
    včera 21:55 | Nová verze

    Softwarový KVM Input Leap (dříve Barrier) byl vydán ve verzi 3.0.0 (a následně pár opravných). Přidává podporu Waylandu a Qt6. Jde o první vydání od přesunu z projektu Barrier v roce 2021. Barrier vznikl jako fork Synergy, jehož verze 2 byla částečně proprietární a její bezplatná open-source verze měla umělá omezení.

    Fluttershy, yay! | Komentářů: 0
    včera 21:00 | Nová verze

    Na čem aktuálně pracují vývojáři GNOME a KDE? Pravidelný přehled novinek v Týden v GNOME a Týden v KDE.

    Ladislav Hagara | Komentářů: 9
    12.10. 06:33 | Komunita

    Přímý přenos (YouTube) z konference LinuxDays 2024, jež probíhá tento víkend v Praze v prostorách Fakulty informačních technologií Českého vysokého učení v Praze (FIT ČVUT). Na programu je spousta zajímavých přednášek.

    Ladislav Hagara | Komentářů: 3
    11.10. 07:11 | IT novinky

    Elon Musk na akci We, Robot (YouTube, 𝕏) představil Robotaxi, Robovan a vylepšeného Tesla Bota (Optimus).

    Ladislav Hagara | Komentářů: 74
    Rozcestník

    David a duchové 🤴 👻

    27.11.2023 20:29 | Přečteno: 3170× | Výběrový blog

    🇮🇱 Pomůžeš králi Davidovi vyhnat z Jeruzaléma všechny zlé duchy? (tutoriál jak si jako v céčku s pomocí knihovny raylib vyrobit uplně supr akční horrorózní plošinovku (se soudruhem Kolybáčem v hlavní roli 😛 😛 😁 😜)) 🇮🇱

    Čí xift to má král David??

    Protože ste určitě všichni nejdřiv sescrollovali dolu k hejbavejm vobrázkům, nóó tak předtim než se pustíme do programovaní asi jako musim vodpovědět čí že je to jakoby xift. Tadydle našeho soudruha Davida Kolybáče hele, se kterým to asi jakoby došlo až tak daleko, že si do patičky připnul vlajku terroristů z hamásu 😁 😁 😁 😁

    Původně jsem měla v plánu někdy na dušičky vyrobit horrorózní hru vokolo tamtoho dýňovýho incidentu s otcem Jaroslavem, jenže pak mi soudruh Kolybáč schodil z hlavní strany blogísek vo prohamáskejch libtardech 😮 🙄 Mě to děsně naštvalo aže když vám jakože neva co tady s. Kolybáč vyvádí nóó takže se na vás uplně vykašlu a nevyrobim sem už vůůbec nic. Jenže pak za ňákou dobu mi došlo že von ten Kolybáč je vlastně jenom takovej nemocnej chudák aže to co tady s tou cenzurou předved je veskutečnosti něco na způsob toho, co vyváděj jeho soudruzi, podobně vypatlaný vod reality vodtržený akademický netáhla, když třeba strhávaj plagáty s fotkama pohřešovanejch lidí který sedmýho řijna unesl tamten islámskej stát v2.0 do gazy. Tendle náš salónní komunista už asi v ulicích všecky plagátky strhnul, nóó a když už neměl co strhávat, tak hrábnul svou nemytou prackou po mým blogísku 😅.


    gratuluju si stotisicátejmiliontejprvní naštěvnik blogisku!!!! Klikni a *možná* vyhraješ 😁 😁 😁 😜


    Lidi jako Kolybáč jsou ale taky jenom voběti libtardismu, si myslim že levicová ideologie a/nebo uživání návykovejch omamnejch látek jim rozežralo mozky a už vnímaj svět jenom prostřednictvím primitivních zjednodušujících modýlků který jim do hlav nakecávaj jiný různý pomatený ultralevicový pošuci a pravdu podle nich asi jako má dycky ten, kdo umí víc nahlas křičet (anebo navopak umlčovat 😅), proto sou schopný uvěřit že terroristický hnutí, pro normálního člověka naprosto nevodlišitelný vod islámskýho státu, sou prejže ňáký chudáčci kterejm celej svět jenom furt ubližuje nebo co. A když už jsem měla ten pahýl Otce Jaroslava, tak mě napadlo že to mužu překopat a vyrobit nějakou hru/tutorial s Kolybáčem, kde se bude bojovat proti islámskýmu zlu, páč si myslim že když mu situaci na blízkým východě dostatečně jednoduše vysvětlíme, gamifikujeme a uděláme ho přímou součástí děje, tak třeba pochopí že islám == zlo. Nóó tak uvidíme, jak to na něj bude fungovat a jestli se nám ho podaří aspoň trošku polepšit 😁 Jestli to na kolybáče ňák zabere by se pak mohla vyrobit třeba ňáká zimní hra ve který by se voxidem uhličitým bojovalo proti době ledový na napravování Krályka, nebo fps/střilečka ve který by se ekologicky likvidovali lyžaři na kurýrování lyžařů (sou zase letos děsně přemnožený), nebo třeba ňákej klon papers please z prostředí současný čechijský cenzury převlečený za tzv. 'boj proti dezinformacím' na napravování zase milovniků totalitních praktik a státní zvůle 🤔 😜

    Raylib

    Raylib je jednoduchá svobodná opensourcová multiplatformní 'multimediální' knihovnička určená primárně pro programování her, má minimum externích závislostí a je uplně mrňavá. Není to žádnej herní engine, spíš hodně odlehčenej framework, takže si dost práce budeme muset udělat sami. Ukážu jak v tom jako vyrobit malou jednoduchou plošinovku, nicméně možnosti knihovničky nekončej jenom u dvourozměrnejch her, zvládá to načítání 3D objektů, má to podporu pro VR headset etc. Pod kapotou Raylib používá openGL, vulkan maj myslimže teprve v plánu a vubec je kolem tý knihovny celkem živo, takže si myslim že se to stane supr alternativou k libSDl2 😮 😜

    Jako jazyk sem vybrala vobyč cčko páč to je jazyk ve kterým je psaná i ta knihova a vubec je to uplně supr jazyk, zná ho každej takže asi i Kolybáč a bude si moct programovat tu duchobijeckou hru s náma 😁 😜. Ale Raylib má bindingy/wrappery pro víc jak šedesátku jinejch programovacích jazyků hele 😮 😁, takže si mužete vybrat cokoliv jinýho, cčko neni nutná podmínka. Pro Andreje tam je wrapper na C++, pro Krályka rustový raylib-rs nebo novější raylib-fii, pro Bystroušáka hnedka 4 knihovny pro python, pro Dušana dokonce ňáký raylib-php, takže si vyberte co se vám líbí. Ale když to nebude cčko, tak si toho holt budete muset hodně napsat sami 😛 😁 😜 😜

    Spustitelný příklady včetně zdrojáků maj tady na stránce hele, návod jak Raylib nainstalovat maj tady hele, nejdřiv ale koukněte jestli ho nááhodou nemáte už v repozitářích svý distribuce, pak by ste mohli raylib nainstalovat normálně jako balíček.

    V Debianu jsem nikde v repozitářích Raylib neviděla, tak sem nainstalovala podle návodu určenýho pro Ubuntu takle nějak:

    sudo apt install build-essential git cmake libasound2-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxinerama-dev
    git clone https://github.com/raysan5/raylib.git raylib
    cd raylib
    mkdir build && cd build
    cmake -DBUILD_SHARED_LIBS=ON ..
    make
    sudo make install
    

    David a duchové

    Vyrobíme si takovou děsně horrorózní hru. Bude to plošinovka ve který bude David běhat po dlaždicový/tiled mapě a pistolkou bojovat proti islamistickejm duchům. Mam to zatim rožčleněný na 17 kroků, vysledkem bude pustitelná hratelná věc, nicmeně eště furt ne kompletní hra. To možná až v ňákým pokračování dalším, jestli napišu. Noa jestli napišu to nvm, ale jestli mi kolybáč zase šáhne prackou na blogísek tak to je skoro jistý že napišu celej děsně dlóóóóóóóóóóóóóóuhatatatatatánckej duchovní serial 😁 😁 😏 😜


    Zdroják

    Celej zdrojáček (i všecky soubory vobrázků, zvuků a hudeb) najdete hele na gitlabu, zdrojáky jednotlivejch kroků hele taky v tom gitlabovým repozitáři. Ze srandy jsem to nazrcadlila i komoušům z kliniky hele sem, by sme si vyzkoušeli jejich pojetí svobody slova a jak to maj v porovnání s tim našim kolybáčem, rači k tomudle druhýmu repozitáři přistupujte jako by byl hostovanej někde v kldr nebo v ňákým bělorusku (legrační bude už jenom to jak je to bude sejřit že to nemužou smazat páč nechtěj bejt za stejný cenzory proti kterejm prejže ty smažky bojujou 😁 😁)

    Obrázky, zvuky, hudba a tak

    Se mi podařilo nacpat na gitlab, všecko hele najdete ve složšce 'assets'. Který lidi jaký zvuky a muziku vyrobili najdete hele dole v 'credits'

    Rejstřík

    Tvl je to hrozně velkej blogovej zapisek (páč sem sem pro jistotu nakopirovala celý změněný zdrojáčky dycky), tak sem rači udělala pro víc rychlejší vorientaci rejstřík 😅 😜

    (asi by bylo dobrý si zapnout javascript jestli ho máte vyplej páč pak sou tady na abclinuxu zdrojáčky rozbalovávací a zbalovávací a nebude to zabirat tolik moc mista)

    Krok jedna: založíme a přichystáme si projekt 😁

    Začneme tim, že si někde vyrobíme složšku projektu, pomenujem to třeba David_a_duchove, tam si vyrobíme další složšku, 'src', kam budeme psát zdroják. Vyrobíme dva soubory, v kořenový složšce soubor 'CMakeLists.txt' a ve složšce 'src' soubor 'main.c'. 'CMakeLists.txt' bude takovej jakože návod pro cmake, jak vyrobit 'Makefile', kterým pak zkompilujeme samotnou hotovou binárku tý naší hry (neni to vubec tak složitý jak to možná teďko zní 😮 😜), v 'main.c' bude, jak už nám název naznačuje, bydlet 'main' funkce 😁. Tam bude hlavní loop naší hry, načítání vobrázků, muziky, budou se votamtaď volat všecky další funkce etc, prostě to bude uplně hlavní funkce 😁 😁

    mkdir David_a_duchove && cd David_a_duchove
    mkdir src
    touch CMakeLists.txt ./src/main.c
    

    Vyrobíme si složšky 'build' a 'assets'. Ve složšce 'build' budeme sestavovat hotovou spustitelnou binárku, do složšky 'assets' budeme strkat vobrázky, zvuky, hudbu a případnej další multimediální a jinej vobsah pro naši hru. Sem to napsala tak, by si to načítalo 'assets' ze stejný relativní cesty/stejný složšky, ve který je binárka. (Todle samozdřejmě neni jediný možný řešení, si mužeme i.e. přepsat cestu k načítanejm souborům ve zdrojáku, mužeme si ve složšce 'build' udělat symlink/'zástupce' na 'assets', mužeme binárku dycky někam přesouvat/kopírovat etc).

    mkdir assets build
    

    Takže teďko bysme měli mit takovýdleho něco

    .
    └── David_a_duchove
        ├── assets
        ├── build
        ├── CMakeLists.txt
        └── src
            └── main.c
    

    Do souboru 'CMakeLists.txt' napíšeme todle:

    cmake_minimum_required(VERSION 3.0)
    project(David_a_duchove LANGUAGES C)
    add_executable(David_a_duchove ./src/main.c)
    target_link_libraries(David_a_duchove raylib m)
    install(TARGETS David_a_duchove RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
    

    Vicemeně tam jenom řikáme jak se nám ta binárka bude menovat, na třetím řádku řikáme kde máme poskovávaný *.c soubory (máme jenom jedinej, 'main.c'), na čtvrtým jaký chceme přilinkovat knihovny (pochopytelně knihovnu 'raylib', to 'm' je matematická knihovna ze stdlib páč se nám bude hodit na různý kejkle), na posledním řádku řikáme kam se to bude jakože instalovat/přesouvat když zadáme příkaz 'make install' ('CMAKE_CURRENT_SOURCE_DIR' je normálně složška se zdrojákem, nicmeně za složšku se zdrojákem to považuje tu, kde je strčenej 'CMakeLists.txt', takže tim vodkazujeme na kořenovej adresář projektu).

    Když už máme 'CMakeLists.txt' přichystanej, tak si mužem vyrobit 'Makefile'. Uděláme to tak, že ve složšce 'build' zavoláme cmake, který nám ho na základě vobsahu souboru 'CMakeLists.txt' vygeneruje:

    cd build
    cmake ..
    

    Hru pak budeme kompilovat a přesouvat do kořenový složšky tak, že ve složšce build zavoláme 'make':

    cd build
    make David_a_duchove && make install
    

    a pustíme když v kořenový složšce zavoláme jednoduše './David_a_duchove'. Takže jednořádkovej přikaz na zkompilování a puštění zavoláme z kořenový složšky třeba takle nějak:

    make -C build David_a_duchove && make -C build install && ./David_a_duchove
    

    ....akorátže když to zavoláme teď, tak nám to akorát vyhubuje, páč v tom našem 'main.c' neni eště vubec nic napsanýho 😮 😁 Tak to poďme změnit 😁 😜

    Krok dva: základní nekonečná smyčka (a točivej měsíc) 🌝

    Takže si votevřem ten soubor 'main.c' a napišem/zkopirujem si tam todle

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    //šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // proměná která nám bude držet referenci na texturu mesice
    Texture2D textura_mesic;
    
    int main ( void )
    {
    
        // nakonfigurujeme si raylib, že budeme chtít vytvořit okno s proměnlivou velikostí a s vertikální synchronizací
        // poznámka pod čarou, ten fígl s bitovým operátorem 'or' jakože se znakem '|' funguje tak, že každá z těch flagovejch
        // konstant má hodotu nastavenou tak, by byl v jejich bytu vobsazenej dycky jenom jeden jedinej bit. Noa když uděláme
        // to bitový or, tak se nám ty proměný zkombinujou do nový unikátní hodnoty kterou ta knihovna umí rozlišit,
        // respektive čte jednotlivý bity v bajtech :O ;D
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        // inicializujeme vokno vo daný šířce, vejšce a s titulkem
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        // inicializujem audio zařízení, by sme mohli přehrávat zvuky
        InitAudioDevice();
    
        // nastavíme požadovanou frekvecni vykreslování
        // takle řikáme, že chceme vykreslovat šedesát snímků za sekundu (framů per sekundu)
        SetTargetFPS ( 60 );
    
        // načtem si ze složšky assets texturu měsice
        textura_mesic = LoadTexture ( "assets/moon.png" );
    
        // spustíme 'nekonečnej' while cyklus, ve kterým poběží ta naše hra
        // přeruší se když se zavře vokno nebo se zmáčkne na klávesnici čudlik 'escape'
        while ( !WindowShouldClose() ) {
    
    
            // uložíme si do proměný 'dt' kolik času realně uplynulo vod posledního vykreslenýho framu
            // máme sice nastavený to FPS na 60, nicmeně na to se nedá spolehnout, jednotlivý cykly nám mužou
            // trvat ruzně dlouho, něco se muže špracnout etc a je víc lepšejší a víc přesnější si tu deltu dycky změřit
            float dt = GetFrameTime();
    
    
            // začnem vykreslovat
            BeginDrawing();
    
            // překreslíme si celou vobrazovku vobdélníkem s takovým mordočerným gradientem
            // První dva argumenty funkce sou iksová a ypsilonová souřadnice levýho horního rohu toho vykreslovanýho vobdélníka,
            // když jsme tam napsali 0,0 tak tim řikáme, že ho chceme začít vykreslovat v levým horním rohu toho našeho vokna.
            // Druhý dva argumenty jsou šířka a vejška našeho vobdelnika, vykreslíme ho přes celou šířku a vejšku našeho vokna
            // poslední dva jsou barvy našeho gradientu, raylib má některý základní předdefinovaný, jinak tam mužem strkat struturu Color,
            // ve který jsou definovaný barvy RGBA v rozsahu vod nuly až po 255
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
    
            //hovorka se asi jako bojí děsně velkejch měsiců když je furt v horrorovejch komixech kreslí,
            // tak mu uděláme radost a na pozadí vykreslíme supr velkej strašidelnej měsíc :D :D
            
            //vezmem si ten víc menšejší rozměr z šiřky a vejšky naší vobrazovky, to použijem jako velikost toho měsice
            float mensi_rozmer = MIN ( GetRenderWidth(),GetRenderHeight() );
            
            // a vykreslíme texturu měsíce. Raylib má víc podobnejch funkcí pro 2D vykreslování textur,
            // použijeme 'DrawTexturePro' pokrejvá asi nejvíc nejvěší množinu různejch kombinací argumentů co ty
            // jednotlivý fce berou, vicemeně si myslim že jich de věčinu nahradit toudle fcí
            
            // první argument je textura
            
            // druhej argument je 'zdrojovej' vobdelnik, kterým definujem v textuře voblast, kterou chceme vykreslovat
            // chceme vykreslit celej měsic, takže vybereme uplně všecko, vod horního levýho vokraje (0,0) až po dolní pravej vokraj,
            // takže šiřku a vejšku zdrojovýho vobdelniku nastavíme na šířku a vejšku textury
            
            // třetí argument je 'cílovej' vobdelník, jakože voblast na našem vokně
            // Měsíc chceme vykreslit přesně uprostřed vobrazovky a nebyl by problém si
            // dopočitat iksovou a ypsilonovu souřadnici, nicmeně mužeme použít 'fígl s originem/počátkem', takže
            // jeho ikosvou a ypsilonovou souřadnici nastavíme na střed vobrazovky (půlku vejšky a půlku šířky)
            // šířku a vejšku cílovýho vobdélníka nastavíme na proměnou 'mensi_rozmer', by nám měl ten menší rozměr vobrazovky
            // uplně vyplnit
            
            // črtvrtej argument je struktura 'Vector2', jakože dvourozměrnej bod, kterej nám řiká kde má náš vobdelnik svuj počátek
            // (defaultně to je bod (0,0)). My ho nastavíme na půlku vejšky a šířky vobdelnika, tzn. do jeho středu.
            // Tim dosáhnem toho, že se nám měsic vykreslí uplně přesně doprostřed :O ;D
            
            // předposledním argumentem je uhel povotočení textury ve stupních
            // mužeme si z legrace vyrobit třeba ňákou proměnou do který budeme cpát uplynulej čas, takže se nám měsic bude furt točit :D :D
            static float uhel = 0.0f;
            uhel += dt * 50.0f;
            
            // noa poslední argument je barva. Funguje tam takovej zálkadní blending, že nám to jakože celou tu vykreslovanou texturu tou barvou pronásobí.
            // prostě si to jakoby pro každej pixel vezme jednotlivý barevný složšky a vynásbí je to s jednotlivejma barevnejma složškama zvolený barvy,
            // ty barvy je asi nejlepčí si přectavit jako hodnoty v rozsahu vod nuly až do jedničky.
            // takže když jako barvu zvolime třeba bílou jakože WHITE, tak texturu vykreslíme pronásobenou jedničkou, takže nezměněnou, Když navopak zvolime
            // černou BLACK, tak to zase prozměnu vynasobime nulama a budem mit texturu celou černou. Když si nastavíme třeba červenou RED, tak tám to
            // z puvodních RGBA kanálů nechá zase jenom červenou a vostatní barvy pronásobí nulou etc
            // Je tam nastavenej ňákej vodstín modrý, mužeme si zkusit s jednotlivejma barvičkama hejbat
            
            DrawTexturePro ( textura_mesic, ( Rectangle ) {
                0,0,textura_mesic.width,textura_mesic.height
            }, ( Rectangle ) {
                GetRenderWidth() /2, GetRenderHeight() /2, mensi_rozmer, mensi_rozmer
            }, ( Vector2 ) {
                mensi_rozmer/2,mensi_rozmer/2
            },uhel, ( Color ) {
                102, 191, 255, 255
            } );
    
            // ukončíme vykreslování
            EndDrawing();
        }
    
        // jestli se přerušil tamten náš hlavní while cyklus, tak zavřem okno, uklidíme po sobě a skončíme
        // běh programu vrácením návratový hodnoty
        CloseWindow();
    
        //uklidíme texturu, to se musí
        UnloadTexture ( textura_mesic );
    
        // vypnem audio zařízení
        CloseAudioDevice();
    
        // nakonec vrátíme nulu jakože všecko proběhlo v cajku a hotovo
        return 0;
    }
    

    V poctatě si jenom načtem jednu texturu, vytvoříme vokno naší aplikace, překreslíme černomodrým gradientem na kterým vykreslíme točivej měsíc, by jsme si ukázali, jak se jako s tim raylibem a cčkem dělá. V komentářích je všecko duležitý vysvětlený 😁 😜


    Krok tři: animace 🎞️

    Točivej měsíc byl asi jako moc pěknej, my ale potřebujem hejbavýho Davida. V 'assets' mužete vidět celej spritesheet hnedka tří aktivit Davida, je tam animace běhu, sednutí si nazadek a animace pérování v kolenou, jen to budem muset ňák rozhejbat. Boužel možnosti animací sou zatim v Raylib vomezený, maj tam ňákou základní funkci 'LoadImageAnim' pro rendrování animací ale předpokládá se asi jako jenom *.gif soubor a to se nám jakože moc nehodí. Naštěstí animace je jenom děsně moc moc kousků nějakýho vobrázku v řadě za sebou, takže si to budem moct napsat celkem snadno sami.

    Animaci Davida máme v jednom velikatatatánským obrázku, kde jsou namalovaný jednotlivý kroky tří různejch animací (takovýmu velkýmu vobrázku ve kterým sou namalovaný vedle sebe různý menčí vobrázky se řiká spritesheet nebo texturovej atlas, už sem vo tom dokonce jednou tady povidala hele 😮 😜). Si jednotlivý obrázky animace popíšeme řadou vobdelníků/rectanglů, který když ve správným pořadí naskládáme za sebe a budem po jednom zobrazovat, tak budeme vlastně vykreslovat tu animaci.

    To by mohlo bejt takle nějak

    // šířka jednotlivejch obrázků/framů animace
    // (pro necečkaře, slovičko 'DAVID_F_SIRKA' a jiný definovaný nám pak prekompilátor nahradí tou hodnotou)
    #define DAVID_F_SIRKA 150.0f
    
    // vejška jednotlivejch obrázků animace
    #define DAVID_F_VYSKA 240.0f
    
    //jednotlivý animace/pole framů
    
    // jsou to vlastně pole strutkur typu 'Rectangle'
    // rectangle deklarujeme čtyrma proměnejma:
    // 1. iksová souřadnice levýho horního rohu
    // 2. ypsilonová souřadnice levýho horního rohu
    // 3. šiřka vobdelnika
    // 4. vejška vobdelnika
    
    // všechny framy maj stejnou vejšku i šířku takže máme vlastně takovou jakože mřížku
    // když si ten vobrázek spritesheetu votevřeme v ňákým prohlížeči vobrázků,
    // tak si mužeme jednoduše prstem na monitoru vodpočítat sloupec (iksová souřadnice) a řádek (ypsilonová)
    // a tim pronásobit šiřku příp. vejšku framu a tim dostanem pozici v tý textuře
    // (nvm jestli jakoby mam vysvětlovat i takovýdle trivialni věci ale asi jo když už to dělám)
    
    
    // pole framů animace běhu
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    // pole framů animace skoku
    // ( sou to vlastně použitý některý framy běhu, takže sme vlastně ziskali
    // 4 aktivity z puvodnich 3 )
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    // pole framů animace pérování na místě/flákání se
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    // pole framů sednutí si na zadek
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    

    Tak to by sme měli vymezený ty framy ale to tak ňák eště nestačí. Budem si potřebovat pamatovat pořadí právě zobrazenýho snimku, budem si muset počítat čas, budem potřebovat nějak nastavovat rychlost přehrávání, hlídat konec animace etc. Takže si jako ve složšce 'src' vyrobíme novej soubor 'animace.h', kde si vytvoříme datovou strukturu která nám tydle proměný bude držet. Pak dvě funkce, jednu pro aktualizaci snimku textury časovou deltou (tim 'dt', který se použilo na točení točicím měsicem), druhou pro samotný vykreslování voblasti textury.

    #ifndef _DAVID_A_DUCHOVE_ANIMACE_H_
    #define _DAVID_A_DUCHOVE_ANIMACE_H_
    // ten fígl s ifndef nahoře slouží k tomu by se nám
    // soubor naimportoval jenom jednou
    
    #include <raylib.h>
    
    typedef struct Animace {
        
        // textura animace
        Texture2D textura;
    
        // jak dlouho bude trvat jeden frame/snímek animace
        float trvani_framu;
        
        // jakože vnitřní čas tý animace (se bude hodit)
        float relativni_cas;
    
        // ukazatel na pole framů (v cčku je pole a ukazatel tak trochu uplně to samý)
        Rectangle * framy;
        
        // kolik má animace framů celkem
        size_t pocet_framu;
        
        // index právě zobrazenýho framu
        int index;
    } Animace;
    
    // bere dva argumenty, ukazatel na animaci noa pak časovou deltu 
    void aktualizovatAnimaci ( Animace * animace, float dt )
    {
        //přičtem časovou deltu k tamtomu vnitřnímu času
        animace->relativni_cas += dt;
    
        // dokud je relativní čas víc věčí než je doba trvání jednoho framu,
        // tak vodečtem vod relativního času bodu trvání framu a posunem index vo jedničku
        while ( animace->relativni_cas > animace->trvani_framu ) {
            animace->relativni_cas -= animace->trvani_framu;
            animace->index++;
            
            // jestli sme vyskočili z maximální dýlky animce, tak se
            // přetočíme zpátky na začátek
            if(animace->index >= animace->pocet_framu)
                animace->index = 0;
    
        }
    }
    
    // bere tři argumenty, ukazatel na animaci, souřadnici kde se bude vykreslovat levej horní roh a barvu
    void vykreslitAnimaci ( Animace * animace, Vector2 pozice, Color barva )
    {
            DrawTextureRec ( animace->textura, animace->framy[animace->index],pozice, barva );
    }
    
    #endif
    

    V souboru 'main.c' si ten hlavičkovej soubor nahoře naimportujem, deklarujem si struktury animací a budem je v tom renderovávacím 'while' loopu furt aktualizovat a vykreslovat

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // naimportujem si vlastní hlavičku
    #include "animace.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    //šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    
    // šířka jednotlivejch obrázků/framů animace
    // (pro necečkaře, slovičko 'DAVID_F_SIRKA' a jiný definovaný nám pak prekompilátor nahradí tou hodnotou)
    #define DAVID_F_SIRKA 150.0f
    
    // vejška jednotlivejch obrázků animace
    #define DAVID_F_VYSKA 240.0f
    
    //jednotlivý animace/pole framů
    
    // jsou to vlastně pole strutkur typu 'Rectangle'
    // rectangle deklarujeme čtyrma proměnejma:
    // 1. iksová souřadnice levýho horního rohu
    // 2. ypsilonová souřadnice levýho horního rohu
    // 3. šiřka vobdelnika
    // 4. vejška vobdelnika
    
    // všechny framy maj stejnou vejšku i šířku takže máme vlastně takovou jakože mřížku
    // když si ten vobrázek spritesheetu votevřeme v ňákým prohlížeči vobrázků,
    // tak si mužeme jednoduše prstem na monitoru vodpočítat sloupec (iksová souřadnice) a řádek (ypsilonová)
    // a tim pronásobit šiřku příp. vejšku framu a tim dostanem pozici v tý textuře
    // (nvm jestli jakoby mam vysvětlovat i takovýdle trivialni věci ale asi jo když už to dělám)
    
    
    // pole framů animace běhu
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    // pole framů animace skoku
    // ( sou to vlastně použitý některý framy běhu, takže sme vlastně ziskali
    // 4 aktivity z puvodnich 3 )
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    // pole framů animace pérování na místě/flákání se
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    // pole framů sednutí si na zadek
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    int main ( void )
    {
    
        // nakonfigurujeme si raylib, že budeme chtít vytvořit okno s proměnlivou velikostí a s vertikální synchronizací
        // poznámka pod čarou, ten fígl s bitovým operátorem 'or' jakože se znakem '|' funguje tak, že každá z těch flagovejch
        // konstant má hodotu nastavenou tak, by byl v jejich bytu vobsazenej dycky jenom jeden jedinej bit. Noa když uděláme
        // to bitový or, tak se nám ty proměný zkombinujou do nový unikátní hodnoty kterou ta knihovna umí rozlišit,
        // respektive čte jednotlivý bity v bajtech :O ;D
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        // inicializujeme vokno vo daný šířce, vejšce a s titulkem
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        // inicializujem audio zařízení, by sme mohli přehrávat zvuky
        InitAudioDevice();
    
        // nastavíme požadovanou frekvecni vykreslování
        // takle řikáme, že chceme vykreslovat šedesát snímků za sekundu (framů per sekundu)
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        
        // vyrobíme si animace
        
        //animace běhání
        Animace a_behani = 
        {
            // jedna patnactina sekundy
            .trvani_framu = 1.0f/15.0f,
            
            //relativní čas a index vynulujem
            .relativni_cas = 0.0f,
            .index = 0,
            
            // textura bude ten spritesheet
            .textura = textura_david_spritesheet,
            
            // animace běhání bude mit samože framy běhu
            .framy = david_framy_behu,
            
            // počet framů ziskáme podělením velikosti celýho pole velikostí jednoho prvku
            .pocet_framu = sizeof ( david_framy_behu ) / sizeof ( Rectangle )
        };
        
        //animace skákání
        Animace a_skok = 
        {
            .trvani_framu = 1.0f/15.0f,
            .relativni_cas = 0.0f,
            .index = 0,
            .textura = textura_david_spritesheet,
            .framy = david_framy_skoku,
            .pocet_framu = sizeof ( david_framy_skoku ) / sizeof ( Rectangle )
        };
        
        //animace idle
        Animace a_idle = 
        {
            .trvani_framu = 1.0f/15.0f,
            .relativni_cas = 0.0f,
            .index = 0,
            .textura = textura_david_spritesheet,
            .framy = david_framy_idle,
            .pocet_framu = sizeof ( david_framy_idle ) / sizeof ( Rectangle )
        };
        
        //animace sednutí si
        Animace a_sed = 
        {
            .trvani_framu = 1.0f/15.0f,
            .relativni_cas = 0.0f,
            .index = 0,
            .textura = textura_david_spritesheet,
            .framy = david_framy_sed,
            .pocet_framu = sizeof ( david_framy_sed ) / sizeof ( Rectangle )
        };
    
        // spustíme 'nekonečnej' while cyklus, ve kterým poběží ta naše hra
        // přeruší se když se zavře vokno nebo se zmáčkne na klávesnici čudlik 'escape'
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // aktualizujem animace
            // ( naše funkce chce po nás ukazatel, takže tam cpem adresu )
            aktualizovatAnimaci(&a_behani, dt);
            aktualizovatAnimaci(&a_skok, dt);
            aktualizovatAnimaci(&a_idle, dt);
            aktualizovatAnimaci(&a_sed, dt);
    
    
            // začnem vykreslovat
            BeginDrawing();
    
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
    
            //vykreslíme animace
            vykreslitAnimaci(&a_behani,(Vector2){0,0},WHITE);
            vykreslitAnimaci(&a_skok,(Vector2){DAVID_F_SIRKA*1,0},WHITE);
            vykreslitAnimaci(&a_idle,(Vector2){DAVID_F_SIRKA*2,0},WHITE);
            vykreslitAnimaci(&a_sed,(Vector2){DAVID_F_SIRKA*3,0},WHITE);
    
            // skončímes vykreslováním
            EndDrawing();
        }
    
        // jestli se přerušil tamten náš hlavní while cyklus, tak zavřem okno, uklidíme po sobě a skončíme
        // běh programu vrácením návratový hodnoty
        CloseWindow();
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
    
        // vypnem audio zařízení
        CloseAudioDevice();
    
        // nakonec vrátíme nulu jakože všecko proběhlo v cajku a hotovo
        return 0;
    }
    


    To by byla uplně jednoduchá animace ale my asi jakoby budeme potřebovat trošku víc. Se nám asi jako bude hodit mit tam možnost vypínat loopování, by se jakože animace přehrála dycky jenom jednou a zustala na posledním framu (například když si David jednou sedne na zadek by zustal sedět auž se nezvedal). Pak by se nám hodilo moct tam nastavovat 'yoyo' efekt, jakože aby to ďálo že když animace dojede až nakonec, tak se začne přehrávat vod konce zpátky až na začátek (třeba ten běh, vidite že se je vidět jak se tam ta levá noha dycky skokově prohodí za pravou. S yoyo efektem to komíhání hnát bude krásně plynulý).

    Takže trošku rozvinutější struktura animace by mohla bejt třeba takle ňák, jako v nasledujicím upraveným zdrojáčku 'animace.h'. Sou tam různý kejkle vokolo ale základní princip je furt stejnej. A vyzkoušíme si tudle vylepšenou animaci rovnou na herní postavičce našeho hlavního hrdiny 😁 😜

    #ifndef _DAVID_A_DUCHOVE_ANIMACE_H_
    #define _DAVID_A_DUCHOVE_ANIMACE_H_
    // ten fígl s ifndef nahoře slouží k tomu by se nám
    // soubor naimportoval jenom jednou
    
    #include <raylib.h>
    
    typedef struct Animace {
        
        // textura animace
        Texture2D textura;
    
        // jak dlouho bude trvat jeden frame/snímek animace
        float trvani_framu;
        
        // jakože vnitřní čas tý animace (se bude hodit)
        float relativni_cas;
    
        // jestli je animace pozastavená
        bool pauznuta;
        
        // jestli má jojo efekt
        bool jojo;
        
        // jestli běží pozpátku
        bool reverzne;
        
        // jestli běží furt dokolečka nebo jestli se zasekné, když dojede nakonec
        bool loopovat;
        
        // jestli animaci vykreslujeme překlopenou vodorovně/po ose x
        bool zrcadlit;
    
        // ukazatel na pole framů (v cčku je pole a ukazatel tak trochu uplně to samý)
        Rectangle * framy;
        
        // kolik má animace framů celkem
        size_t pocet_framu;
        
        // index právě zobrazenýho framu
        int index;
    } Animace;
    
    // bere dva argumenty, ukazatel na animaci noa pak časovou deltu 
    void aktualizovatAnimaci ( Animace * animace, float dt )
    {
        if ( animace->pauznuta ) {
            return;
        }
        animace->relativni_cas += dt;
    
        while ( animace->relativni_cas > animace->trvani_framu ) {
            animace->relativni_cas -= animace->trvani_framu;
    
            if ( animace->reverzne ) {
                if ( --animace->index <= 0 ) {
                    if ( animace->loopovat ) {
                        if ( animace->jojo ) {
                            animace->index = 0;
                            animace->reverzne = false;
                        } else {
                            animace->index = animace->pocet_framu - 1;
                        }
                    } else {
                        animace->pauznuta=true;
                        animace->index=0;
                        return;
                    }
                }
            }
    
            else {
                if ( ++animace->index == animace->pocet_framu ) {
                    if ( animace->loopovat ) {
                        if ( animace->jojo ) {
                            animace->index = animace->pocet_framu - 1;
                            animace->reverzne = true;
                        } else {
                            animace->index = 0;
                        }
                    } else {
                        animace->pauznuta=true;
                        animace->index =animace->pocet_framu-1;
                        return;
                    }
                }
            }
    
        }
    }
    
    // bere tři argumenty, ukazatel na animaci, souřadnici kde se bude vykreslovat levej horní roh a barvu
    void vykreslitAnimaci ( Animace * animace, Vector2 pozice, Color barva )
    {
        // převrácení po některý s os dosháhneme nastavením šiřky a/nebo vejšky
        // zdrojovýho vobdelnika na zápornou hodnotu
        // ( víc efektivnější by asi bylo mit dvě sady animací, jednu normální a druhou s
        // překlopenou šiřkou, než to počitat v každým kroku renderu)
        if ( animace->zrcadlit ) {
            Rectangle frame = animace->framy[animace->index];
            frame.width = - frame.width;
    
            DrawTextureRec ( animace->textura, frame,pozice, barva );
        } else {
            DrawTextureRec ( animace->textura, animace->framy[animace->index],pozice, barva );
        }
    }
    
    #endif
    

    Krok čtyři: David ✡️

    Že sme si takle vykreslili animace vedle sebe v řadě je fajn, teďko je potřebujem jakoby spojit do jednoho voběktu, kterej nám bude reprezentovat hlavní herní postavičku, krále Davida. Takže si vyrobíme v 'src' novej soubor 'david.h' kde si nadefinujeme strukturu 'David'. Budem tam mit dvě funkce, jednu pro vykreslování Davida (tam viceměne jenom vykreslíme jednu z těch animací) noa funkci na aktualizovávání toho Davida, kam nastrkáme všecku jeho 'herní' logiku. Tam si nastavíme a budem chytat uživatelskej vstup z klávesnice, jakože když hráč bude mačkat šipku doleva, tak David na obrazovce půjde doleva, když hráč máčkne šipku doprava, tak David pujde doprava noa když máčkne šipku dolů, tak si David sedne nazadek - takže budeme podle toho jaký čudliky se mačkaj přepínat Davidovu aktualně zvolenou animaci a měnit jeho polohu na vobrazovce.

    (a taky si ukažeme jak načíst zvuky a jak multimediální vobsah sdílet mezi jednotlivejma souborama zdrojáčku, když David bude chodit, tak to bude dělat zvuk 😮 😜)

    Takže soubor 'david.h' by moch bejt takovejdle třeba zatim:

    #ifndef _DAVID_A_DUCHOVE_DAVID_H_
    #define _DAVID_A_DUCHOVE_DAVID_H_
    
    // naimportujem si animaci
    // (s ní se nám současně natáhne raylib.h)
    #include "animace.h"
    
    // kouzelným slovíčkem 'extern' https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
    // mužeme 'sdílet' se souborem 'main.c' v něm deklarovaný proměný, teďko na ukázku zatim jenom
    // zvuk chůze, de ale všecko :O ;D 
    extern Sound zvuk_kroku;
    
    // přestěhujem si sem z 'main.c' framy animace by to tam zbytečně nezabiralo misto ve zdrojáčku 
    #define DAVID_F_SIRKA 150.0f
    #define DAVID_F_VYSKA 240.0f
    
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    
    
    };
    
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    // tady si budeme definovat různý hodnoty a konstatny k davidoj
    // zatim si tady jenom nadeklarujeme rychlost jeho chůze
    // Je vzdálenost v 'pixelech' kterou David jakože urazí za jednu vteřinu
    #define RYCHLOST_CHUZE_DAVIDA 350.0f
    
    typedef struct David {
        
        // jednotlivý animace davida
        Animace animace_beh;
        Animace animace_idle;
        Animace animace_sed;
        Animace animace_skok;
    
        // ukazatel na animaci, která bude jakože jedniná vybraná,
        // aktualizovaná a vykreslovaná. Máme čtyry ale vidět chcem přece jako
        // jenom jednu :D :D
        Animace * aktualni_animace;
    
    
        // pozice levýho horního vokraje vykreslovaný textury
        Vector2 pozice;
        
        // okraje naší herní postavičky (vykreslíme si, když v 'main.c' nahoře aktivujem 'DEBUG')
        // bude se nám hodit v budoucnu třeba pro kolize s jinejma herníma věcma/entitamama
        // (vymezíme si menší voblast než jsou rozměry framu animace)
        Rectangle okraje;
        
        // směr kterým David kouká. Jednička znamená z leva doprava, -1 znamená z z prava doleva
        int smer;
    
    } David;
    
    // funcke na aktualizování davida, argumenty jsou ukazatel na strukturu 'David' a hodnota časový delty
    // Funkce nám bude kromě aktualizovávání Davida hlídat i uživatelský vstupy na klávesnici, tzn. mačkání
    // čudlíků, kterejma se david bude hejbat
    void aktualizovatDavida ( David * david, float dt )
    {
    
        // pokud je máčknutá na klávesnici šipka nahoru tak se kouknem jestli si david sednul na
        // zem nebo jestli si právě na zem sedá. To poznáme tim, že jako atribut 'aktualni_animace' je nastavená
        // animace sednutí si na zem, tzn. že ukazatel aktuální animace ukazuje na adresu atributu 'animace_sed'
        if ( IsKeyDown ( KEY_UP ) ) {
    
            if ( david->aktualni_animace == &david->animace_sed ) {
                
                // pro případ že je animace pauznutá (neloopujicí animace se nám samy pauznou když dojenou na konec)
                // ji vodpauzujeme....
                david->aktualni_animace->pauznuta = false;
                // ....a začnem přehrávat pozpátku
                david->aktualni_animace->reverzne=true;
    
                // pokud aktuální animace (což je furt animace sednutí si) dojela zpátky na začátek (index je nula),
                // tak přepnem aktuální animaci na takový to pérování v kolenou (do ukazatele aktualni_animace narvem adresu
                // animace idle)
                if ( david->aktualni_animace->index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            } 
        }
    
        // pokud je na klávesnici máčknutá šipka doleva a aktuální animace není animace sednutí
        // si na zem (david přece nemuže chodit když sedí, to dá rozum :D ;D), tak budem aktualizovat
        // davidovu polohu, jakože nám david jde někam doleva
        if ( IsKeyDown ( KEY_LEFT ) && david->aktualni_animace != &david->animace_sed ) {
            
            // nastavíme jeho směr doleva (vicemeně jenom kuli vykreslování animací)
            david->smer = -1;
            
            // a vytvoříme si prepozici jeho polohy, na kterou ho pak šoupnem
            // (by sme mohli jednoduše posouvat samotný vokraje i pozici, prepozice se nám ale bude hodit v dalších
            // krocích vyrábění tý naší hry)
            
            // zkopírujeme si současnou polohu vokrajů do dočasný proměný....
            Rectangle prepozice = david->okraje;
            
            // a posunem ji směrem doleva vo rychlost chůze krát časová delta
            // (aťuž si nastavíme jaký chceme FPS, když poščítáme dohromady všecky časový delty v proměný 'dt' za nějakej čas 't',
            // tak velikost toho celkovýho součtu bude +- rovna tomu času 't'. Napřiklad, my sme si nastavili fps na šedesát,
            // takže by sme měli mit (idelálně, nic neni 100% přesný) proměnou 'dt' rovnou pokaždý jedný šedesatině, páč rendrujeme
            // těch šedesát snimků za sekundu. Noa kdyby sme si poščitali hodnoty proměný 'dt' za dobu jedný vteřiny, během který
            // vyrendrujem těch 60 snímků, nóó tak budeme mit děsně překvapivě šedesát šedesátin a sme zase na jedničce, resp. na
            // jedný vteřině :O ;D. Takže když tou deltou budeme násobit rychlost, máme skoro něco jako 'posun za jednu jednotku času'
            // (fajnšmekři si mužou vygooglit věci jako sou 'derivace' nebo třeba 'diferenciál' :D ;D))
            prepozice.x -= RYCHLOST_CHUZE_DAVIDA * dt;
    
            // noa provedeme posun Davida na tu spočitanou prepozici.
            // Takže nastavíme iksovou souřadnici vokrajů na nově spočitanou hodnotu....
            david->okraje.x = prepozice.x;
            
            // ....a z vokrajů si dopočítáme iksovou souřadnici levýho horního vobdelnika framu textury
            david->pozice.x = david->okraje.x - 45;
            
            // nakonec eště musíme přepnout aktuální animaci na animaci běhu
            david->aktualni_animace = &david->animace_beh;
    
            }
        
        // pro máčknutí čudliku pravý šipky je +- uplně stejnej blok kódu jako pro máčknutí šipky doleva,
        // jenom máme ten iksovej posun kladnej 
        else if ( IsKeyDown ( KEY_RIGHT ) && david->aktualni_animace != &david->animace_sed ) {
    
            david->smer = 1;
            Rectangle prepozice = david->okraje;
            prepozice.x += RYCHLOST_CHUZE_DAVIDA * dt;
            david->okraje.x = prepozice.x;
            david->pozice.x = david->okraje.x - 45;
            david->aktualni_animace = & david->animace_beh;
            
            } 
        
        // jestli je máčkutej na klávesnici čudlik šipky dolu, tak začnem přehrávat animaci sednutí
        // si na zadek
        else if ( IsKeyDown ( KEY_DOWN ) ) {
    
            // přepnem aktualní animaci....
            david->aktualni_animace = & david->animace_sed;
            
            // ....nastavíme atribut 'reverzně' na 'false' by se nám animace přehrávala normálně,
            // jakože směrem vod začátku ke konci....
            david->aktualni_animace->reverzne = false;
            // ....a vodpauzujem ji, pro případ kdyby byla pauznutá
            david->aktualni_animace->pauznuta = false;
            }
        
        // mačkání tědlech čudliků sme si jakoby zřetězili takovou jakože nudlí if()else if() else...... takže jestli
        // sme se teďko v běhu programu dostali k tomudlectomu kousku kódu, tak neni máčknutej žádnej knoflik.
        // Koukneme se, jestli si David náhodou nesednul na zem nebo jestli si zrovna teďko nesedá nebo z tý země nevstává
        // (to poznáme tim, jestli má jako aktualní animaci nastavenou animaci sedání) noa jestli ne, tak mu přepnem
        // animaci na to akční pérování v kolenou
        else if ( david->aktualni_animace != &david->animace_sed )
        {
            david->aktualni_animace = & david->animace_idle;
        }
    
        // nastavíme vertikální překlopení vykreslování textury podle Davidova atributu 'směr', jakože podle toho, jakým
        // směrem se kouká
        david->aktualni_animace->zrcadlit = david->smer<0;
    
        // pokud je aktuální animace animace sedání a pokud ta animace dojela už na konec (animace sednutí se neloopuje,
        // takže když dojede na konec, tak se sama pauzne) tak se kouknem, na index zobrazovanýho snimku. Pokud to je první
        // snímek animace (index rovnej nule), tak víme, že David už nesedí, ani si nesedá, ani nevstává, ale že už vstal.
        // Takže přepnem animaci na 'idle'
        if ( david->aktualni_animace == &david->animace_sed ) {
            if ( david->animace_sed.pauznuta ) {
                if ( david->animace_sed.index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            }
    
        }
    
        // pokud je aktualní animace běhání, tak se kouknem jestli hraje zvuk kroků noa jestli ne,
        // ho začnem přehrávat 
        else if ( david->aktualni_animace == &david->animace_beh ) {
            if ( !IsSoundPlaying ( zvuk_kroku ) ) {
                PlaySound ( zvuk_kroku );
            }
        }
    
        // nakonec aktualizujem aktuální animaci :D ;D
        aktualizovatAnimaci ( david->aktualni_animace, dt );
    
    }
    
    // funkce na vykreslování Davida
    void vykreslitDavida ( David * david )
    {
        vykreslitAnimaci ( david->aktualni_animace, david->pozice, WHITE );
    
        // jestli je definovanej 'DEBUG', vykreslíme vokraje třeba zelenou barvičkou
    #ifdef DEBUG
        DrawRectangleLines ( david->okraje.x, david->okraje.y, david->okraje.width, david->okraje.height, GREEN );
    #endif
    }
    
    #endif
    

    Ještě si musíme pochopytelně zase překopat ten soubor 'main.c' a Davida si tam přidat 😮 😜

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    //šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    
    // zvuky
    Sound zvuk_kroku;
    
    int main ( void )
    {
    
        // nakonfigurujeme si raylib, že budeme chtít vytvořit okno s proměnlivou velikostí a s vertikální synchronizací
        // poznámka pod čarou, ten fígl s bitovým operátorem 'or' jakože se znakem '|' funguje tak, že každá z těch flagovejch
        // konstant má hodotu nastavenou tak, by byl v jejich bytu vobsazenej dycky jenom jeden jedinej bit. Noa když uděláme
        // to bitový or, tak se nám ty proměný zkombinujou do nový unikátní hodnoty kterou ta knihovna umí rozlišit,
        // respektive čte jednotlivý bity v bajtech :O ;D
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        // inicializujeme vokno vo daný šířce, vejšce a s titulkem
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        // inicializujem audio zařízení, by sme mohli přehrávat zvuky
        InitAudioDevice();
    
        // nastavíme požadovanou frekvecni vykreslování
        // takle řikáme, že chceme vykreslovat šedesát snímků za sekundu (framů per sekundu)
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        
        // vyrobíme si instance jednotlivejch animací možnejch davidovejch aktivit
        // animace běhu
    
        // jeden snímek animace nám bude trvat jednu třicetinu sekundy, relativní čas a index vynulujem, zapnem atribut 'jojo' by
        // se nám pak animace po normálním přehrání pouštěla pozpátku, nastavíme atributy 'reverzně' a 'zrcadlit' na false,
        // zapnem loopování, nastavíme texturu a pole jednotlivejch framů ve spritesheetu, počet framů/dylku pole spočitáme podělením velikosti
        // celýho pole velikostí jednoho prvku
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
        // animace sednutí si, puvodně to měla bejt animace chcípnutí jakože si ztoho sedne na zadek :D ale pak mě napadlo že ta hra
        // by mohla bejt víc zajimavější když by se david moch přikrčovat před muslimskou střelbou k zemi
        // pozn. si všimněte že má animace vypnutej loop
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            //nakopírujeme do davida jednotlivý animace
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
            
            // aktuální animaci nastavíme zatim na nulovou adresu, ten ukazatel vyplníme až 
            // adresou animace z instance Davida v tý právě vyráběný proměný 'david' 
            .aktualni_animace = NULL,
    
            //souřadnice davida
            // (je to pozice levýho horního okraje 'obrázku')
            .pozice = {GetRenderWidth()/2 - DAVID_F_SIRKA/2,200},
                        
            //směr kterým kouká (jednička je zleva doprava, -1 je zprava doleva)
            .smer = 1,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
    
            BeginDrawing();
    
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
    
            //vykreslíme davida
            vykreslitDavida(&david);
    
            EndDrawing();
        }
    
        // jestli se přerušil tamten náš hlavní while cyklus, tak zavřem okno, uklidíme po sobě a skončíme
        // běh programu vrácením návratový hodnoty
        CloseWindow();
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
    
        return 0;
    }
    


    Krok pět: Dlaždicová mapa 🖽

    Nj ale David nám jentak běhá vevzduchu. Musíme mu vyrobit ňákej svět ve kterým by se moch ňák normálně pohybovat, musel řešit řešit a vobcházet různý překážky a tak 😁 😜

    Herní svět Davidoj vyrobíme z takovejch jakože bloků, pravidelnejch čtverečků s texturou kamenů (použitá textura sou vopravdický šutry ze Zdi nářků hele třeba 😮 😜), který budeme rovnat do pravidelný dvourozměrný mřížky, takový jakože improvizovaný tiled mapy/ dlaždicový mapy. Takže si ve složšce 'src' vyrobíme novej hlavičkovej soubor 'mapa.h' a tam napišeme todle:

    #ifndef _DAVID_A_DUCHOVE_MAPA_H_
    #define _DAVID_A_DUCHOVE_MAPA_H_
    
    #include <raylib.h>
    
    // vejška a šířka kostiček, resp. 'dlaždic', ze kterejch budem skládat tu naši herní mapu
    #define BLOK_SIRKA 80
    #define BLOK_VYSKA 80
    
    // makra na zišťování maximální/minimální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b) ? (a) : (b))
    #define MIN(a, b) ((a)<(b) ? (a) : (b))
    #endif
    
    // struktura tý dlaždicový mapy
    typedef struct Mapa
    {
        // v cčku muže bejt ukazatel pole, noa když máme ukazatel na ukazatele takže tam vlastně mužeme schovat
        // 'pole polí' a tak ziskat dvourozměrný pole. Todlecto 2d pole bude vlastně taková jakože mřížka a jednotlivý
        // chlívečky v mřížce mužou bejt buďto volný misto, noa nebo šutr.Jednotlivý kostičky herní mapy budem popisovat číslem,
        // nula bude prázndej prostor, kladný číslo bude znamenat žeje tednlecten 'chlíveček v mřížce' vobsazenej pevným blokem.
        // Noa konkrétní hodnota toho čísla bude určovat konkrétní texturu v spritesheetu kamenů, kterou vykreslit (máme víc variant)
        int ** bloky;
        
        //vejška a šířka toho našeho 2d pole
        int sirka, vyska;
        
        // textura, kterou budem používat na vykreslování těch kostek
        Texture2D textura;
    }Mapa;
    
    // funkce na vykreslování mapy
    // bere tři argumenty, první je samozdřejmě ukazatel na mapu, noa pak minimální a maximální hodnota vykreslovaný iksový
    // souřadnice, ty nám vymezujou kterou voblast mapy budem malovat. Dokavaď máme tu mapu relativně malou, tak takovýho něco asi
    // jako nemusíme moc řešit. Kdybysme ale měli mapu děsně dlouhatatatatánckou bambilion kostiček tak by nám vykreslování celý mřížky
    // dlaždicový mapy žralo zbytečně celkem poctatnej kus počítacího víkonu. Proto si stanovujem vokraje vykreslovaný mapy 
    void vykreslitMapu(Mapa * mapa, float min_x, float max_x)
    {
        // vypočítáme si z hodnoty iksový polohy souřadnici kostky v dlaždicový mapě
        // (prostě to číslo podělíme dýlkou bloku/dlaždice a zavokrouhlíme. Menčí hodnotu zavokrouhlíme floorem
        // dolu, večí čislo ceilem nahoru, by sme fakt jako pokryly i ty nejvíc nejvokrajovějšejší hodnoty)
        int _min_x = (int)floor((min_x) / (float)BLOK_SIRKA);
        int _max_x = (int)ceil((max_x) / (float)BLOK_SIRKA);
        
        // si pohlídáme si by sme mezema nevyskočili z mapy a nelezli mimo voblast pole
        // takže dolní mez muže bejt minimálně nula....
        _min_x = MAX(0, _min_x);
        // ....a horní mez maximálně velká jako šířka celý mapy
        _max_x = MIN(mapa->sirka, _max_x);
        
        // projdeme si mapu vod min_x až po max_x sloupec po sloupci....
        for(int x = _min_x; x < _max_x; x++)
        {
            // každej sloupeček budem číst vodzhora až dolu
            for(int y = 0; y < mapa->vyska; y++)
            {
                // a pro každej chlíveček v tý 2d mřížce se kouknem jaká je tam skovaná hodnota 
                int blok = mapa->bloky[y][x];
                
                //noa jestli to neni nula (nebo zaporný čislo), tak vykreslíme vodpovidajicí kostku
                if(blok)
                    // jeruzálémský kameny sou ve spritesheetu srovnaný v jednom řádku za sebou takže vodpovidajicí pořadí ziskame pronásobením
                    // dýlky kostky hodnotou vobsaženou v proměný 'blok'. Šutry maj ve spritesheetu kolem sebe trošku volnýho místa (by se předešlo
                    // tile bleedingu), tendle vokraj musíme zohlednit (sou to ty 2.0f, co tam strašej)  
                    DrawTextureRec(mapa->textura, (Rectangle){2.0f +84.0f * (float)(blok-1),2.0f,80.0f,80.0f},(Vector2){(float)x*BLOK_SIRKA,(float)y*BLOK_VYSKA},DARKBLUE);
            }
            
        }
        
        // noa teďko mě napadnul uplně supr zlepšovák pro vykreslování tý naší mapy, by nám jentak nevysela vevzuduchu jako taková tenká vrstva
        // tlustá jenom jednu kostku na vejšku. Projdeme si zase jako celou mapu a kouknem jestli souřadnice v tom nejvíc nejspodnějším řádku mapy
        // neni ďoura, noa jestli neni resp. je tam pevnej blok, tak eště tři kostičky vykreslíme
        // ( jestli nastavíme vejšku mapy na deset kostiček, tak to bude dohromady nějakejch 800 pixelů. Vejšku vokna máme definovanou v main.c jako
        // 960 pixelů, takže když budeme vykreslovat naši dlaždicovou mapu na pozici (0,0) jakože v levým a hlavně horním rohu vobrazovky, tak nám
        // na vejšku na pokrytí celý vobrazovky zbejvá eště 160 pixelů, to sou dvě kostky, přestřelíme na tři (vono se to s
        // tou oblastí vobrazovky pak bude trošku komplikovat až začnem dělat s kamerou v některým z dalších kroků))
    
        for(int x = _min_x; x < _max_x; x++)
        {
            if(mapa->bloky[mapa->vyska-1][x] != 0)
            for(int y = mapa->vyska; y < mapa->vyska + 3; y++)
            {
                int index = mapa->bloky[mapa->vyska - 1][x];
                index = 7;
                DrawTextureRec(mapa->textura, (Rectangle){2 +84*(index-1),2,80,80},(Vector2){x*BLOK_SIRKA,y*BLOK_VYSKA},DARKBLUE);
            }
        }
    }
    
    // funkce na vytažení hodnoty bloku mapy na souřadnicích 'x' a 'y'
    // jenom to hlídá by sme nevyskočili z mapy a neptali se na hodnotu ležicí mimo rozsah toho 2d pole
    // (hežčí by to asi jako bylo hlídat ty meze v těch druhejch funkcích páč by to zredukovalo množšství
    // volání ifů)
    int getBlokMapy(int x, int y, Mapa * mapa)
    {    
        if(x >= 0 && x < mapa->sirka && y>=0 && y < mapa->vyska)
        {
            return mapa->bloky[y][x];
        }
        // jestli sme vyskočili z mapy, vrátíme -1
        return -1;
    }
    
    // funkce na zišťování, jestli bod leží ve voblasti některý z kostek mapy 
    bool kolizeSeBlokemMapy_bod(Vector2 bod, Mapa * mapa)
    {
        // převedem si souřadnici na polohu v mapě 
        int x = (int)floor(bod.x / (float)BLOK_SIRKA);
        int y = (int)floor(bod.y / (float)BLOK_VYSKA);
        // a kouknem jestli je to kladná hodnota
        // (v cčku by sme to mohli napsat i bez toho '> 0' na konci :O ;D)
        return getBlokMapy(x,y, mapa) > 0;
    }
    
    // funkce na zišťování, jestli vobdelnik leží na některý kostce mapy
    bool kolizeRectSeBlokemMapy(Rectangle box, Mapa * mapa)
    {
        // převedem si souřadnice vobdelnika do souřadnic mapy
        int x = (int)floor((box.x) / (float)BLOK_SIRKA);
        int y = (int)floor(box.y / (float)BLOK_VYSKA);
        
        int y_max = (int)ceil((box.y + box.height) / (float)BLOK_VYSKA);
        int x_max = (int)ceil((box.width + box.x) / (float)BLOK_VYSKA);
    
        // a projdem všecky chlívečky mřížky, do kterejch ten náš vobdelnik zasahuje
        // pokavaď aspoň jeden chlíveček vobsahuje bevnej blok, tak máme kolizi
        for (int j = x; j < x_max; j++)
        for (int i = y; i < y_max; i++)
        {
            if(getBlokMapy(j,i, mapa) > 0)
                return true;
        }
        
        return false;
    }
    
    #endif
    

    Teďkonc upravíme kód Davida, by si jeho struktura v sobě držela referenci na dlaždicovou mapu ve který se David jakože pohybuje, pak upravíme kód aktualizace Davida by sme tam hlídali narážení do bloků herní mapy (jinak by nám David vlez do kostky noa to by sme mohli považovat za bug :explode: 😮)

    #ifndef _DAVID_A_DUCHOVE_DAVID_H_
    #define _DAVID_A_DUCHOVE_DAVID_H_
    
    // naimportujem si animaci
    // (s ní se nám současně natáhne raylib.h)
    #include "animace.h"
    #include "mapa.h"
    
    // kouzelným slovíčkem 'extern' https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
    // mužeme 'sdílet' se souborem 'main.c' v něm deklarovaný proměný, teďko na ukázku zatim jenom
    // zvuk chůze, de ale všecko :O ;D 
    extern Sound zvuk_kroku;
    
    // přestěhujem si sem z 'main.c' framy animace by to tam zbytečně nezabiralo misto ve zdrojáčku 
    #define DAVID_F_SIRKA 150.0f
    #define DAVID_F_VYSKA 240.0f
    
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    
    
    };
    
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    // tady si budeme definovat různý hodnoty a konstatny k davidoj
    // zatim si tady jenom nadeklarujeme rychlost jeho chůze
    // Je vzdálenost kterou david urazí za jednu vteřinu
    #define RYCHLOST_CHUZE_DAVIDA 350.0f
    
    typedef struct David {
        
        // jednotlivý animace davida
        Animace animace_beh;
        Animace animace_idle;
        Animace animace_sed;
        Animace animace_skok;
    
        // ukazatel na animaci, která bude jakože jedniná vybraná,
        // aktualizovaná a vykreslovaná. Máme čtyry ale vidět chcem přece jako
        // jenom jednu :D :D
        Animace * aktualni_animace;
    
    
        // pozice levýho horního vokraje vykreslovaný textury
        Vector2 pozice;
        
        // okraje naší herní postavičky (vykreslíme si, když v 'main.c' nahoře aktivujem 'DEBUG')
        // bude se nám hodit v budoucnu třeba pro kolize s jinejma herníma věcma/entitamama
        // (vymezíme si menší voblast než jsou rozměry framu animace)
        Rectangle okraje;
        
        // směr kterým David kouká. Jednička znamená z leva doprava, -1 znamená z z prava doleva
        int smer;
        
        // dlaždicová mapa, ve který se david pohybuje
        Mapa * mapa;
    
    } David;
    
    // funcke na aktualizování davida, argumenty jsou ukazatel na strukturu 'David' a hodnota časový delty
    // Funkce nám bude kromě aktualizovávání Davida hlídat i uživatelský vstupy na klávesnici, tzn. mačkání
    // čudlíků, kterejma se david bude hejbat
    void aktualizovatDavida ( David * david, float dt )
    {
    
        // pokud je máčknutá na klávesnici šipka nahoru tak se kouknem jestli si david sednul na
        // zem nebo jestli si právě na zem sedá. To poznáme tim, že jako atribut 'aktualni_animace' je nastavená
        // animace sednutí si na zem, tzn. že ukazatel aktuální animace ukazuje na adresu atributu 'animace_sed'
        if ( IsKeyDown ( KEY_UP ) ) {
    
            if ( david->aktualni_animace == &david->animace_sed ) {
                
                // pro případ že je animace pauznutá (neloopujicí animace se nám samy pauznou když dojenou na konec)
                // ji vodpauzujeme....
                david->aktualni_animace->pauznuta = false;
                // ....a začnem přehrávat pozpátku
                david->aktualni_animace->reverzne=true;
    
                // pokud aktuální animace (což je furt animace sednutí si) dojela zpátky na začátek (index je nula),
                // tak přepnem aktuální animaci na takový to pérování v kolenou (do ukazatele aktualni_animace narvem adresu
                // animace idle)
                if ( david->aktualni_animace->index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            } 
        }
    
    
        
        // voproti minulýmu kódu sme si sem přidali podmínku, že davida bude možný posouvat doleva jenom když je jeho pozice
        // věčí než nula (by nám neutek z mapy)
        if ( IsKeyDown ( KEY_LEFT ) && david->pozice.x > 0 && david->aktualni_animace != &david->animace_sed ) {
            
            // nastavíme jeho směr doleva (vicemeně jenom kuli vykreslování animací)
            david->smer = -1;
            
            Rectangle prepozice = david->okraje;
            prepozice.x -= RYCHLOST_CHUZE_DAVIDA * dt;
    
            // kouknem se, jestli nemá prepozice kolizi s některým ze bloků mapy 
            // Jestli jo, tak se nebudem posouvat a přepnem animaci na 'idle'
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
    
                //jestli ale kolizi nemáme, tak Davida normálně šoupnem na prepozici jako sme to ďáli předtim
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->aktualni_animace = &david->animace_beh;
                }
    
            }
        
        // Voproti minule sme si sem přidali podmínku by david nemoch utýct z herní mapy, doprava teďko bude chodit navíc jenom když bude jeho
        // iksová souřadnice menčí než šiřka mapy (- minus šiřka velikosti framu animace, davidova pozice vodpovídá levý horní souřadnici jeho
        // atributu 'okraje', nás zajímá ale pravej vokraj tak to celý musíme šoupnout vo jeho šířku)
        else if ( IsKeyDown ( KEY_RIGHT ) && david->pozice.x < david->mapa->sirka*BLOK_SIRKA - DAVID_F_SIRKA && david->aktualni_animace != &david->animace_sed ) {
    
            david->smer = 1;
            Rectangle prepozice = david->okraje;
            prepozice.x += RYCHLOST_CHUZE_DAVIDA * dt;
            
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->aktualni_animace = & david->animace_beh;
                } 
        }
        // jestli je máčkutej na klávesnici čudlik šipky dolu, tak začnem přehrávat animaci sednutí
        // si na zadek
        else if ( IsKeyDown ( KEY_DOWN ) ) {
    
            // přepnem aktualní animaci....
            david->aktualni_animace = & david->animace_sed;
            
            // ....nastavíme atribut 'reverzně' na 'false' by se nám animace přehrávala normálně,
            // jakože směrem vod začátku ke konci....
            david->aktualni_animace->reverzne = false;
            // ....a vodpauzujem ji, pro případ kdyby byla pauznutá
            david->aktualni_animace->pauznuta = false;
            }
        
        // mačkání tědlech čudliků sme si jakoby zřetězili takovou jakože nudlí if()else if() else...... takže jestli
        // sme se teďko v běhu programu dostali k tomudlectomu kousku kódu, tak neni máčknutej žádnej knoflik.
        // Koukneme se, jestli si David náhodou nesednul na zem nebo jestli si zrovna teďko nesedá nebo z tý země nevstává
        // (to poznáme tim, jestli má jako aktualní animaci nastavenou animaci sedání) noa jestli ne, tak mu přepnem
        // animaci na to akční pérování v kolenou
        else if ( david->aktualni_animace != &david->animace_sed )
        {
            david->aktualni_animace = & david->animace_idle;
        }
    
        // nastavíme vertikální překlopení vykreslování textury podle Davidova atributu 'směr', jakože podle toho, jakým
        // směrem se kouká
        david->aktualni_animace->zrcadlit = david->smer<0;
    
        // pokud je aktuální animace animace sedání a pokud ta animace dojela už na konec (animace sednutí se neloopuje,
        // takže když dojede na konec, tak se sama pauzne) tak se kouknem, na index zobrazovanýho snimku. Pokud to je první
        // snímek animace (index rovnej nule), tak víme, že David už nesedí, ani si nesedá, ani nevstává, ale že už vstal.
        // Takže přepnem animaci na 'idle'
        if ( david->aktualni_animace == &david->animace_sed ) {
            if ( david->animace_sed.pauznuta ) {
                if ( david->animace_sed.index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            }
    
        }
    
        // pokud je aktualní animace běhání, tak se kouknem jestli hraje zvuk kroků noa jestli ne,
        // ho začnem přehrávat 
        else if ( david->aktualni_animace == &david->animace_beh ) {
            if ( !IsSoundPlaying ( zvuk_kroku ) ) {
                PlaySound ( zvuk_kroku );
            }
        }
    
        // nakonec aktualizujem aktuální animaci :D ;D
        aktualizovatAnimaci ( david->aktualni_animace, dt );
    
    }
    
    // funkce na vykreslování Davida
    void vykreslitDavida ( David * david )
    {
        vykreslitAnimaci ( david->aktualni_animace, david->pozice, WHITE );
    
        // jestli je definovanej 'DEBUG', vykreslíme vokraje třeba zelenou barvičkou
    #ifdef DEBUG
        DrawRectangleLines ( david->okraje.x, david->okraje.y, david->okraje.width, david->okraje.height, GREEN );
    #endif
    }
    
    #endif
    

    Noa eště si musíme někde v 'main.c' tu mapu vyrobit a strčit do Davida:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    //šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    
    // zvuky
    Sound zvuk_kroku;
    
    int main ( void )
    {
    
        // nakonfigurujeme si raylib, že budeme chtít vytvořit okno s proměnlivou velikostí a s vertikální synchronizací
        // poznámka pod čarou, ten fígl s bitovým operátorem 'or' jakože se znakem '|' funguje tak, že každá z těch flagovejch
        // konstant má hodotu nastavenou tak, by byl v jejich bytu vobsazenej dycky jenom jeden jedinej bit. Noa když uděláme
        // to bitový or, tak se nám ty proměný zkombinujou do nový unikátní hodnoty kterou ta knihovna umí rozlišit,
        // respektive čte jednotlivý bity v bajtech :O ;D
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        // inicializujeme vokno vo daný šířce, vejšce a s titulkem
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        // inicializujem audio zařízení, by sme mohli přehrávat zvuky
        InitAudioDevice();
    
        // nastavíme požadovanou frekvecni vykreslování
        // takle řikáme, že chceme vykreslovat šedesát snímků za sekundu (framů per sekundu)
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        
        // vyrobíme si instance jednotlivejch animací možnejch davidovejch aktivit
        // animace běhu
    
        // jeden snímek animace nám bude trvat jednu třicetinu sekundy, relativní čas a index vynulujem, zapnem atribut 'jojo' by
        // se nám pak animace po normálním přehrání pouštěla pozpátku, nastavíme atributy 'reverzně' a 'zrcadlit' na false,
        // zapnem loopování, nastavíme texturu a pole jednotlivejch framů ve spritesheetu, počet framů/dylku pole spočitáme podělením velikosti
        // celýho pole velikostí jednoho prvku
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
        // animace sednutí si, puvodně to měla bejt animace chcípnutí jakože si ztoho sedne na zadek :D ale pak mě napadlo že ta hra
        // by mohla bejt víc zajimavější když by se david moch přikrčovat před muslimskou střelbou k zemi
        // pozn. si všimněte že má animace vypnutej loop
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        // alokujeme si dynamický dourozměrný pole který jakože bude mřížka tý naší herní mapy
        // použijem misto mallocu calloc, kterej má tu vyhodu že alokovanou paměť vyplní nulama
        // (alokovanou paměť zase musíme uvolnit)
        
        //šiřk a vejška toho pole (bude schodný s vejškou a šiřkou mapy)
        const int vejska_mapy = 10;
        const int sirka_mapy = 20;
        
        // nejdřiv si alokujeme ukazatele na ukazatele, jakože pole polí (pro nás pole řádků mapy)
        int ** bloky = calloc ( vejska_mapy, sizeof ( int * ) * vejska_mapy );
        // pak jednotlivý řádky mapy
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            bloky[i] = calloc ( sirka_mapy,sizeof ( int ) );
        }
    
        // a spodní vrstvu mapy vyplníme plošinou
        for ( size_t i=0; i<sirka_mapy; i++ )
            bloky[vejska_mapy - 1][i] = 1;
        
        // přidáme si do cesty pár bloků, by sme viděli jak se David zasekává vo překážky
        bloky[vejska_mapy - 2][7] = 1;
        bloky[vejska_mapy - 2][10] = 1;
        bloky[vejska_mapy - 3][10] = 1;
        
        // vyrobíme si herní mapu
        Mapa mapa = {
            
            .textura = textura_kameny,
            .sirka = sirka_mapy,
            .vyska = vejska_mapy,
            .bloky = bloky
            
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // davida postavíme nohama na ty kostky
            // (spočitáme si souřadnici spodní vrstvy a vodečtem vejšku davida
            // (pozice je levej horní roh, my nastavujem spodní stranu))
            .pozice = {0,(vejska_mapy - 1) * 80 - DAVID_F_VYSKA},
                        
    
            .smer = 1,
            
            // strčíme mapu do Davida
            .mapa = &mapa,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
    
            BeginDrawing();
    
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
    
            //vykreslíme mapu
            vykreslitMapu(&mapa,0.0f,9999.0f);
            
            //vykreslíme davida
            vykreslitDavida(&david);
    
            EndDrawing();
        }
    
        CloseWindow();
        
        // musíme uklidit to alokovaný pole 'bloky'
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            free ( bloky[i] );
        }
        free ( bloky );
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
    
        return 0;
    }
    

    Když zkompilujeme a pustíme by sme měli vidět takovýdleho něco


    Krok šest: Skákání a padání 🦘

    Dali sme si do cesty kameny vo který se David zasekává a nedá se jít dál 😮 🙄 Nóó takže Davida musíme naučit skákat 😮 😜 A taky mu dát ňákou aspoň primitivní fyziku by z kostek moch padat dolu a choval se v tom dlaždicovým svěťě ňák víc přirozenějc 😁 😜

    Upravíme soubor 'david.h' do týdle podoby:

    #ifndef _DAVID_A_DUCHOVE_DAVID_H_
    #define _DAVID_A_DUCHOVE_DAVID_H_
    
    // naimportujem si animaci
    // (s ní se nám současně natáhne raylib.h)
    #include "animace.h"
    #include "mapa.h"
    
    // kouzelným slovíčkem 'extern' https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
    // mužeme 'sdílet' se souborem 'main.c' v něm deklarovaný proměný, teďko na ukázku zatim jenom
    // zvuk chůze, de ale všecko :O ;D 
    extern Sound zvuk_kroku;
    extern Sound zvuk_skoku;
    
    // přestěhujem si sem z 'main.c' framy animace by to tam zbytečně nezabiralo misto ve zdrojáčku 
    #define DAVID_F_SIRKA 150.0f
    #define DAVID_F_VYSKA 240.0f
    
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    
    
    };
    
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    #define RYCHLOST_CHUZE_DAVIDA 350.0f
    
    //máme tady dvě další hodnoty, rychlost skoku a gravitaci
    #define RYCHLOST_SKOKU_DAVIDA -15.0f
    #define GRAVITACE_DAVIDA 40.0f
    
    typedef struct David {
        
        // jednotlivý animace davida
        Animace animace_beh;
        Animace animace_idle;
        Animace animace_sed;
        Animace animace_skok;
    
        Animace * aktualni_animace;
    
    
        Vector2 pozice;
        
        Rectangle okraje;
        
        int smer;
        
        Mapa * mapa;
        
        // david bude mit dva nový atributy:
        // boolean jestli skáče a vertikální rychlost kterou se jakoby pohybuje
        bool zdaSkace;
        float vertikalni_rychlost;
    
    } David;
    
    
    void aktualizovatDavida ( David * david, float dt )
    {
    
        // čudlikem šipky nahroru jsme zatim jenom zvedali Davida ze země, teďko mu přidáme eště jednu funkci a to
        // že jim david bude skákat (pokud nesedí a nesedá si nebo nevstává)
        if ( IsKeyDown ( KEY_UP ) ) {
    
            if ( david->aktualni_animace == &david->animace_sed ) {
                david->aktualni_animace->pauznuta = false;
                david->aktualni_animace->reverzne=true;
    
                if ( david->aktualni_animace->index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            // pokud je zmáčknutá šipka nahoru a animace není animace sedání,
            // tak se kouknem jestli David už neskáče, a jestli ne, tak zapnem zvuk skoku,
            // nastavíme atrimut skákání, resetujem skákací animaci na index 0 a nastavíme vertikální rychlost na max
            // (aktuální animaci přepnem kousek dál v upraveným kódu)
            } else if ( !david->zdaSkace ) {
                PlaySound ( zvuk_skoku );
                david->zdaSkace = true;
                david->animace_skok.index = 0;
                david->vertikalni_rychlost = RYCHLOST_SKOKU_DAVIDA;
            }
        }
    
    
        
        if ( IsKeyDown ( KEY_LEFT ) && david->pozice.x > 0 && david->aktualni_animace != &david->animace_sed ) {
            
            david->smer = -1;
            
            Rectangle prepozice = david->okraje;
            prepozice.x -= RYCHLOST_CHUZE_DAVIDA * dt;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
    
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->aktualni_animace = &david->animace_beh;
                }
    
            }
        
        else if ( IsKeyDown ( KEY_RIGHT ) && david->pozice.x < david->mapa->sirka*BLOK_SIRKA - DAVID_F_SIRKA && david->aktualni_animace != &david->animace_sed ) {
    
            david->smer = 1;
            Rectangle prepozice = david->okraje;
            prepozice.x += RYCHLOST_CHUZE_DAVIDA * dt;
            
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->aktualni_animace = & david->animace_beh;
                } 
        }
        // jestli je máčkutej na klávesnici čudlik šipky dolu, tak začnem přehrávat animaci sednutí
        // si na zadek
        else if ( IsKeyDown ( KEY_DOWN ) ) {
    
            david->aktualni_animace = & david->animace_sed;
            david->aktualni_animace->reverzne = false;
            david->aktualni_animace->pauznuta = false;
            }
            
        else if ( david->aktualni_animace != &david->animace_sed ) {
            david->aktualni_animace = & david->animace_idle;
            }
            
        // kouknem jestli má david pod nohama pevnou zem
        // vyrobíme si kopii okrajů/boundingboxu a postrčíme ji o 5 pixelů dolu
        // pokud okraje/boundingbox nebude mit kolizi s pevnejma kostkama herní mapy,
        // tak davidoj zapnem skákací atribut, ale nedáme mu žádnou rychlost,
        // tzn. necháme ho padat volným pádem dolu s počateční vertikální rychlostí nula
        // (rychlost nastavujem na nulu dycky když se David nohama dotkne země takže by už rychlost
        // na nulu měla bejt nastavená z jinýho kousku kodu)
        Rectangle prepozice = david->okraje;
        prepozice.y += 5;
        if ( ! kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
            david->zdaSkace = true;
        }
    
        // kouknem jestli David má nastavenej atribut skákání na true. Pokud jakože jo,
        // tak mu budem aktualizovat polohu podle tý jeho vertikální rychlosti.
        if ( david->zdaSkace ) {
    
            // aktualizujem si Davidovu vertikální rychlost
            // (pomalinku ji táhnem gravitací směrem dolu k zemi)
            david->vertikalni_rychlost += dt * GRAVITACE_DAVIDA;
            
            // uplně stejně jako při chození do stran si spočitáme jeho prepozici, jakože jeho
            // vokraje posunutý vo vertikální rychlost směrem dolu
            Rectangle prepozice = david->okraje;
            prepozice.y += david->vertikalni_rychlost;
    
            // noa kouknem, jestli by posunem na tu prepozici došlo ke kontaktu s mapou
            // (posouváme jenom po ose ypsilon, bočniho narazu do kostek mapy se jakoby nemusíme bát)
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                
                // pokud by mělo příštím krokem dojit k tomu kontaktu Davida s mapou, tak si to budem počitat jako že
                // nám David už spadnul na zem. Takže mu vynulujem vertikální rychlost a nastavíme atribut skákání 'zdaSkace' na false
                david->vertikalni_rychlost = 0.0f;
                david->zdaSkace = false;
    
                // jenže David nám furt visí ve vzduchu, a když ho posunem  vo vetikální rychlost, tak ho zase zanoříme do dlaždicový mapy :O :O
                // takže si spočitáme vertikální polohu spodního vokraje Davida (okraje.y + vejška), přepočitáme ho na souřadnici dlažidový mapy
                // ( ceil(y/BLOK_VYSKA) a tu zpátky pronásobíme vejškou bloku, takže sme získali souřadnici zarovnanou na kostku mapy
                // teďko vod toho eště musíme vodečíst vejšku Davida, páč Davidova poloha je jeho levej horní roh ( A eště vodečtem ňákou mrňavou
                // hodnotu, páč by byl jinak těsně zanořenej ve hraně mapy)
                david->okraje.y =  ceil ( ( david->okraje.y + david->okraje.height  ) / BLOK_VYSKA ) * BLOK_VYSKA - david->okraje.height - 1;
    
                // pokud je díky mačkutí šipky doprava nebo doleva náhodou nastavená jako aktuální animace běhání,
                // tak využijem toho že sme animaci skoku vyrobili z podmnožiny framů animace běhu a nastavíme běhací animaci jako
                // právě teď zobrazenej snímek (index) vodpovídající snimek animace skoku, současně nastavíme stejnej směr přehrávání, jakože
                // jestli přehráváme reverzně nebo ne. Tim si myslim že dosáhneme trošičku lepší navaznosti animací na sebe a budou jakoby mezi sebou
                // krásně plynule přecházet. Uvidime :D
                if ( david->aktualni_animace == &david->animace_beh ) {
                    david->aktualni_animace->index = david->animace_skok.index +5;
                    david->aktualni_animace->reverzne = david->animace_skok.reverzne;
                }
    
            } else {
                
                // pokud se padací/skákací prepozice neprotne s dlaždicovou mapou, tzn. David eště nedopadne na zem,
                // tak mu nastavíme aktualní animaci na animaci skákání (pro případ kdyby ji hráč mačkáním šipek přepnul na běch)
                david->aktualni_animace = & david->animace_skok;
                
                // a posunem okraje na spočitanou prepozici
                david->okraje.y += david->vertikalni_rychlost;
    
            }
            
            // aktualizujem davidovu pozici podle aktuální pozice vokrajů
            // (trošku sem tu polohu upravila, vektor 'pozice' určuje polohu vykreslování textury Davida,
            // šoupla sem ji vo pár čísel dolu, by David neplandal nohama vevzduchu nad mapou. Vypočty kolizí a relálný polohy stejně
            // věčinou ve zdrojáčku děláme pomocí toho rectanglu 'okraje', tady de spíš jakože vo tu estetiku nebo co :D)
            david->pozice.y = david->okraje.y - 3;
            
    
        }
    
        david->aktualni_animace->zrcadlit = david->smer<0;
    
    
        if ( david->aktualni_animace == &david->animace_sed ) {
            if ( david->animace_sed.pauznuta ) {
                if ( david->animace_sed.index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            }
    
        }
    
        // pokud je aktualní animace běhání, tak se kouknem jestli hraje zvuk kroků noa jestli ne,
        // ho začnem přehrávat 
        else if ( david->aktualni_animace == &david->animace_beh ) {
            if ( !IsSoundPlaying ( zvuk_kroku ) ) {
                PlaySound ( zvuk_kroku );
            }
        }
        
        // pokud je aktualní animace skákání a pokud hraje zvuk kroků, tak ten zvuk vypnem
        if ( david->aktualni_animace == &david->animace_skok && IsSoundPlaying ( zvuk_kroku ) ) {
            StopSound ( zvuk_kroku );
        }
    
        // nakonec aktualizujem aktuální animaci :D ;D
        aktualizovatAnimaci ( david->aktualni_animace, dt );
    
    }
    
    // funkce na vykreslování Davida
    void vykreslitDavida ( David * david )
    {
        vykreslitAnimaci ( david->aktualni_animace, david->pozice, WHITE );
    
        // jestli je definovanej 'DEBUG', vykreslíme vokraje třeba zelenou barvičkou
    #ifdef DEBUG
        DrawRectangleLines ( david->okraje.x, david->okraje.y, david->okraje.width, david->okraje.height, GREEN );
    #endif
    }
    
    #endif
    

    A upravíme si i 'main.c', by sme si tam načetli zvuk skákání a nastavili Davidoj nový atributy:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    //šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    
    int main ( void )
    {
    
        // nakonfigurujeme si raylib, že budeme chtít vytvořit okno s proměnlivou velikostí a s vertikální synchronizací
        // poznámka pod čarou, ten fígl s bitovým operátorem 'or' jakože se znakem '|' funguje tak, že každá z těch flagovejch
        // konstant má hodotu nastavenou tak, by byl v jejich bytu vobsazenej dycky jenom jeden jedinej bit. Noa když uděláme
        // to bitový or, tak se nám ty proměný zkombinujou do nový unikátní hodnoty kterou ta knihovna umí rozlišit,
        // respektive čte jednotlivý bity v bajtech :O ;D
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        // inicializujeme vokno vo daný šířce, vejšce a s titulkem
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        // inicializujem audio zařízení, by sme mohli přehrávat zvuky
        InitAudioDevice();
    
        // nastavíme požadovanou frekvecni vykreslování
        // takle řikáme, že chceme vykreslovat šedesát snímků za sekundu (framů per sekundu)
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        
        // vyrobíme si instance jednotlivejch animací možnejch davidovejch aktivit
        // animace běhu
    
        // jeden snímek animace nám bude trvat jednu třicetinu sekundy, relativní čas a index vynulujem, zapnem atribut 'jojo' by
        // se nám pak animace po normálním přehrání pouštěla pozpátku, nastavíme atributy 'reverzně' a 'zrcadlit' na false,
        // zapnem loopování, nastavíme texturu a pole jednotlivejch framů ve spritesheetu, počet framů/dylku pole spočitáme podělením velikosti
        // celýho pole velikostí jednoho prvku
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
        // animace sednutí si, puvodně to měla bejt animace chcípnutí jakože si ztoho sedne na zadek :D ale pak mě napadlo že ta hra
        // by mohla bejt víc zajimavější když by se david moch přikrčovat před muslimskou střelbou k zemi
        // pozn. si všimněte že má animace vypnutej loop
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        // alokujeme si dynamický dourozměrný pole který jakože bude mřížka tý naší herní mapy
        // použijem mito mallocu calloc, kterej má tu vyhodu že alokovanou paměť vyplní nulama
        // (alokovanou paměť zase musíme uvolnit)
        const int vejska_mapy = 10;
        const int sirka_mapy = 20;
        int ** bloky = calloc ( vejska_mapy, sizeof ( int * ) * vejska_mapy );
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            bloky[i] = calloc ( sirka_mapy,sizeof ( int ) );
        }
    
        // a spodní vrstvu mapy vyplníme plošinou
        for ( size_t i=0; i<sirka_mapy; i++ )
            bloky[vejska_mapy - 1][i] = 1;
        
        // přidáme si do cesty pár bloků, by sme viděli jak se David zasekává vo překážky
        bloky[vejska_mapy - 2][7] = 1;
        bloky[vejska_mapy - 2][10] = 1;
        bloky[vejska_mapy - 3][10] = 1;
        
        // vyrobíme si herní mapu
        Mapa mapa = {
            
            .textura = textura_kameny,
            .sirka = sirka_mapy,
            .vyska = vejska_mapy,
            .bloky = bloky
            
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // strčíme mapu do Davida
            .mapa = &mapa,
            
            // nastavíme vertikální rychost na nulu a to zda skáče na true
            // (ikdyž to zda skáče by se asi jako stejně přeplo samo hnedka :D)
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
    
            BeginDrawing();
    
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
    
            //vykreslíme mapu
            vykreslitMapu(&mapa,0.0f,9999.0f);
            
            //vykreslíme davida
            vykreslitDavida(&david);
    
            EndDrawing();
        }
    
        CloseWindow();
        
        // musíme uklidit to alokovaný pole 'bloky'
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            free ( bloky[i] );
        }
        free ( bloky );
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
    
        return 0;
    }
    


    Krok sedum: kamera 🎥

    Když si ale jakoby zkusíme dojít s Davidem na pravej konec mapy tak se stane vošklivá věc, David nám uplně normálně uteče z vobrazovky někam pryč 😮 😮

    Naštěstí Raylib nám umožňuje rendrování pomocí kamery. Představte si, že ten náš herní svět máme namalovanej na takový velikatatatáncký čtvrtce papíru nalepený někde na zdi, noa po tý čtvrtce nám běhá tamta 2D postavička krále Davida. A teďko si eště přectavte, že před tou čtvrtkou stojí fotograf David Ježek (pozor, nebezpečí zaměny Davidů 😁 😁) s ňákým tim svým foťákem na fotomodulky (jakože s kamerou) nebo cože to bylo a snaží se pohyb tý 2d figurky na ten svuj foťák nějak jakože nahrávat na videjko. Noa jak to jakoby ten Ježek bude dělat: nejdřiv si nastaví na foťáku nějaký přiblížení/zoom, by byla na tom jeho videjku postavička vidět v ňáký rozumný velikosti. A když se bude postavička po čtvrtce pohybovat, tak se Ježek bude snažit by byl jeho foťák furt kolmo namířenej na tu 2d figurku, takže poběží i s tim svým foťákem podél tý čtvrtky a bude furt mířit na střed tý běhajicí figurky 😮 😜

    Uplně to samý uděláme my, deklarujeme si nějakou kameru, budem ji nastavovat nějaký rozumný zazoomování/přiblížení a budem ji furt zaměřovat někam na střed krále Davida. Noa co jakoby tou kamerou uvidíme se prostě bude zobrazovat na vobrazovce 😮 😜 (pod kapotou má raylib na 100% ty starý známý fígle s maticovovým počitáním, je to před náma tou kamerou skovaný takže to vubec nemusíme řešit. Fajnšmekři si ale jako mužou vygooglit tisic ruznejch povidání a tutoriálů vokolo wolrd/view/model/etc matic hele třeba)

    Takže si takle upravíme 'main.c', by sme si tam tu kameru přidali:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    //šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    //kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 50
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    
    int main ( void )
    {
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        
        // inicializujeme si strukturu kamery
        // (vlastně kromě rotace nemusíme vyplňovat atributy
        // vono si je to bude aktuallizovat každým loopem)
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
    
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
    
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
    
            //přiblížení
            .zoom = 1.0f
        };
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        const int vejska_mapy = 10;
        const int sirka_mapy = DELKA_LEVELU_BLOKU;
        int ** bloky = calloc ( vejska_mapy, sizeof ( int * ) * vejska_mapy );
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            bloky[i] = calloc ( sirka_mapy,sizeof ( int ) );
        }
    
        // a spodní vrstvu mapy vyplníme plošinou
        for ( size_t i=0; i<sirka_mapy; i++ )
            bloky[vejska_mapy - 1][i] = 1;
        
        // přidáme si do cesty pár bloků, by sme viděli jak se David zasekává vo překážky
        bloky[vejska_mapy - 2][7] = 1;
        bloky[vejska_mapy - 2][10] = 1;
        bloky[vejska_mapy - 3][10] = 1;
        
        // vyrobíme si herní mapu
        Mapa mapa = {
            
            .textura = textura_kameny,
            .sirka = sirka_mapy,
            .vyska = vejska_mapy,
            .bloky = bloky
            
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // strčíme mapu do Davida
            .mapa = &mapa,
            
            // nastavíme vertikální rychost na nulu a to zda skáče na true
            // (ikdyž to zda skáče by se asi jako stejně přeplo samo hnedka :D)
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            //určíme si meze, ve kterejch se kamera muže pohybovat
            
            // minimální iksová souřadnice je polovina šířky vobrazovky (takže když se david bude přibližovat
            // levýmu vokraji mapy, přestanem ho kamerou sledovat by sme nevykoukli mimo voblast tý dlaždicový mapy),
            // maximální dýlka levelu v počtu bloků minus zase půlka vobrazovky (ze stejnejch duvodů jen pro druhej vokraj)
            // maximální ypsilon (roste nám směrem zezhora dolu, horní vokraj obrazovky má nulu) je
            // půlka vejšky vobrazovky + půlka vejšky davida + vejška pár bloků navíc, by hráč nemusel mit voči moc sklopený k dolnímu vokraji
            // vobrazovky (zpomináte si jak sme si vykreslovali v souboru 'mapa.h' těch pár kostek navíc?? teďko se šiknou. Posun kamery mi
            // přišel nejhežčí dokonce vo vejšku pěti bloků, nejenom tří jak to tam máme v hlavičce 'mapa.h' napsaný. Necháme soubor mapa.h jak je,
            // už mam vymyšlený jak to celý zavonačíme by spodek tý mapy byl pěknej a nemuseli sme si rendrovat zbytečně moc kostek :O ;D)
            
            // (hodnoty transformujem do rozměrů kamerózního světa podělením ňákýho toho rozměru nebo
            // souřadnice spočitanou hodnotou proměný 'přiblížení')
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme mapu
            vykreslitMapu(&mapa,0.0f,9999.0f);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            // a teďko příde to slíbený zavonačení :D :D 
            // nakreslíme na spodku mapy čtverec s černým gradientem, takže to bude vypadat že se nám spodek mapy
            // jakože noří do ňákýho stínu nebo čeho
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // musíme uklidit to alokovaný pole 'bloky'
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            free ( bloky[i] );
        }
        free ( bloky );
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
    
        return 0;
    }
    


    Krok vosum: střílení 🔫

    Sme si řekli že to má bejt jakože akční hra, navíc má David v ruce ňákou takovou pistolku takže asi jako musíme dodržet Čechovovovovo pravidlo hele takže Davidova pistolka musí střílet 😁 😜

    Že projektily budou takový herní voběkty který maj ňákou rychlost a budou se posouvat po mapě a když narazej do ňáký pevný překážky tak se zničej, to je jasný. My ale abysme nemuseli furt alokovat a uvolňovat paměť, kdyby sme si třeba struktury projektilů furt dynamicky vytvářeli a při zničení z paměti mazali, tak si alokujeme celej zásobník Davidovejch střel a jednou použitý projektily budem znova recyklovat. Hráč si ničeho nevšimne páč to bude vypadat uplně stejně jako by furt znikaly ňáký nový projektily, ale to bude jenom takovej trik, veskutečnosti budem furt točit dokolečka ty samý struktury 😮 😜

    takže si ve složšce 'src' vyrobíme novej soubor 'projektily.h' a dáme tam takovejdle vobsach:

    #ifndef _DAVID_A_DUCHOVE_PROJEKTILY_H_
    #define _DAVID_A_DUCHOVE_PROJEKTILY_H_
    
    #include <raylib.h>
    
    #include "mapa.h"
    
    // druh střely
    // stejnou strukturu budem využívat pozdějc i u duchů, zatim máme jenom jedinej možnej druch
    enum druh_strely {strela_davida};
    
    typedef struct Strela {
        
        // rychlost střely
        float rychlost;
        
        // relativní čas střely
        float relativni_cas;
        
        // nastavená maximální doba života střely
        // když relativní čas překročí tudle hodnotu tak střelu deaktivujem a budem považovat za zničenou
        float doba_zivota;
        enum druh_strely druh;
        
        // pozice střely
        Vector2 pozice;
        
        // zda je střela aktivní
        // pokud aktivní neni považujem ji za zničenou a/nebo nevystřelenou, takovou střelu nebudeme
        // vykreslovat ani aktualizovat
        bool aktivni;
    }
    Strela;
    
    void aktualizovatStrelu ( Strela * strela, Mapa * mapa, float dt )
    {
        strela->relativni_cas += dt;
        if ( strela->relativni_cas > strela->doba_zivota ) {
            strela->aktivni = false;
        } else {
            strela->pozice.x += dt * strela->rychlost;
            
            // pokud dojde ke srážce střely s blokem mapy, tak střelu deaktivujem
            if ( kolizeSeBlokemMapy_bod ( strela->pozice, mapa ) ) {
                strela->aktivni = false;
            }
        }
    }
    
    void vykreslitStrelu ( Strela * strela )
    {
        if ( !strela->aktivni ) {
            return;
        }
        // zatim budem vykreslovat jenom Davidovy střely,
        // budou to takový jakoby softwérový kuličky s bílošedivým gradientem
        switch ( strela->druh ) {
        case strela_davida:
            DrawCircleGradient ( strela->pozice.x,strela->pozice.y,5.0f,WHITE,DARKGRAY );
            break;
        default:
            break;
        }
    }
    
    #endif
    

    Upravíme si kód Davida v hlavičkovým souboru 'david.h', přidáme mu tam střílení mezernikem a aktualizaci a vykreslování střel:

    #ifndef _DAVID_A_DUCHOVE_DAVID_H_
    #define _DAVID_A_DUCHOVE_DAVID_H_
    
    // naimportujem si animaci
    // (s ní se nám současně natáhne raylib.h)
    #include "animace.h"
    #include "mapa.h"
    #include "projektily.h"
    
    extern Sound zvuk_kroku;
    extern Sound zvuk_skoku;
    extern Sound zvuk_vystrel;
    
    // přestěhujem si sem z 'main.c' framy animace by to tam zbytečně nezabiralo misto ve zdrojáčku 
    #define DAVID_F_SIRKA 150.0f
    #define DAVID_F_VYSKA 240.0f
    
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    
    
    };
    
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    #define RYCHLOST_CHUZE_DAVIDA 350.0f
    #define RYCHLOST_SKOKU_DAVIDA -15.0f
    #define GRAVITACE_DAVIDA 40.0f
    
    //přidáme si další tři hodnoty
    // 1. rychlost davidovejch střel
    #define RYCHLOST_STREL_DAVIDA 800.0f
    
    // 2. dobu čekání mezi jednotlivejma výstřelama (čtvrt sekundy)
    #define STRILECI_COOLDOWN_DAVIDA 0.25f
    
    // 3. maximální počet střel, jakože max velikost zasobniku
    #define POCET_STREL_DAVIDA_MAX 32
    
    typedef struct David {
        
        // jednotlivý animace davida
        Animace animace_beh;
        Animace animace_idle;
        Animace animace_sed;
        Animace animace_skok;
    
        Animace * aktualni_animace;
    
    
        Vector2 pozice;
        
        Rectangle okraje;
        
        int smer;
        
        Mapa * mapa;
    
        bool zdaSkace;
        float vertikalni_rychlost;
        
        // zásobník střel, bude to ukazatel na 'pole' střel
        Strela * strely;
        // zbejvajicí čas do dalšího výstřelu
        float strileci_cooldown;
    
    } David;
    
    
    void aktualizovatDavida ( David * david, float dt )
    {
    
        if ( IsKeyDown ( KEY_UP ) ) {
    
            if ( david->aktualni_animace == &david->animace_sed ) {
                david->aktualni_animace->pauznuta = false;
                david->aktualni_animace->reverzne=true;
    
                if ( david->aktualni_animace->index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
    
            } else if ( !david->zdaSkace ) {
                PlaySound ( zvuk_skoku );
                david->zdaSkace = true;
                david->animace_skok.index = 0;
                david->vertikalni_rychlost = RYCHLOST_SKOKU_DAVIDA;
            }
        }
        
        // když hráč zmáčkne mezernik, tak se David pokusí vystřelit z tý svý pistolky
        if ( IsKeyDown ( KEY_SPACE ) ) {
            // vystřelit mužeme jenom když uplynula čekací doba mezi výstřelama resp. střílecí cooldown je menší nebo rovnej nule
            if ( david->strileci_cooldown <= 0.0f ) {
                // projdeme si celej davidův zásobník a pokusíme se v něm najít střelu, kterou budeme moct použít
                // to poznáme tak, že bude mit atribut aktivní nastavenej na nulu
                for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
                    if ( !david->strely[i].aktivni ) {
                        
                        // pokud sme takovou střelu našli, tak si vybereme pro upravování atributů
                        Strela * s = david->strely + i;
    
                        // nejdřiv ji nastavíme novou polohu,
                        //to znamená přibližně někam na konec hlavně tý pistolky co má david v rukou
                        
                        //nj jenže david muže stát, sedět na zemi, muže koukat z prava doleva, nebo muže dokonce právě vstávat ze země
                        // všecky tydlecty eventualitky jakoby musíme pokrejt
                        if ( david->aktualni_animace != &david->animace_sed )
                            s->pozice = ( Vector2 ) {
                            // střelu umisťujem podle toho jakým směrem david kouká
                            david->smer==1? david->pozice.x+DAVID_F_SIRKA - 25: david->pozice.x+25,
                            david->pozice.y + DAVID_F_VYSKA/2 - 36
                        };
                        else {
                            // pokud david má jako aktuální animaci sedání, tak si zistíme index a vo ten budeme posouvat iksovou a ypsilonovou
                            // souřadnici střely. Neni to uplně přesný ale na to nikdo koukat nebude :D
                            int index = david->animace_sed.index;
                            s->pozice = ( Vector2 ) {
                                david->smer==1? david->pozice.x+DAVID_F_SIRKA - 25 - index*5: david->pozice.x+25 + index*5,david->pozice.y + DAVID_F_VYSKA/2 - 26 - 8 + index*14
                            };
    
                        }
                        
                        //polohu máme, teďko nastavíme další atributy střely
                        
                        // nastavíme střele rychlost, zohledníme i směr kterým poletí, ten vodpovídá
                        // směru kterým David právě teďko kouká
                        s->rychlost = RYCHLOST_STREL_DAVIDA * ( float ) david->smer;
                        
                        // vynulujem relativní čas
                        s->relativni_cas = 0.0f;
                        
                        // nastavíme dobu života třeba na čtyry vteřiny
                        s->doba_zivota = 4.0f;
                        
                        // a aktivujem
                        s->aktivni=true;
                        
                        // střelu máme upravenou, ukazatel už nepotřebujem
                        s=0;
    
                        // ..a když sme aktivovali střelu, tak sme vlastně vystřelili, takže nastavíme střílecí čekací dobu
                        // na maximální hodnotu
                        david->strileci_cooldown = STRILECI_COOLDOWN_DAVIDA;
                        
                        // zahrajem zvuk výstřelu
                        PlaySound ( zvuk_vystrel );
                        
                        // a přerušíme hledací for cyklus
                        break;
                    }
                }
            }
            // eště upravíme aktuální animaci, pokud to neni animace sedání, tak přepnem animaci na idle na první snímek,
            // páč při tý animaci david hejbe pistolkou a vypadalo by to divně kdyby z ní vylítla vodorovně střela. Pokud david skáče,
            // běží nebo padá, tak se nám ta animace stejně přepne někde dál tady ve zdrojáčku týdle funkce
            // (při animaci běhu/skoků todle nepřectavuje problém, pistolka je na všech vobrázcích spritesheetu ve stejný vejšce,
            // kromě tý animace 'idle', tam je ve stejný vejšce právě jenom na prvním snimku)
            if ( david->aktualni_animace != &david->animace_sed ) {
                david->aktualni_animace = & david->animace_idle;
                david->aktualni_animace->index = 0;
                david->aktualni_animace->relativni_cas = 0.0f;
            }
        }
    
    
        
        if ( IsKeyDown ( KEY_LEFT ) && david->pozice.x > 0 && david->aktualni_animace != &david->animace_sed ) {
            
            david->smer = -1;
            
            Rectangle prepozice = david->okraje;
            prepozice.x -= RYCHLOST_CHUZE_DAVIDA * dt;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
    
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->aktualni_animace = &david->animace_beh;
                }
    
            }
        
        else if ( IsKeyDown ( KEY_RIGHT ) && david->pozice.x < david->mapa->sirka*BLOK_SIRKA - DAVID_F_SIRKA && david->aktualni_animace != &david->animace_sed ) {
    
            david->smer = 1;
            Rectangle prepozice = david->okraje;
            prepozice.x += RYCHLOST_CHUZE_DAVIDA * dt;
            
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->aktualni_animace = & david->animace_beh;
                } 
        }
        // jestli je máčkutej na klávesnici čudlik šipky dolu, tak začnem přehrávat animaci sednutí
        // si na zadek
        else if ( IsKeyDown ( KEY_DOWN ) ) {
    
            david->aktualni_animace = & david->animace_sed;
            david->aktualni_animace->reverzne = false;
            david->aktualni_animace->pauznuta = false;
            }
            
        else if ( david->aktualni_animace != &david->animace_sed ) {
            david->aktualni_animace = & david->animace_idle;
            }
            
        Rectangle prepozice = david->okraje;
        prepozice.y += 5;
        if ( ! kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
            david->zdaSkace = true;
        }
    
        if ( david->zdaSkace ) {
    
            david->vertikalni_rychlost += dt * GRAVITACE_DAVIDA;
            
            Rectangle prepozice = david->okraje;
            prepozice.y += david->vertikalni_rychlost;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                
                david->vertikalni_rychlost = 0.0f;
                david->zdaSkace = false;
    
                david->okraje.y =  ceil ( ( david->okraje.y + david->okraje.height  ) /BLOK_VYSKA ) * BLOK_VYSKA - david->okraje.height - 1;
    
                if ( david->aktualni_animace == &david->animace_beh ) {
                    david->aktualni_animace->index = david->animace_skok.index +5;
                    david->aktualni_animace->reverzne = david->animace_skok.reverzne;
                }
    
            } else {
                
                david->aktualni_animace = & david->animace_skok;
                
                david->okraje.y += david->vertikalni_rychlost;
    
            }
    
            david->pozice.y = david->okraje.y - 3;
            
    
        }
    
        david->aktualni_animace->zrcadlit = david->smer<0;
    
    
        if ( david->aktualni_animace == &david->animace_sed ) {
            if ( david->animace_sed.pauznuta ) {
                if ( david->animace_sed.index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            }
    
        }
    
        else if ( david->aktualni_animace == &david->animace_beh ) {
            if ( !IsSoundPlaying ( zvuk_kroku ) ) {
                PlaySound ( zvuk_kroku );
            }
        }
        
        if ( david->aktualni_animace == &david->animace_skok && IsSoundPlaying ( zvuk_kroku ) ) {
            StopSound ( zvuk_kroku );
        }
        
        // odečteme časovou deltu vod zbejvajicí čekací doby mezi výstřelama
        if ( david->strileci_cooldown > 0.0f ) {
            david->strileci_cooldown -= dt;
        }
        
        // a aktualizujem si celej davidův zasobnik
        for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
            aktualizovatStrelu ( david->strely+i, david->mapa,dt );
        }
    
        // nakonec aktualizujem aktuální animaci :D ;D
        aktualizovatAnimaci ( david->aktualni_animace, dt );
    
    }
    
    // funkce na vykreslování Davida
    void vykreslitDavida ( David * david )
    {
        vykreslitAnimaci ( david->aktualni_animace, david->pozice, WHITE );
        
        // vykreslíme střely
        for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
            vykreslitStrelu ( david->strely+i );
        }
    
        // jestli je definovanej 'DEBUG', vykreslíme vokraje třeba zelenou barvičkou
    #ifdef DEBUG
        DrawRectangleLines ( david->okraje.x, david->okraje.y, david->okraje.width, david->okraje.height, GREEN );
    #endif
    }
    
    #endif
    

    Noa eště musíme upravit 'main.c', by sme si tam vyrobili ten zásobnik Davidovejch střel a přidali zvuk střílení

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 50
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    
    int main ( void )
    {
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        const int vejska_mapy = 10;
        const int sirka_mapy = DELKA_LEVELU_BLOKU;
        int ** bloky = calloc ( vejska_mapy, sizeof ( int * ) * vejska_mapy );
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            bloky[i] = calloc ( sirka_mapy,sizeof ( int ) );
        }
    
        // a spodní vrstvu mapy vyplníme plošinou
        for ( size_t i=0; i<sirka_mapy; i++ )
            bloky[vejska_mapy - 1][i] = 1;
        
        // přidáme si do cesty pár bloků, by sme viděli jak se David zasekává vo překážky
        bloky[vejska_mapy - 2][7] = 1;
        bloky[vejska_mapy - 2][10] = 1;
        bloky[vejska_mapy - 3][10] = 1;
        
        // vyrobíme si herní mapu
        Mapa mapa = {
            
            .textura = textura_kameny,
            .sirka = sirka_mapy,
            .vyska = vejska_mapy,
            .bloky = bloky
            
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            .mapa = &mapa,
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidův vnitřní časovač střílecího cooldownu 
            .strileci_cooldown = 0.0f,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            //určíme si meze, ve kterejch se kamera muže pohybovat
            
            // minimální iksová souřadnice je polovina šířky vobrazovky (takže když se david bude přibližovat
            // levýmu vokraji mapy, přestanem ho kamerou sledovat by sme nevykoukli mimo voblast tý dlaždicový mapy),
            // maximální dýlka levelu v počtu bloků minus zase půlka vobrazovky (ze stejnejch duvodů jen pro druhej vokraj)
            // maximální ypsilon (roste nám směrem zezhora dolu, horní vokraj obrazovky má nulu) je
            // půlka vejšky vobrazovky + půlka vejšky davida + vejška pár bloků navíc, by hráč nemusel mit voči moc sklopený k dolnímu vokraji
            // vobrazovky (zpomináte si jak sme si vykreslovali v souboru 'mapa.h' těch pár kostek navíc?? teďko se šiknou. Posun kamery mi
            // přišel nejhežčí dokonce vo vejšku pěti bloků, nejenom tří jak to tam máme v hlavičce 'mapa.h' napsaný. Necháme soubor mapa.h jak je,
            // už mam vymyšlený jak to celý zavonačíme by spodek tý mapy byl pěknej a nemuseli sme si rendrovat zbytečně moc kostek :O ;D)
            
            // (hodnoty transformujem do rozměrů kamerózního světa podělením ňákýho toho rozměru nebo
            // souřadnice spočitanou hodnotou proměný 'přiblížení')
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme mapu
            vykreslitMapu(&mapa,0.0f,9999.0f);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            // a teďko příde to slíbený zavonačení :D :D 
            // nakreslíme na spodku mapy čtverec s černým gradientem, takže to bude vypadat že se nám spodek mapy
            // jakože noří do ňákýho stínu nebo čeho
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // musíme uklidit to alokovaný pole 'bloky'
        for ( size_t i=0; i<vejska_mapy; i++ ) {
            free ( bloky[i] );
        }
        free ( bloky );
        
        // uvolníme pole střel
        if ( david_strely ) {
            free ( david_strely );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
    
        return 0;
    }
    


    Krok devět: level s náhodnou mapou 🗺️

    Vytvoříme si strukturu herního levelu, která bude řešit celej herní svět a Davidovu interakci s nim. Zatim tam budeme mít jenom to generování pseudonáhodný mapy ale v příštích krocích si tam budeme přidávat duchy, bonusy a možná ňáký další jiný herní voběkty (to generování mapy je spíš dočasný řešení by sme si tu hru vyzkoušeli, jestli se vám tendlecten duchobijeckej blogísek bude líbit tak si spíš v ňákým možným pokračování ukažeme supr editor dlaždicovejch světů tiled)

    Takže si vyrobíme v tý zdrojáčkový složce 'src' novej soubor 'level.h' a nacpem tam todle:

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    
    // maximální vejška mapy (hodnota je v počtu kostek dlaždicový mapy)
    #define MAPA_MAX_VYSKA 10
    
    // struktura levelu
    // zatim tam máme jenom tu mapu
    typedef struct Level {
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    // pomocná struktura pro generování mapy
    // pude popisovat dílčí kousek ze kterejch budeme skládat tu svou náhodnou mapu
    // bude to vlastně takový jakoby dvourozměrný pole
    // (je to nadefinovaný jako jednorozměrný, ukazatelovou aritmetikou s nim budem pracovat jako s dvourozměrným )
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        // alokujem si tu strukturu kterou chcem jakože vracet
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        
        // a mapu kterou do ní nacpem
        // (pozor, nehlídám selhávání alokace :O :O správně by sme měli uklízet alokovanou paměť když třeba selže až ten druhej malloc )
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        // enum který nám bude popisovat jednotlivý prvky mapy, zsatim tám máme jenom 'N' jakože nic a 'B' jakože blok
        enum herniVec {N,B};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // (sem to napsala takle 'dvourozměrně' na řádky by to bylo líp čitelný)
        
        // placka
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        
        // taková malinkatá pyramidka
        int seg2 [] =
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        
        // díra v zemi
        // na ni si vyzkoušíme jak to vypadá když David spadne do ďoury a jak se při tom chová kamera
        int seg3 [] =
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
    
        // vyrobíme si ty pomocný struktury (vicemeně jenom by sme měli někde poznamennanou vejšku a šiřku těch segmentů,
        // páč nemusej bejt dycky stejně velký, jak to máme zrovna teďko)
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {5,2,seg3},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        // na začátku potřebujem dát hráčoj trošku volnýho místa by pak nespadnul rovnou někam do boje třeba,
        // na konci si pak uděláme ňákou specialitku která bude voznačovat konec mapy
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        // budeme postupně do mapy kopírovat náhodně vybraný segmenty pěkně v řadě za sebou,
        // na to si potřebujem měřit zbejvající místo v mapě
        int zbyva_delka = sirka - 10;
    
        // dokud je zbejvajicí dýlka věčí než 15
        // k tomudle čislu sme došli tim, že chceme vynechat posledních 10 sloupců mapy a pětka je
        // nejmenčí možná dýlka náhodnýho segmentu. Takže dokavaď je dýlka rovna věčí patnácti, furt de
        // vygenerovat náhodnej segment aniž by sme vlezli do tý vyhrazený zóny na konci mapy
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            // (raylibová fuknce 'GetRandomValue' vrací celý čislo v rozsahu svýho prvního a druhýho argumentu(inkluzivně))
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            // pokud sme náhodou trefili moc dlouhej segment kterej se nám už na mapu nevejde (aniž by sme vlezli
            // do tý zóny na konci), tak si zkusíme vybrat jinej náhodnej segment
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    // zatim tam máme jenom ten blok mapy
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            // vod zbejvajicí dýlky vodečtem dýlku segmentu kterej sme tam nacpali
            zbyva_delka-=sirka_segmentu;
        }
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    // až si s levelem přestanem hrát, tak musíme alokovanou paměť po sobě uklidit
    // (a alokovanou pamět se musí dycky pak volat free())
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    void aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        // zatim eště nemáme co aktualizovat
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        // minimální a maximální vykreslovanou vzdalenost dlaždicový mapy spočitáme z kamery
        // kamera kouká někam doprostředka vobrazovky, takže když k tomu přičtem půlku šířky vobrazovky
        // na vobě strany, tak si krásně vymezíme v dlaždicový mapě voblast vobrazovky
        // (vodtransformováváme hodnotu z kamerovýho světa, proto to eště dělíme hodnotou zoomu)
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
    }
    
    #endif
    

    Pochopytelně si zase jakoby musíme upravit 'main.c', musíme si tam ten level vyrobit, mimojiný si taky musíme inicializovat generator náhodnejch čisel (raylib má svou vlastní funkci na generování pseudonáhodnejch čisel):

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidův vnitřní časovač střílecího cooldownu 
            .strileci_cooldown = 0.0f,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            // aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
    
        return 0;
    }
    


    Krok deset: ať žijí duchové!! 👻 👻 😱 😜

    Aby Davidoj nebylo na tý mapě smutno, tak mu tam přidáme duchy.

    Ve spritesheetu máme hnedka několik různejch duchů (nejsou jim vidět nohy páč to sou duchové hele a maj červeně sviticí voči protože sou zlí). Z tohodlectoho duchovního spritesheetu vybereme náhodnej vobrázek a to bude jakože ten náš duch. Duch bude jezdit po dlaždicový mapě a když narazí na překážku (což muže bejt jak blok v cestě nebo ďoura v zemi) tak se votočí a pojede na vopačnou stranu. Trochu zajimavější to eště možná bude když duchům přidáme i ňákou malou šanci na děsně překvapivou změnu směru.

    Duchové budou mit nějakej počet životů a dycky když ňákýho ducha král David trefí, tak duchoj jeden život vodečtem. Noa když duchoj životy dojdou, tak asi zahrajeme nějakej chcípací zvuk a uděláme nějakej jednoduchej chcípací efekt, celkem srandovní mi přišlo že se duch roztočí na mistě a pomaličku zmizne 😁 😁.

    Že David ducha trefil poznáme tak, že Davidův projektil bude v ňáký vobdelnikový voblasti voběktu ducha. Mohli by sme použít vobdelnik 'okraje', jenže to by sme detekovali zásach ducha vo hodně dřív, než by se Davidova kulka vubec ducha dotkla, takže si nadefinujeme kromě vokrajů ještě jeden vobdelnik, 'hitbox'. Bude to jakoby taková jakože podvoblast vobrázku ducha, kterou když trefíme tak až todlecto budem považovat za zásach ducha (hitboxy vykreslujem červeně když si nazačátku souboru main.c vodkomentujete to '#define DEBUG' tak je uvidite)

    Duchové taky budou po davidoj střílet vočima, takže každej duch bude mit podobně jako David nějakej zásobnik střel. Budou to takový malý červený softwérový kuličky který budem z duchů vypouštět někde na urovni jejich xiftů, podobně jako sme vypouštěli softwérový kuličky z tý Davidovy pistolky.

    Takže si vyrobíme ve zdrojákový složšce 'src' soubor 'duch.h' a napišem tam všecko todlenc co sme si řekli:

    #ifndef _DAVID_A_DUCHOVE_DUCH_H_
    #define _DAVID_A_DUCHOVE_DUCH_H_
    
    #include <stdlib.h>
    #include <raylib.h>
    
    #include "mapa.h"
    #include "projektily.h"
    
    
    // vezmem si z 'main.c' texturu spritesheetu duchů a zvuky
    extern Texture2D textura_duchove_spritesheet;
    
    extern Sound zvuk_duch_chcip;
    extern Sound zvuk_duch_strela;
    
    // maximalni počet životů ducha
    #define HITPOINTU_DUCHA 3
    
    // čas v sekundách jak dlouho duch chcípe
    #define CHIPACI_CAS_DUCHA 1.5f
    
    // kolik má duch střel
    #define ZASOBNIK_STREL_DUCHA 3
    
    // střílecí cooldown ducha, vlastně to střílení je uplně identicky řešený jako v davidoj :O ;D
    #define STRILECI_COOLDOWN_DUCHA 1.0f
    
    // rychlost vypálenejch projektilů ducha
    #define RYCHLOST_STRELY_DUCHA 600.0f
    
    //rychlost chůze ducha
    #define RYCHLOST_CHUZE_DUCHA 120.0f
    
    // šířka a vejška jednoho 'podvobrázku' v spritesheetu
    #define DUCH_F_VYSKA 240.0f
    #define DUCH_F_SIRKA 85.0f
    
    typedef struct Duch {
        
        // směr kterým duch kouká, taky identicky řešený jako v davidoj
        int smer;
        
        // hp jakože hitpointy jakože počet životů
        int hp;
    
        // oblast textury, jakože kterej kousek z toho spritesheetu s duchama jsme vybrali
        Rectangle oblast_textury;
        
        // okraje ducha, podobně jako u davida
        // (duchoj vodpovídaj vokraje velikosti textury, to u davida neplatí)
        Rectangle okraje;
        
        // hitbox, voblast která definuje 'zranitelnou' část vobrázku ducha
        // bude trochu tenčí než 'okraje', by sme měli zásah až když bude kulka fakt někde nad
        // viditelnou částí vobrázku
        // a pak taky trošku nad zemí (ta poloprusvitná část vobrázků duchů bude jakoby nezranitelná)
        Rectangle hitbox;
    
        // jestli je duch aktivní
        // pokud neni, tak ho nebudem vykreslovat ani aktualizovat, prostě bude upně vyplej
        bool aktivni;
        
        // jestli duch chícpe, jakože mu už došly hitpointy a máme za
        bool chcipe;
    
        // vnitřní čas ducha
        float relativni_cas;
        
        // uhel ducha pro animaci efektu chcípání
        float uhel;
        
        // střílecí cooldown ducha
        float strileci_cooldown;
    
        
        // zásobnik střel ducha
        Strela * strely;
    
        // zvuky ducha
        // pozor budou to 'aliasy' těch zvuků,povim v 'konstruktoru'
        Sound zvuk_chcipnuti;
        Sound zvuk_strela;
    }
    Duch;
    
    // takovej jakože pseudokonstruktor instace ducha
    // bere jedinej argument, pozici bodu kde ducha jakoby vyrobíme
    //pozor, používá malloc, takže se pak musí udělat na každým duchoj freeDucha()
    Duch * vygenerovatDucha ( Vector2 kde )
    {
        // alokujem si ducha, kterýho pak budeme v připadě uspěšnýho vyrobení z konstrukoru vracet
        // (když se něco pokazí, vracíme nulovou adresu, prostě nulu)
        Duch * duch = calloc ( 1, sizeof ( Duch ) );
        if(!duch)return NULL;
        
        // počáteční směr ducha bude náhodnej
        duch->smer = GetRandomValue( 0,1 ) ? 1 : -1;
        
        // vokraje určíme z počáteční polohy a rozměrů podvobrázku spritesheetu
        duch->okraje = ( Rectangle ) {
            kde.x,kde.y,DUCH_F_SIRKA,DUCH_F_VYSKA
        };
        
        // podobně si určíme hitbox, bude ale votrošku menčí než okraje a bude i trošku kratčí na vejšku
        // (kuli těm nezranitelnejm nohoum duchů)
        duch->hitbox = ( Rectangle ) {
            kde.x+15,kde.y+15,55,155
        };
        
        // oblast textury určíme náhodně, vybereme uplně náhodnej podvobrázek
        duch->oblast_textury = ( Rectangle ) {
            DUCH_F_SIRKA * GetRandomValue( 0,5 ),0 + DUCH_F_VYSKA * GetRandomValue( 0,1 ),DUCH_F_SIRKA * duch->smer,DUCH_F_VYSKA
        };
        
        // aktivujem ducha a nastavíme mu hitpointy na vychozí hodnotu
        duch->aktivni = true;
        duch->hp = HITPOINTU_DUCHA;
        
        // a nakopírujem si zvuky tim, že si vyrobíme jejich alias
        // Potíž s normálníma zvukama v raylib je v tom, že dycky máme jakoby jenom jednu přehratelnou instanci. U voběktu/struktury davida
        // todle neni moc vekej problém, páč Davida máme na mapě jenom jednoho a ten jeho kod vubec moc nepřipouští situace žeby David měl
        // vydávat ňákej stenej zvuk rychle posobě. Duchů ale budem mit na mapě hodně a šance na tudle kolizi přehrávání je vyrazně věčí,
        // třeba zvuk chcípání ducha je dost dlouhej a je možný že ho budem chtít začít přehrávat ve stejným vokamžiku,
        // kdy ho už ňákej jinej chcipajicí duch hraje. Stalo by se nejspiš to že by to stoplo předchazejicí přehrávání a začalo by to hrát
        // stejnej zvuk vodzačátku.
        // Na todlecto chytrý lidi vod raylibu naštěstí mysleli a přidali možnost vyrábění aliasu zvuků, prostě si jakoby vyrobíme kopii toho zvuku
        // (pod kapotou nejspíš ty kopie a voriginál furt sdílej stejný zdrojový data zvuku, jen si k tomu každá kopie asi jakoby pamatuje jinej
        // balast vokolo, jakože čas přehrávání, nastavení hlasitosti etc)
        
        // takže si vyrobíme ty aliasy zvuků
        duch->zvuk_chcipnuti = LoadSoundAlias ( zvuk_duch_chcip );
        duch->zvuk_strela = LoadSoundAlias ( zvuk_duch_strela );
    
        // nakonec alokujeme střely
        // (děláme to stejně jako se střelama pro Davida)
        duch->strely = calloc ( ZASOBNIK_STREL_DUCHA, sizeof ( Strela ) );
        if(!duch->strely)
        {
            free(duch);
            return NULL;
        }
        for ( size_t i =0; i<ZASOBNIK_STREL_DUCHA; i++ ) {
            duch->strely[i].druh = strela_ducha;
        }
        
    
        return duch;
    }
    
    // funkce na vykreslování ducha
    void vykreslitDucha ( Duch * duch )
    {
        // ducha budem vykreslovat jenom když je aktivní
        if ( !duch->aktivni ) {
            return;
        }
    
    
        // jestli duch chcípe, tak budem vykreslovat ten efekt umiraní
        if ( duch->chcipe ) {
            
            // vyrobíme si kopii vokrajů,
            // převedem si progress chcípání do rozsahu vod nuly do jedničky a invertujem to
            // noa tim budem scvrkávat velikost tý kopie vobdélnika vokrajů
            Rectangle _okraje = duch->okraje;
            const float chcipani = 1.0f - duch->relativni_cas/CHIPACI_CAS_DUCHA;
            _okraje.x += _okraje.width/2;
            _okraje.y += _okraje.height/2;
            _okraje.width *= chcipani;
            _okraje.height *= chcipani;
            
            // budeme texturu vykreslovat do tý scvrklý kopie vokrajů a střed textury posunem z defaultního
            // levýho horního rohu doprostředka. To děláme proto, že nastavujeme i úhel náklonu vykreslovaný textury noa
            // chcem, by střed rotace nebyl někde v tom rohu vobrázku, ale pěkně uprostřed 
            // barvu textury budem nastavovat pomocí raylibový funkce 'Fade', ta nám umožňuje měnit alfa složšku barvy (pro nás
            // teďko alfa znamená 'průsvitnost' resp. 'neviditelnost' tý barvy) ňákou hodnotou v rosahu nula až jedna
            // (duch se bude jakoby postupně zneviditelňovat jak bude chcípat)
            DrawTexturePro ( textura_duchove_spritesheet,duch->oblast_textury,_okraje,
                                ( Vector2 ) { _okraje.width/2.0f,_okraje.height/2.0f},
                                duch->uhel, Fade ( WHITE, 1.0f - duch->relativni_cas/CHIPACI_CAS_DUCHA ) );
    
        } else {
            // když duch nechcípe, vykreslíme ho uplně normálně
            DrawTexturePro ( textura_duchove_spritesheet,duch->oblast_textury,duch->okraje, ( Vector2 ) {0,0},0.0f, WHITE );
        }
    
    #ifdef DEBUG
        // v připadě debugovávání vykreslíme okraje a hitbox
        DrawRectangleLines ( duch->okraje.x,duch->okraje.y, duch->okraje.width, duch->okraje.height,GREEN );
        DrawRectangleLines ( duch->hitbox.x,duch->hitbox.y, duch->hitbox.width, duch->hitbox.height,RED );
    #endif
    }
    
    // funkce na aktualizovávání ducha
    // jako argumenty bere pochopytelně ducha, pak mapu ve který se duch jakože pohybuje noa pak vobligátní časovou deltu
    void aktualizovatDucha ( Duch * duch, Mapa * mapa, float dt )
    {
    
        // když neni aktivní, tak ho nebudem aktualizovat
        if ( !duch->aktivni ) {
            return;
        }
        
        // jestli eště duch nechcípe ale má hitpointy na nule,
        // tak mu zapnem chcípání a začnem přehrávat zvuk chcípání
        if ( !duch->chcipe && duch->hp <= 0 ) {
            duch->chcipe = true;
            PlaySound ( duch->zvuk_chcipnuti );
        }
    
        // jestli duch chcípe, tak mu začnem měřit relativní čas, by sme věděli jestli už uplynula doba
        // potřebná na uplný chpípnutí ducha. Až ta doba uplyne, tak ducha uplně vypnem (nastavíme mu atribut 'aktivní' na false)
        if ( duch->chcipe ) {
            duch->relativni_cas += dt;
            
            // eště musíme při tom chcípání furt upravovat tu rotaci vykreslovaný textury
            // myslimže to bude takový zajimavější když se rychlost rotace bude s uplynulým časem furt zvěčovat 
            duch->uhel+= dt * ( 500 + 250 * duch->relativni_cas );
            if ( duch->relativni_cas > CHIPACI_CAS_DUCHA ) {
                duch->aktivni = false;
            }
            
            //noa jestli duch chcípe, tak už nás nezajímá žádný další dělání v tý jeho aktualizční funkci, už nikam nebude chodit ani střílet,
            // prostě z týdle funkce vyskočíme returnem
            return;
        }
    
        // malá pravděpodobnost že duch nečekaně změní směr
        if ( GetRandomValue ( 0,1000 ) == 1 ) {
            duch->smer*=-1;
            
            // překlopíme šiřku zdrojový textury, by se nám vykreslovala zrcadlově vobráceně
            // (podobně sme ďáli už v 'animace.h')
            duch->oblast_textury.width *= -1.0f;
        }
    
        // uplně stejně jako u davida budem počitat prepozici
        Rectangle prepozice = duch->okraje;
        
        // když de z leva doprava
        if ( duch->smer == 1 ) {
            
            // posunem prepozici vo rychlost ducha krát časová delta
            prepozice.x += RYCHLOST_CHUZE_DUCHA * dt;
            
            // a eště si spočitáme roh pravýho dolního vokraje prepozice a posunem ho
            // vo nějakejch pět pixelů dolu. Timdle bodem se budeme koukat, jestli má prepozice
            // pod sebou pevnou kostku mapy, noa jestli ne duch přišel na vokraj plošiny :O ;D
            Vector2 bod = ( Vector2 ) {
                prepozice.x + prepozice.width, prepozice.y + prepozice.height +5
            };
    
            // kouknem jestli nenastává kolize prepozice s blokem mapy, nebo jestli prepozice nekončí nad ďourou
            // v tom připadě votočíme ducha a příští aktualizací pude duch vopačným směrem
            if ( kolizeRectSeBlokemMapy ( prepozice, mapa ) || ! kolizeSeBlokemMapy_bod ( bod,mapa ) )
            {
                duch->smer *= -1;
                duch->oblast_textury.width *= -1.0f;
            } else {
                
                // jinak posunem ducha na prepozici
                duch->okraje.x += RYCHLOST_CHUZE_DUCHA * dt;
                duch->hitbox.x += RYCHLOST_CHUZE_DUCHA * dt;
            }
            
        // když de z prava doleva
        // vlastně to je zase uplně to samý jako pro chození  z leva doprava, jenom na vopačnou stranu :D ;D
        } else if ( duch->smer == -1 ) {
            prepozice.x -= RYCHLOST_CHUZE_DUCHA * dt;
            if ( kolizeRectSeBlokemMapy ( prepozice, mapa ) || ! kolizeSeBlokemMapy_bod ( ( Vector2 ) {
            prepozice.x, prepozice.y + prepozice.height +5
        },mapa ) ) {
                duch->smer *= -1;
                duch->oblast_textury.width *= -1.0f;
            } else {
                duch->okraje.x -= RYCHLOST_CHUZE_DUCHA * dt;
                duch->hitbox.x -= RYCHLOST_CHUZE_DUCHA * dt;
            }
        }
    
        // střílení je vlastně taky uplně stejný jako u davida, taky se počitá střilecí colldown, taky se vybírá
        // volná neaktivní střela, taky se recykluje, taky se ji nastavuje ňáká rychlost etc
        if ( duch->strileci_cooldown > 0.0f ) {
            duch->strileci_cooldown-=dt;
        } else {
            // jenom tady nemáme to chování nijak hráčem vovládaný
            // prostě budem střílet náhodně když uplyne cooldown tak budeme skoušet trefovat náhodný čislo tak dlouho
            // až nám padne naše vybraný noa v ten vokamžik duch zkusí vystřelit
            if ( GetRandomValue ( 0,200 ) == 1 ) {
                for ( size_t i =0; i<ZASOBNIK_STREL_DUCHA; i++ ) {
                    if ( !duch->strely[i].aktivni ) {
    
                        // vyrobíme si střelu a nakopírujem jeji hodnoty na vodpovidajicí misto v zasobniku
                        Strela s = {
    
                            .druh = strela_ducha,
                            .rychlost = RYCHLOST_STRELY_DUCHA * ( float ) duch->smer,
                            .pozice = ( Vector2 ) { duch->smer==1? duch->okraje.x+DUCH_F_SIRKA/2.0f: duch->okraje.x,duch->okraje.y + 25},
                            .relativni_cas = 0.0f,
                            .doba_zivota = 2.0f,
                            .aktivni=true,
                        };
                        duch->strely[i] = s;
    
                        // zahrajeme zvuk výstřelu, nastavíme střílecí čekací čas a řerušíme hledací for cyklus
                        PlaySound ( duch->zvuk_strela );
                        duch->strileci_cooldown = STRILECI_COOLDOWN_DUCHA;
                        break;
                    }
                }
    
    
            }
        }
    
    }
    
    // něco jako destruktor ducha
    // musíme samozdřejmě uvolnit alokovaný struktury
    // a taky aliasy zvuků
    void freeDucha ( Duch * duch )
    {
        UnloadSoundAlias ( duch->zvuk_chcipnuti );
        UnloadSoundAlias ( duch->zvuk_strela );
        
        free( duch->strely );
        free ( duch );
    }
    
    #endif
    

    Duchové uměj střílet, takže si upravíme soubor 'projektily.h' a přidáme si tam novej druh střely a jeho vykreslování:

    #ifndef _DAVID_A_DUCHOVE_PROJEKTILY_H_
    #define _DAVID_A_DUCHOVE_PROJEKTILY_H_
    
    #include <raylib.h>
    
    #include "mapa.h"
    
    // přidáme si sem střelu duchů
    enum druh_strely {strela_davida,strela_ducha};
    
    typedef struct Strela {
        
        // rychlost střely
        float rychlost;
        
        // relativní čas střely
        float relativni_cas;
        
        // nastavená maximální doba života střely
        // když relativní čas překročí tudle hodnotu tak střelu deaktivujem a budem považovat za zničenou
        float doba_zivota;
        enum druh_strely druh;
        
        // pozice střely
        Vector2 pozice;
        
        // zda je střela aktivní
        // pokud aktivní neni považujem ji za zničenou a/nebo nevystřelenou, takovou střelu nebudeme
        // vykreslovat ani aktualizovat
        bool aktivni;
    }
    Strela;
    
    void aktualizovatStrelu ( Strela * strela, Mapa * mapa, float dt )
    {
        strela->relativni_cas += dt;
        if ( strela->relativni_cas > strela->doba_zivota ) {
            strela->aktivni = false;
        } else {
            strela->pozice.x += dt * strela->rychlost;
            
            // pokud dojde ke srážce střely s blokem mapy, tak střelu deaktivujem
            if ( kolizeSeBlokemMapy_bod ( strela->pozice, mapa ) ) {
                strela->aktivni = false;
            }
        }
    }
    
    void vykreslitStrelu ( Strela * strela )
    {
        if ( !strela->aktivni ) {
            return;
        }
        switch ( strela->druh ) {
        case strela_davida:
            DrawCircleGradient ( strela->pozice.x,strela->pozice.y,5.0f,WHITE,DARKGRAY );
            break;
            
        // přidáme si sem střelu duchů
        // bude to taky taková červená softwérová kulička
        case strela_ducha:
            DrawCircleGradient ( strela->pozice.x,strela->pozice.y,5.0f,RED,Fade(RED,0.8f) );
            break;
        default:
            break;
        }
    }
    
    #endif
    

    Uravíme soubor 'level.h' a přidáme si tam generování a aktualizaci duchů, vodteďka tam bude bydlet vzajemná interakce herních věcí s Davidem:

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    
    // zvuk zásahu
    // (je hrozně moc krátkej tak si myslim že asi jako nemusíme mit alias)
    extern Sound zvuk_zasah;
    
    // maximální vejška mapy (hodnota je v počtu kostek dlaždicový mapy)
    #define MAPA_MAX_VYSKA 10
    
    // minimální nutná vzdálenost herních entit vod polohy Davida abysme je vykreslovali a aktualizovali
    // (herní svět muže bejt děsně velkej a bylo by zbytečný aktualizovat a vykreslovat věci který sou vod hráče moc daleko,
    // takže je vlastně ani eště nemůže vidět ani s nima iteragovat ňák)
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // struktura levelu
    typedef struct Level {
        
        // pole duchů 
        // (budem to použivat jako jednorozměrný pole ukazatelů na jednotlivý instance duchů)
        Duch ** duchove;
        
        // kolik je v poli duchů
        size_t pocet_duchu;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    // pomocná struktura pro generování mapy
    // pude popisovat dílčí kousek ze kterejch budeme skládat tu svou náhodnou mapu
    // bude to vlastně takový jakoby dvourozměrný pole
    // (je to nadefinovaný jako jednorozměrný, ukazatelovou aritmetikou s nim budem pracovat jako s dvourozměrným )
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        // alokujeme si pole duchů
        // připravíme si prostor pro 256 duchů, páč ještě nevíme kolik jich budem vyrábět
        // zbytečný místo pak ucvaknem
        // (určitě by šlo vodhadnout worst case scenario z dýlky levelu ale na to kadí dalmatýn)
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        enum herniVec {N,D,B};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // přidáme si tam ňáký segmenty s duchama
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
    
    
        int seg5 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {10,5,seg5},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        // na začátku potřebujem dát hráčoj trošku volnýho místa by pak nespadnul rovnou někam do boje třeba,
        // na konci si pak uděláme ňákou specialitku která bude voznačovat konec mapy
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        // budeme postupně do mapy kopírovat náhodně vybraný segmenty pěkně v řadě za sebou,
        // na to si potřebujem měřit zbejvající místo v mapě
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
    
        // dokud je zbejvajicí dýlka věčí než 15
        // k tomudle čislu sme došli tim, že chceme vynechat posledních 10 sloupců mapy a pětka je
        // nejmenčí možná dýlka náhodnýho segmentu. Takže dokavaď je dýlka rovna věčí patnácti, furt de
        // vygenerovat náhodnej segment aniž by sme vlezli do tý vyhrazený zóny na konci mapy
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            // (raylibová fuknce 'GetRandomValue' vrací celý čislo v rozsahu svýho prvního a druhýho argumentu(inkluzivně))
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            // pokud sme náhodou trefili moc dlouhej segment kterej se nám už na mapu nevejde (aniž by sme vlezli
            // do tý zóny na konci), tak si zkusíme vybrat jinej náhodnej segment
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            // pozice bude souřadnice bloku minus vejška dvou bloků a chlup (chlup by se nám duch neprolínal s blokama mapy)
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            // strčíme ducha do toho našeho zasobniku a počítadlo duchů pak zvednem vo jedničku
                            duchove[duchu++] = duch;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            // vod zbejvajicí dýlky vodečtem dýlku segmentu kterej sme tam nacpali
            zbyva_delka-=sirka_segmentu;
        }
        
        // realokujem pole duchů, máme tam zabranýho víc místa než kolik sme relalně duchů alokovali,
        // určitě sme jich nevyrobili 256 :D ;D
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
    
        //nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
    
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    void aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        // teďko už máme co aktualizovat :D ;D
        // ukazatel na davidovy střely
        Strela * strely = david->strely;
        
        // každou aktualizací projdem pole duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            // a kouknem, jestli je duch dostatečně blízko k hráčoj, abysme s duchem ztráceli
            // čas a aktualizovali ho. Pokud je iksová vzdálenost Davida a Ducha věčí než dýlka dvaceti kostek,
            // tak ducha přeskočíme a pokusíme se aktualizovat dalšího
            // (tamto 'fabsf' je absolutní hodnota která bere i vrací float, použiváme ji na to měření vzdáleností)
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            // pokud je duch dostatečnš blízko tak se kouknem jestli nechcípe....
            if ( ! lvl->duchove[i]->chcipe )
                // noa jestli eště nechcípe, tak postupně projdem všecky Davidovy projektily a kouken jestli nááhodou některá
                // z nich neleží ve voblasti hitboxu ducha (zistíme funkcí 'CheckCollisionPointRec' z raylibu)
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            // noa jestli v tom hitboxu některá z aktivních střel skutečně je, tak ji 'zničíme' tim
                            // že ji deaktivujem
                            s->aktivni = false;
                            
                            // noa pak duchoj vodečtem hitpoint a zahrajem zvuk zásahu
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            // aktualizujem každýho ducha kterej je dostatečně blízko....
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
    
            // ....a každýmu duchoj eště aktualizujem všecky střely
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                }
            }
        }
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    }
    
    #endif
    

    Noa nakonec si v 'main.c' načtem nový zvuky a spritesheet duchů:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidův vnitřní časovač střílecího cooldownu 
            .strileci_cooldown = 0.0f,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu
        // (jsou vo trošku menčí než vokraje voblasti framu animace)
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
    
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            // aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
    
        return 0;
    }
    


    Krok jedenáct: zranitelnej David ❤️‍🩹

    Máme duchy a mužeme je postřílet, jenom to asi jakoby nebude moc velká zábava když je David nezranitelnej 🙄 😜 Uděláme to s Davidem jako s duchem, nastavíme mu nějakej počet životu a přidáme mu hitbox. A když se duchové do Davida trefjej (střela ducha zasáhne hitbox) nebo se Davida dotknou (hitbox ducha má kolizi s hitboxem Davida), tak mu vodečtem život (David zatim eště nebude nijak umírat, budem zatim jenom vodečítat ty životy).

    Aby zásah nepřítelem Davida hnedka nezabil a nesebral mu všecky životy, tak mu dycky nastavíme krátkej čas nezranitelnosti. V různejch hrách co sem viděla se přitom postavička rozbliká a dokavaď je postavička nezranitelná tak furt bliká. Tendle koncept vykradem a uděláme by nám David při zranění blikal.

    Nóó takže si upravíme kód Davida v 'david.h' apřidáme mu tam tu nezranitelnost a blikání:

    #ifndef _DAVID_A_DUCHOVE_DAVID_H_
    #define _DAVID_A_DUCHOVE_DAVID_H_
    
    #include "animace.h"
    #include "mapa.h"
    #include "projektily.h"
    
    extern Sound zvuk_kroku;
    extern Sound zvuk_skoku;
    extern Sound zvuk_vystrel;
    
    // načtem si zvuk pádu kterej budem hrát dycky když nám David zahučí někam do ďoury v zemi
    extern Sound zvuk_padu;
    
    #define DAVID_F_SIRKA 150.0f
    #define DAVID_F_VYSKA 240.0f
    
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    
    
    };
    
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    #define RYCHLOST_CHUZE_DAVIDA 350.0f
    #define RYCHLOST_SKOKU_DAVIDA -15.0f
    #define GRAVITACE_DAVIDA 40.0f
    #define RYCHLOST_STREL_DAVIDA 800.0f
    #define STRILECI_COOLDOWN_DAVIDA 0.25f
    #define POCET_STREL_DAVIDA_MAX 32
    
    // přidáme si sem maximální počet životů/hitpointů davida
    #define POCET_ZIVOTU_DAVIDA_MAX 10
    // a blikací čas (v sekundách)
    #define BLIKACI_CAS_DAVIDA 0.5f
    
    typedef struct David {
        
        Animace animace_beh;
        Animace animace_idle;
        Animace animace_sed;
        Animace animace_skok;
    
        Animace * aktualni_animace;
    
        Vector2 pozice;
        
        Rectangle okraje;
        
        // david bude mit vodteď hitbox vymezujicí jeho zranitelnou voblast, podobně jako duchové
        Rectangle hitbox; 
        
        int smer;
        
        Mapa * mapa;
    
        bool zdaSkace;
        float vertikalni_rychlost;
        
        Strela * strely;
        float strileci_cooldown;
        
        // david bude mit eště další nový tři atributy
        // aktuální počet životů
        int zivoty;
        
        // zbejvajicí čas blikání (dočasný nezranitelnosti po zásahu)
        float blikaci_cas;
        
        // a boolean jestli je právě teďko zranitelnej nebo ne
        bool zranitelny;
    
    } David;
    
    
    void aktualizovatDavida ( David * david, float dt )
    {
    
        if ( IsKeyDown ( KEY_UP ) ) {
    
            if ( david->aktualni_animace == &david->animace_sed ) {
                david->aktualni_animace->pauznuta = false;
                david->aktualni_animace->reverzne=true;
    
                if ( david->aktualni_animace->index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
    
            } else if ( !david->zdaSkace ) {
                PlaySound ( zvuk_skoku );
                david->zdaSkace = true;
                david->animace_skok.index = 0;
                david->vertikalni_rychlost = RYCHLOST_SKOKU_DAVIDA;
            }
        }
        
        // když hráč zmáčkne mezernik, tak se David pokusí vystřelit z tý svý pistolky
        if ( IsKeyDown ( KEY_SPACE ) ) {
            // vystřelit mužeme jenom když uplynula čekací doba mezi výstřelama resp. střílecí cooldown je menší nebo rovnej nule
            if ( david->strileci_cooldown <= 0.0f ) {
                // projdeme si celej davidův zásobník a pokusíme se v něm najít střelu, kterou budeme moct použít
                // to poznáme tak, že bude mit atribut aktivní nastavenej na nulu
                for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
                    if ( !david->strely[i].aktivni ) {
                        
                        // pokud sme takovou střelu našli, tak si vybereme pro upravování atributů
                        Strela * s = david->strely + i;
    
                        // nejdřiv ji nastavíme novou polohu,
                        //to znamená přibližně někam na konec hlavně tý pistolky co má david v rukou
                        
                        //nj jenže david muže stát, sedět na zemi, muže koukat z prava doleva, nebo muže dokonce právě vstávat ze země
                        // všecky tydlecty eventualitky jakoby musíme pokrejt
                        if ( david->aktualni_animace != &david->animace_sed )
                            s->pozice = ( Vector2 ) {
                            // střelu umisťujem podle toho jakým směrem david kouká
                            david->smer==1? david->pozice.x+DAVID_F_SIRKA - 25: david->pozice.x+25,
                            david->pozice.y + DAVID_F_VYSKA/2 - 36
                        };
                        else {
                            // pokud david má jako aktuální animaci sedání, tak si zistíme index a vo ten budeme posouvat iksovou a ypsilonovou
                            // souřadnici střely. Neni to uplně přesný ale na to nikdo koukat nebude :D
                            int index = david->animace_sed.index;
                            s->pozice = ( Vector2 ) {
                                david->smer==1? david->pozice.x+DAVID_F_SIRKA - 25 - index*5: david->pozice.x+25 + index*5,david->pozice.y + DAVID_F_VYSKA/2 - 26 - 8 + index*14
                            };
    
                        }
                        
                        //polohu máme, teďko nastavíme další atributy střely
                        
                        // nastavíme střele rychlost, zohledníme i směr kterým poletí, ten vodpovídá
                        // směru kterým David právě teďko kouká
                        s->rychlost = RYCHLOST_STREL_DAVIDA * ( float ) david->smer;
                        
                        // vynulujem relativní čas
                        s->relativni_cas = 0.0f;
                        
                        // nastavíme dobu života třeba na čtyry vteřiny
                        s->doba_zivota = 4.0f;
                        
                        // a aktivujem
                        s->aktivni=true;
                        
                        // střelu máme upravenou, ukazatel už nepotřebujem
                        s=0;
    
                        // ..a když sme aktivovali střelu, tak sme vlastně vystřelili, takže nastavíme střílecí čekací dobu
                        // na maximální hodnotu
                        david->strileci_cooldown = STRILECI_COOLDOWN_DAVIDA;
                        
                        // zahrajem zvuk výstřelu
                        PlaySound ( zvuk_vystrel );
                        
                        // a přerušíme hledací for cyklus
                        break;
                    }
                }
            }
            // eště upravíme aktuální animaci, pokud to neni animace sedání, tak přepnem animaci na idle na první snímek,
            // páč při tý animaci david hejbe pistolkou a vypadalo by to divně kdyby z ní vylítla vodorovně střela. Pokud david skáče,
            // běží nebo padá, tak se nám ta animace stejně přepne někde dál tady ve zdrojáčku týdle funkce
            // (při animaci běhu/skoků todle nepřectavuje problém, pistolka je na všech vobrázcích spritesheetu ve stejný vejšce,
            // kromě tý animace 'idle', tam je ve stejný vejšce právě jenom na prvním snimku)
            if ( david->aktualni_animace != &david->animace_sed ) {
                david->aktualni_animace = & david->animace_idle;
                david->aktualni_animace->index = 0;
                david->aktualni_animace->relativni_cas = 0.0f;
            }
        }
    
    
        
        if ( IsKeyDown ( KEY_LEFT ) && david->pozice.x > 0 && david->aktualni_animace != &david->animace_sed ) {
            
            david->smer = -1;
            
            Rectangle prepozice = david->okraje;
            prepozice.x -= RYCHLOST_CHUZE_DAVIDA * dt;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
    
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                
                // aktualizujem pozici hitboxu
                david->hitbox.x = david->okraje.x + 10;
                
                david->aktualni_animace = &david->animace_beh;
                }
    
            }
        
        else if ( IsKeyDown ( KEY_RIGHT ) && david->pozice.x < david->mapa->sirka*BLOK_SIRKA - DAVID_F_SIRKA && david->aktualni_animace != &david->animace_sed ) {
    
            david->smer = 1;
            Rectangle prepozice = david->okraje;
            prepozice.x += RYCHLOST_CHUZE_DAVIDA * dt;
            
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                
                // aktualizujem pozici hitboxu
                david->hitbox.x = david->okraje.x + 10;
                
                david->aktualni_animace = & david->animace_beh;
                } 
        }
        // jestli je máčkutej na klávesnici čudlik šipky dolu, tak začnem přehrávat animaci sednutí
        // si na zadek
        else if ( IsKeyDown ( KEY_DOWN ) ) {
    
            david->aktualni_animace = & david->animace_sed;
            david->aktualni_animace->reverzne = false;
            david->aktualni_animace->pauznuta = false;
            }
            
        else if ( david->aktualni_animace != &david->animace_sed ) {
            david->aktualni_animace = & david->animace_idle;
            }
            
        Rectangle prepozice = david->okraje;
        prepozice.y += 5;
        if ( ! kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
            david->zdaSkace = true;
        }
    
        if ( david->zdaSkace ) {
    
            david->vertikalni_rychlost += dt * GRAVITACE_DAVIDA;
            
            Rectangle prepozice = david->okraje;
            prepozice.y += david->vertikalni_rychlost;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                
                david->vertikalni_rychlost = 0.0f;
                david->zdaSkace = false;
    
                david->okraje.y =  ceil ( ( david->okraje.y + david->okraje.height  ) /BLOK_VYSKA ) * BLOK_VYSKA - david->okraje.height - 1;
    
                if ( david->aktualni_animace == &david->animace_beh ) {
                    david->aktualni_animace->index = david->animace_skok.index +5;
                    david->aktualni_animace->reverzne = david->animace_skok.reverzne;
                }
    
            } else {
                
                david->aktualni_animace = & david->animace_skok;
                
                david->okraje.y += david->vertikalni_rychlost;
    
            }
    
            // aktualizujem po dopadu taky hitbox
            david->hitbox.y = david->okraje.y + 12;
            david->pozice.y = david->okraje.y - 3;
            
    
        }
    
        david->aktualni_animace->zrcadlit = david->smer<0;
    
    
        if ( david->aktualni_animace == &david->animace_sed ) {
            
            // pokud má David jako aktualní animaci sedání, tak mu musíme nastavit hitbox podle jednotlivejch framů tý animace
            // asi to takle nebude uplně přesný, nicmeně pro náš učel to je dostatečně přesný, schvalně si zapněte v main.c DEBUG :D ;D
            david->hitbox= ( Rectangle ) {
                david->pozice.x + 55 + david->smer* ( -5*david->animace_sed.index ), david->pozice.y + 10 + 13*david->animace_sed.index, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30-13*david->animace_sed.index
            };
            
            
            if ( david->animace_sed.pauznuta ) {
                if ( david->animace_sed.index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            }
    
        }
    
        else if ( david->aktualni_animace == &david->animace_beh ) {
            if ( !IsSoundPlaying ( zvuk_kroku ) ) {
                PlaySound ( zvuk_kroku );
            }
        }
        
        // jestli má David moc podezřele velkou ypsilonovou souřadnici tak asi jako nejspíš spadnul do ďoury
        // zahrajeme zvuk pádu (jestli už nehraje) a budem mu postupně každým voláním týdle aktualizvávací funkce
        // vodečítat jeden život za druhým až uplně umře :O ;D
        if ( david->pozice.y > BLOK_VYSKA*13 ) {
            if ( !IsSoundPlaying ( zvuk_padu ) ) {
                PlaySound ( zvuk_padu );
            }
    
            david->zivoty--;
        }
        
        if ( david->aktualni_animace == &david->animace_skok && IsSoundPlaying ( zvuk_kroku ) ) {
            StopSound ( zvuk_kroku );
        }
        
        if ( david->strileci_cooldown > 0.0f ) {
            david->strileci_cooldown -= dt;
        }
        
        // pokud je davidův blikací čas věčí než nula, tak vod něj vodečtem časovou deltu
        // a uděláme Davida nezranitelnýho, páč furt eště bliká
        if ( david->blikaci_cas > 0.0f ) {
            david->blikaci_cas -= dt;
            david->zranitelny = false;
        } else {
            //ale jestli už doblikal, tak už zase zranitelnej bude
            david->zranitelny = true;
        }
        
        for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
            aktualizovatStrelu ( david->strely+i, david->mapa,dt );
        }
    
        aktualizovatAnimaci ( david->aktualni_animace, dt );
    
    }
    
    // funkce na vykreslování Davida
    void vykreslitDavida ( David * david )
    {
        // pokud je David nezranitelnej, tak bude červeně blikat
        // podělíme si blikací čas ňákým kouskem kterej nám bude určovat periodu blikání
        // tou desetinou bliknem nějak 10x za vteřinu
        if ( !david->zranitelny ) {
            Color barva = ( int ) ( david->blikaci_cas/0.1f ) %2 ? WHITE : RED;
            vykreslitAnimaci ( david->aktualni_animace, david->pozice,barva );
        } else {
            vykreslitAnimaci ( david->aktualni_animace, david->pozice,WHITE );
        }
        
        for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
            vykreslitStrelu ( david->strely+i );
        }
    
    #ifdef DEBUG
        DrawRectangleLines ( david->okraje.x, david->okraje.y, david->okraje.width, david->okraje.height, GREEN );
        // nově teďko vykreslujem červeně i ten hitbox
        DrawRectangleLines ( david->hitbox.x, david->hitbox.y, david->hitbox.width, david->hitbox.height, RED );
    #endif
    }
    
    #endif
    

    Musíme upravit soubor 'level.h' a přidat tam novou interakci duchů a Davida, vodteď tam budem v aktualizaci hlídat kolizi hitboxů duchů s Davidovým hitboxem:

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    
    // zvuky
    extern Sound zvuk_zasah;
    extern Sound zvuk_kontakt;
    
    #define MAPA_MAX_VYSKA 10
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // struktura levelu
    typedef struct Level {
        
        Duch ** duchove;
        size_t pocet_duchu;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        // alokujeme si pole duchů
        // připravíme si prostor pro 256 duchů, páč ještě nevíme kolik jich budem vyrábět
        // zbytečný místo pak ucvaknem
        // (určitě by šlo vodhadnout worst case scenario z dýlky levelu ale na to kadí dalmatýn)
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        enum herniVec {N,D,B};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // přidáme si tam ňáký segmenty s duchama
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
    
    
        int seg5 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {10,5,seg5},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        // na začátku potřebujem dát hráčoj trošku volnýho místa by pak nespadnul rovnou někam do boje třeba,
        // na konci si pak uděláme ňákou specialitku která bude voznačovat konec mapy
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        // budeme postupně do mapy kopírovat náhodně vybraný segmenty pěkně v řadě za sebou,
        // na to si potřebujem měřit zbejvající místo v mapě
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
    
        // dokud je zbejvajicí dýlka věčí než 15
        // k tomudle čislu sme došli tim, že chceme vynechat posledních 10 sloupců mapy a pětka je
        // nejmenčí možná dýlka náhodnýho segmentu. Takže dokavaď je dýlka rovna věčí patnácti, furt de
        // vygenerovat náhodnej segment aniž by sme vlezli do tý vyhrazený zóny na konci mapy
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            // (raylibová fuknce 'GetRandomValue' vrací celý čislo v rozsahu svýho prvního a druhýho argumentu(inkluzivně))
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            // pokud sme náhodou trefili moc dlouhej segment kterej se nám už na mapu nevejde (aniž by sme vlezli
            // do tý zóny na konci), tak si zkusíme vybrat jinej náhodnej segment
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            duchove[duchu++] = duch;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            zbyva_delka-=sirka_segmentu;
        }
        
        // realokujem pole duchů, máme tam zabranýho víc místa než kolik sme relalně duchů alokovali,
        // určitě sme jich nevyrobili 256 :D ;D
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
    
        //nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
    
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    void aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        Strela * strely = david->strely;
        
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            if ( ! lvl->duchove[i]->chcipe )
    
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            s->aktivni = false;
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
            
            // pohlídáme si kolizi Davida s duchem, pokud se srazej tak duch Davida zraní
            // kolizi zistíme raylibí funkcí 'CheckCollisionRecs' do který nacpem hitboxy vobou herních entit
            if ( !lvl->duchove[i]->chcipe && CheckCollisionRecs ( lvl->duchove[i]->hitbox, david->hitbox ) ) {
                if ( david->zranitelny ) {
                    
                    // zahrajem zvuk kontaktu
                    // (vlastně nvm jestli to má bejt jakože zvuk co vydává duch nebo david :D )
                    PlaySound ( zvuk_kontakt );
                    
                    // vodečtem davidoj život
                    david->zivoty--;
                    
                    // nastavíme davidoj blikací čas dočasný nezranitelnosti..
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    
                    // ..a zapnem mu tu nezranitelnost
                    david->zranitelny = false;
                    
                    // pokud má ňákou vertikální rychlost směrem nahoru k hornímu vokraji vobrazkovky,
                    // tak mu ji snižime na nulu. Vono to vytváří takovej psychochologickej efekt jakože
                    // hráče ty duchové chytaj a bráněj mu v pohybu :O ;D
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
            }
    
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                    
                    // podobně jako sme hlídali zásah hitboxu ducha davidovou střelou,
                    // tak budeme klídat zásah davida střelou ducha
                    if ( CheckCollisionPointRec ( strela_ducha->pozice, david->hitbox ) ) {
                        strela_ducha->aktivni = false;
    
                        if ( david->zranitelny ) {
                            // v poctatě to samý jako při kontaktu
                            PlaySound ( zvuk_kontakt );
                            david->zivoty--;
                            david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                            david->zranitelny = false;
                        }
                    }
                }
            }
        }
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    }
    
    #endif
    

    V souboru 'main.c' musíme načíst nový zvuky a jednu texturu. V tý textuře je mimojiný namalový srdíčko, to použijem na vykreslování počtu Davidovejch životů v HUDu (češtinsky se to řekne 'průhledový display' hele 😁) vlevo dole na vobrazovce:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidovy vnitřní časovače střílecího cooldownu a času blikání resp. dočasný
            // nezranitelnosti po nepřátelským zásahu ie. islamistickým duchem nebo rudou kulkou
            .strileci_cooldown = 0.0f,
            .blikaci_cas = 0.0f,
                        
            // nastavíme počet životů na max a atribut zranitelnosti na true
            .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
            .zranitelny = true,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            // aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            // nakreslíme HUD - takový to herní menu co ukazuje počet životů, skóre a tak
            // (nám to vykresluje jenom počet životů)
            // po tom co sme vypli kameru, malujeme bez tý kamerový transformace, takže nebudem
            // mit problem trefit levej spodní vokraj vobrazovky kde si budeme malovat
            // takovou řadu srdíček který budou jakože ukazovat kolik Davidoj zbejvá životů
            
            // zrojová voblast srdička ve spritesheetu 'různé'
            const Rectangle srdicko_rect = {2,503,96,83};
            
            // srdíček budem vykreslovat v řadě za sebou furt stejnej maximální počet,
            // akorát jenom když budem vykreslovat ty který by přesahovali aktualní počet Davidovejch
            // životů, tak je budeme malovat černý
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
    
        return 0;
    }
    


    Krok dvanáct: burkinátor 🧕 ↕️

    Vyrobíme si eště jeden druh nepřátelskýho ducha, burkinátora 😮 😁. Burkinátor bude na Davida číhat v ďourách a dycky když se k němu David děsně blízko přiblíží, tak na něj burkinátor z tý díry vyletí, začně dělat takový to výhružný vejskání který hele duchové vobvykle vydávaj když třeba voslavujou terroristický utoky proti bezbranejm civilistům a poletí až někam nahoru nad vobrazovku, pak se vrátí zpátky do ďoury v zemi, kam patří 😏 😜. (Žádný další druhy duchů v tomdlectom návodu dělat nebudem, sem nechtěla dělat ani toho burkinátora původně, ale nápad se mi děsně líbil 😁 😁 Jestli ale budete hodný tak napišu ňáký pokračování a tam si vyrobíme ňáký nový druhy bubáků 😮 😜)

    Na burkinátora použijem uplně tu samou strukturu kterou už používaj duchové, dokonce použijem i stejnou vykreslovací funkci. Burkinátor se bude vod normálních duchů lišit svým 'konstruktorem' a funkcí kterou budem burkinátora aktualizovat. Je to malá změna takže si na to nebudem zakládat žádnej novej soubor a upravíme si zdrojáček souboru 'duch.h':

    #ifndef _DAVID_A_DUCHOVE_DUCH_H_
    #define _DAVID_A_DUCHOVE_DUCH_H_
    
    #include <stdlib.h>
    #include <raylib.h>
    
    #include "mapa.h"
    #include "projektily.h"
    
    extern Texture2D textura_duchove_spritesheet;
    
    extern Sound zvuk_duch_chcip;
    extern Sound zvuk_duch_strela;
    
    //přidáme si sem zvuk toho vejskání
    extern Sound zvuk_zaghrouta;
    
    #define HITPOINTU_DUCHA 3
    #define CHIPACI_CAS_DUCHA 1.5f
    #define ZASOBNIK_STREL_DUCHA 3
    #define STRILECI_COOLDOWN_DUCHA 1.0f
    #define RYCHLOST_STRELY_DUCHA 600.0f
    #define RYCHLOST_CHUZE_DUCHA 120.0f
    
    // definujem si počateční vertikální rychlost burkinátora
    #define RYCHLOST_BURKINATORA 200.0f
    
    #define DUCH_F_VYSKA 240.0f
    #define DUCH_F_SIRKA 85.0f
    
    typedef struct Duch {
        
        // směr kterým duch kouká, taky identicky řešený jako v davidoj
        int smer;
        
        // hp jakože hitpointy jakože počet životů
        int hp;
    
        Rectangle oblast_textury;
        Rectangle okraje;
        Rectangle hitbox;
    
        // jestli je duch aktivní
        // pokud neni, tak ho nebudem vykreslovat ani aktualizovat, prostě bude upně vyplej
        bool aktivni;
        
        // jestli duch chícpe, jakože mu už došly hitpointy a máme za
        bool chcipe;
    
        // vnitřní čas ducha
        float relativni_cas;
        
        // uhel ducha pro animaci efektu chcípání
        float uhel;
        
        // střílecí cooldown ducha
        float strileci_cooldown;
    
        
        // zásobnik střel ducha
        Strela * strely;
    
        // zvuky ducha
        Sound zvuk_chcipnuti;
        Sound zvuk_strela;
    }
    Duch;
    
    
    Duch * vygenerovatDucha ( Vector2 kde )
    {
    
        Duch * duch = calloc ( 1, sizeof ( Duch ) );
        if(!duch)return NULL;
        
        duch->smer = GetRandomValue( 0,1 ) ? 1 : -1;
        
        duch->okraje = ( Rectangle ) {
            kde.x,kde.y,DUCH_F_SIRKA,DUCH_F_VYSKA
        };
    
        duch->hitbox = ( Rectangle ) {
            kde.x+15,kde.y+15,55,155
        };
        
        // oblast textury určíme náhodně, vybereme uplně náhodnej podvobrázek
        duch->oblast_textury = ( Rectangle ) {
            DUCH_F_SIRKA * GetRandomValue( 0,5 ),0 + DUCH_F_VYSKA * GetRandomValue( 0,1 ),DUCH_F_SIRKA * duch->smer,DUCH_F_VYSKA
        };
        
        duch->aktivni = true;
        duch->hp = HITPOINTU_DUCHA;
        
        duch->zvuk_chcipnuti = LoadSoundAlias ( zvuk_duch_chcip );
        duch->zvuk_strela = LoadSoundAlias ( zvuk_duch_strela );
    
        duch->strely = calloc ( ZASOBNIK_STREL_DUCHA, sizeof ( Strela ) );
        if(!duch->strely)
        {
            free(duch);
            return NULL;
        }
        for ( size_t i =0; i<ZASOBNIK_STREL_DUCHA; i++ ) {
            duch->strely[i].druh = strela_ducha;
        }
        
    
        return duch;
    }
    
    // funkce na vykreslování ducha
    void vykreslitDucha ( Duch * duch )
    {
        // ducha budem vykreslovat jenom když je aktivní
        if ( !duch->aktivni ) {
            return;
        }
    
    
        // jestli duch chcípe, tak budem vykreslovat ten efekt umiraní
        if ( duch->chcipe ) {
            
            Rectangle _okraje = duch->okraje;
            const float chcipani = 1.0f - duch->relativni_cas/CHIPACI_CAS_DUCHA;
            _okraje.x += _okraje.width/2;
            _okraje.y += _okraje.height/2;
            _okraje.width *= chcipani;
            _okraje.height *= chcipani;
            
            DrawTexturePro ( textura_duchove_spritesheet,duch->oblast_textury,_okraje,
                                ( Vector2 ) { _okraje.width/2.0f,_okraje.height/2.0f},
                                duch->uhel, Fade ( WHITE, 1.0f - duch->relativni_cas/CHIPACI_CAS_DUCHA ) );
    
        } else {
            // když duch nechcípe, vykreslíme ho uplně normálně
            DrawTexturePro ( textura_duchove_spritesheet,duch->oblast_textury,duch->okraje, ( Vector2 ) {0,0},0.0f, WHITE );
        }
    
    #ifdef DEBUG
        // v připadě debugovávání vykreslíme okraje a hitbox
        DrawRectangleLines ( duch->okraje.x,duch->okraje.y, duch->okraje.width, duch->okraje.height,GREEN );
        DrawRectangleLines ( duch->hitbox.x,duch->hitbox.y, duch->hitbox.width, duch->hitbox.height,RED );
    #endif
    }
    
    // funkce na aktualizovávání ducha
    // jako argumenty bere pochopytelně ducha, pak mapu ve který se duch jakože pohybuje noa pak vobligátní časovou deltu
    void aktualizovatDucha ( Duch * duch, Mapa * mapa, float dt )
    {
    
        if ( !duch->aktivni ) {
            return;
        }
        
        if ( !duch->chcipe && duch->hp <= 0 ) {
            duch->chcipe = true;
            PlaySound ( duch->zvuk_chcipnuti );
        }
    
        if ( duch->chcipe ) {
            duch->relativni_cas += dt;
            
            duch->uhel+= dt * ( 500 + 250 * duch->relativni_cas );
            if ( duch->relativni_cas > CHIPACI_CAS_DUCHA ) {
                duch->aktivni = false;
            }
    
            return;
        }
    
        if ( GetRandomValue ( 0,1000 ) == 1 ) {
            duch->smer*=-1;
            
            duch->oblast_textury.width *= -1.0f;
        }
    
        Rectangle prepozice = duch->okraje;
        
        if ( duch->smer == 1 ) {
            
            prepozice.x += RYCHLOST_CHUZE_DUCHA * dt;
            Vector2 bod = ( Vector2 ) {
                prepozice.x + prepozice.width, prepozice.y + prepozice.height +5
            };
    
            if ( kolizeRectSeBlokemMapy ( prepozice, mapa ) || ! kolizeSeBlokemMapy_bod ( bod,mapa ) )
            {
                duch->smer *= -1;
                duch->oblast_textury.width *= -1.0f;
            } else {
                
                duch->okraje.x += RYCHLOST_CHUZE_DUCHA * dt;
                duch->hitbox.x += RYCHLOST_CHUZE_DUCHA * dt;
            }
            
    
        } else if ( duch->smer == -1 ) {
            prepozice.x -= RYCHLOST_CHUZE_DUCHA * dt;
            if ( kolizeRectSeBlokemMapy ( prepozice, mapa ) || ! kolizeSeBlokemMapy_bod ( ( Vector2 ) {
            prepozice.x, prepozice.y + prepozice.height +5
            },mapa ) ) {
                duch->smer *= -1;
                duch->oblast_textury.width *= -1.0f;
            } else {
                duch->okraje.x -= RYCHLOST_CHUZE_DUCHA * dt;
                duch->hitbox.x -= RYCHLOST_CHUZE_DUCHA * dt;
            }
        }
    
    
        if ( duch->strileci_cooldown > 0.0f ) {
            duch->strileci_cooldown-=dt;
        } else {
    
            if ( GetRandomValue ( 0,200 ) == 1 ) {
                for ( size_t i =0; i<ZASOBNIK_STREL_DUCHA; i++ ) {
                    if ( !duch->strely[i].aktivni ) {
    
                        Strela s = {
    
                            .druh = strela_ducha,
                            .rychlost = RYCHLOST_STRELY_DUCHA * ( float ) duch->smer,
                            .pozice = ( Vector2 ) { duch->smer==1 ? duch->okraje.x+DUCH_F_SIRKA/2.0f : duch->okraje.x,duch->okraje.y + 25},
                            .relativni_cas = 0.0f,
                            .doba_zivota = 2.0f,
                            .aktivni=true,
                        };
                        duch->strely[i] = s;
    
                        PlaySound ( duch->zvuk_strela );
                        duch->strileci_cooldown = STRILECI_COOLDOWN_DUCHA;
                        break;
                    }
                }
    
    
            }
        }
    
    }
    
    // 'konstruktor' burkinátora
    Duch * vygenerovatBurkinatora ( Vector2 kde )
    {
        Duch * duch = ( Duch * ) calloc ( 1, sizeof ( Duch ) );
        if(!duch)
            return NULL;
        
        // směr nám řídí jenom vykreslování textury
        // (burkinátor bude lítat zezdol nahoru, tak jakej jako směr do stran)
        duch->smer = GetRandomValue ( 0,1 ) ? 1 : -1;
        duch->okraje = ( Rectangle ) {
            kde.x,kde.y,DUCH_F_SIRKA,DUCH_F_VYSKA
        };
        duch->hitbox = ( Rectangle ) {
            kde.x+15,kde.y+15,55,160
        };
    
        // by sme burkinátora vod vostatních duchů vodlišili, tak bude mit texturu jenom ducha v burce
        // sou tam na víběr dva různý, jeden v černým hadru, druhej  v bílým
        // z tědlech dou textur si pokaždý nahodně vyberem
        const Rectangle moznosti[2]= {
            ( Rectangle ) {DUCH_F_SIRKA*3,0,DUCH_F_SIRKA,DUCH_F_VYSKA},
            ( Rectangle ) {DUCH_F_SIRKA*2,DUCH_F_VYSKA,DUCH_F_SIRKA,DUCH_F_VYSKA},
        };
        duch->oblast_textury = moznosti[GetRandomValue ( 0,1 )];
        
        duch->aktivni = true;
        duch->hp = HITPOINTU_DUCHA;
        duch->zvuk_chcipnuti = LoadSoundAlias ( zvuk_duch_chcip );
        
        // mistu zvuku střely nakopírujem alias zvuku tamtoho terroristickýho vejskání
        duch->zvuk_strela = LoadSoundAlias ( zvuk_zaghrouta );
    
    
        // burkinátor nebude mít žádný střely
        duch->strely = NULL;
    
        return duch;
    }
    
    // burkinátor nebude řešit žádný kolize s ďourama a blokama, takže voproti vobyčejnýmu duchoj nepotřebuje znát mapu
    // bude ale potřebovat znát iksovou pozici Davida, by burkinátor věděl kdy na Davida vybafnout
    void aktualizovatBurkinatora ( Duch * duch, float x_pozice_cile,  float dt )
    {
    
        if ( !duch->aktivni ) {
            return;
        }
        
        // tudle chcípací část kódu budem mit uplně stejnou jako u vobyč ducha
        if ( !duch->chcipe && duch->hp <= 0 ) {
            duch->chcipe = true;
            PlaySound ( duch->zvuk_chcipnuti );
            duch->relativni_cas = 0.0f;
        }
    
        if ( duch->chcipe ) {
            duch->relativni_cas += dt;
            duch->uhel+= dt * ( 500 + 250 * duch->relativni_cas );
            if ( duch->relativni_cas > CHIPACI_CAS_DUCHA ) {
                duch->aktivni = false;
            }
            return;
        }
    
        // pokud je pozice cíle blíž jak dýlka jeden a půl herní kostky, tak burkinátor začne letět nahoru
        // (stav, že má letět budem hlídat tim, že se kouknem jestli je burkinátorova vypsilonová souřadnice menčí než výchozí,
        // proto ten operátor 'or' s tou vejškou menčí než 960 (to ňákejch dvanáct kostek, takže spodek mapy))
        if ( fabsf ( x_pozice_cile - duch->okraje.x + duch->okraje.width/2 ) < BLOK_SIRKA*1.5 || duch->okraje.y < 959.9999f ) {
            
            // přičtem desetinu dt k relativnímu času (desetinu páč to rostlo moc rychle :D :D)
            duch->relativni_cas += dt/10;
            
            // a tim relativním časem vynasobeným rychlostí posuneme ducha nahoru
            // (děláme to takle, by burkinátor zrychloval )
            duch->okraje.y-= RYCHLOST_BURKINATORA*duch->relativni_cas;
            duch->hitbox.y = duch->okraje.y+15;
            if ( !IsSoundPlaying ( duch->zvuk_strela ) ) {
                PlaySound ( duch->zvuk_strela );
            }
        }
    
        // pokud duch vylít dostatečně vysoko, tak ho 'teleportujeme' zpátkydolu do ďoury
        // vynulujeme mu realtivní čas, vypneme zvuk vejskání noa vlastně ho necháme znova číhat na Davida
        if ( duch->okraje.y + DUCH_F_VYSKA <= -800 ) {
            duch->okraje.y = 960;
            duch->hitbox.y = duch->okraje.y+15;
            duch->relativni_cas = 0.0f;
            StopSound ( duch->zvuk_strela );
        }
    }
    
    
    // funguje i na burkinátory
    void freeDucha ( Duch * duch )
    {
        UnloadSoundAlias ( duch->zvuk_chcipnuti );
        UnloadSoundAlias ( duch->zvuk_strela );
        
        free( duch->strely );
        free ( duch );
    }
    
    #endif
    

    Aby se nám burkinátoři voběvovali na mapě, tak si je musíme ňák připsat do 'level.h', přidáme je tam uplně stejně jako sme přidávali duchy. Rozdíl voproti vobyč duchům bude jenom v aktualizaci (páč burkinátoři nestřílej) a ve spawnování burkinátorů při generování levelu (vobyč duchy generujem tak by stáli na mapě, burkinátory vygenerujem u spodku vobrazovky, necháme je trošku z ďour vykukovat by si jich hráč měl šanci všimnout) :

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    
    // zvuky
    extern Sound zvuk_zasah;
    extern Sound zvuk_kontakt;
    
    #define MAPA_MAX_VYSKA 10
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // struktura levelu
    typedef struct Level {
        
        Duch ** duchove;
        size_t pocet_duchu;
        
        // level teďko bude mit burkinátory,
        // alokujem si je stejným stylem jako předtim duchy
        Duch ** burkinatori;
        size_t pocet_burkinatoru;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        
        // alokujem si burkinátory
        Duch ** burkinatori = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        // 'Q' jako burkinátor (vono se to prej správně piše ňák s kvé jakože 'burqa' nebo jak)
        enum herniVec {N,D,B,Q};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // přidáme si tam ňáký burkinátory
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
        int seg5 [] = {
    
            0,0,0,0,0,
            B,0,Q,0,B,
        };
        int seg6 [] = {
    
            0,0,0,0,0,0,0,0,0,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,B,0,B,0,
            0,0,B,0,B,0,0,0,B,0,0,B,0,B,0,
            B,Q,B,Q,B,Q,0,Q,B,Q,0,B,Q,B,B,
        };
        int seg7 [] = {
    
            0,0,0,0,0,0,0,0,0,B,0,0,0,0,0,
            0,0,0,0,0,0,0,0,B,B,0,0,0,0,0,
            0,0,0,0,0,0,0,B,B,B,0,0,0,0,0,
            0,0,0,0,0,0,B,B,B,B,0,0,0,0,0,
            0,0,0,0,0,B,B,B,B,B,0,0,0,0,0,
            0,0,0,0,B,B,B,B,B,B,0,0,0,0,0,
            0,0,0,B,B,B,B,B,B,B,0,0,0,0,0,
            0,0,B,B,B,B,B,B,B,B,0,0,0,0,0,
            0,B,B,B,B,B,B,B,B,B,0,0,0,0,0,
            B,B,B,B,B,B,B,B,B,B,Q,Q,Q,Q,B,
        };
        int seg8 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg9 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,D,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg10 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,B,0,
            0,B,0,B,0,
            B,B,B,B,B
        };
        int seg11 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,B,0,0, 0,0,0,0,0,
            0,B,B,D,0, D,0,D,0,B,
            B,B,B,B,B, B,B,B,B,B,
        };
    
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {5,2,seg5},
            ( SegmentMapy ) {15,5,seg6},
            ( SegmentMapy ) {15,10,seg7},
            ( SegmentMapy ) {10,5,seg8},
            ( SegmentMapy ) {5,5,seg9},
            ( SegmentMapy ) {5,5,seg10},
            ( SegmentMapy ) {10,5,seg11},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
        
        // podobně jako sme si počitali normální duchy, si budem počitat burkinátory
        size_t burkinatoru = 0;
        
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            duchove[duchu++] = duch;
                        }
                        break;
                    case Q:
                        //vyrobíme burkinátora
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA + BLOK_VYSKA*3,
                            };
                            Duch * duch = vygenerovatBurkinatora ( pozice );
                            burkinatori[burkinatoru++] = duch;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            zbyva_delka-=sirka_segmentu;
        }
        
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
        // realokujem burkinátory
        burkinatori = realloc ( burkinatori, sizeof ( Duch * ) * burkinatoru );
    
        // nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
        
        // napcem tam i burkinátory
        lvl->pocet_burkinatoru = burkinatoru;
        lvl->burkinatori = burkinatori;
    
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        // musíme uvolnit i burkinátory
        for ( size_t i=0; i<lvl->pocet_burkinatoru; i++ ) {
            freeDucha ( lvl->burkinatori[i] );
        }
        free ( lvl->burkinatori );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    void aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        Strela * strely = david->strely;
        
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            if ( ! lvl->duchove[i]->chcipe )
    
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            s->aktivni = false;
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
            
            // pohlídáme si kolizi Davida s duchem, pokud se srazej tak duch Davida zraní
            // kolizi zistíme raylibí funkcí 'CheckCollisionRecs' do který nacpem hitboxy vobou herních entit
            if ( !lvl->duchove[i]->chcipe && CheckCollisionRecs ( lvl->duchove[i]->hitbox, david->hitbox ) ) {
                if ( david->zranitelny ) {
                    
                    // zahrajem zvuk kontaktu
                    // (vlastně nvm jestli to má bejt jakože zvuk co vydává duch nebo david :D )
                    PlaySound ( zvuk_kontakt );
                    
                    // vodečtem davidoj život
                    david->zivoty--;
                    
                    // nastavíme davidoj blikací čas dočasný nezranitelnosti..
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    
                    // ..a zapnem mu tu nezranitelnost
                    david->zranitelny = false;
                    
                    // pokud má ňákou vertikální rychlost směrem nahoru k hornímu vokraji vobrazkovky,
                    // tak mu ji snižime na nulu. Vono to vytváří takovej psychochologickej efekt jakože
                    // hráče ty duchové chytaj a bráněj mu v pohybu :O ;D
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
            }
    
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                    
                    // podobně jako sme hlídali zásah hitboxu ducha davidovou střelou,
                    // tak budeme klídat zásah davida střelou ducha
                    if ( CheckCollisionPointRec ( strela_ducha->pozice, david->hitbox ) ) {
                        strela_ducha->aktivni = false;
    
                        if ( david->zranitelny ) {
                            // v poctatě to samý jako při kontaktu
                            PlaySound ( zvuk_kontakt );
                            david->zivoty--;
                            david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                            david->zranitelny = false;
                        }
                    }
                }
            }
        }
        
        // vicemeně skoro uplně stejně si sem přidáme aktualizaci burkinátorů, jako sme napsali aktualizaci vobyč duchů
        for ( size_t i =0; i<lvl->pocet_burkinatoru; i++ ) {
    
            if ( fabsf ( david->pozice.x - lvl->burkinatori[i]->okraje.x ) > NUTNA_VZDALENOST )
                continue;
            
            if ( ! lvl->burkinatori[i]->chcipe )
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->burkinatori[i]->hitbox ) ) {
                            s->aktivni = false;
                            lvl->burkinatori[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                    
                }
                
                // zkusíme kolizi s davidem
                if ( david->zranitelny && CheckCollisionRecs ( lvl->burkinatori[i]->hitbox, david->hitbox ) ) {
                    PlaySound ( zvuk_kontakt );
                    david->zivoty--;
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
    
            
            aktualizovatBurkinatora ( lvl->burkinatori[i], david->pozice.x, dt );
            
        }
        
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    
        // vykreslíme burkinátory
        for ( size_t i = 0; i < lvl->pocet_burkinatoru; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->burkinatori[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->burkinatori[i] );
            }
        }
        
    }
    
    #endif
    

    V 'main.c' si akorát načteme zvuk toho strašidelnýho vejskání:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    Sound zvuk_zaghrouta;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        zvuk_zaghrouta = LoadSound ( "assets/zaghrouta.ogg" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidovy vnitřní časovače střílecího cooldownu a času blikání resp. dočasný
            // nezranitelnosti po nepřátelským zásahu ie. islamistickým duchem nebo rudou kulkou
            .strileci_cooldown = 0.0f,
            .blikaci_cas = 0.0f,
                        
            // nastavíme počet životů na max a atribut zranitelnosti na true
            .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
            .zranitelny = true,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            // aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            // aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            // nakreslíme HUD - takový to herní menu co ukazuje počet životů, skóre a tak
            // (nám to vykresluje jenom počet životů)
            // po tom co sme vypli kameru, malujeme bez tý kamerový transformace, takže nebudem
            // mit problem trefit levej spodní vokraj vobrazovky kde si budeme malovat
            // takovou řadu srdíček který budou jakože ukazovat kolik Davidoj zbejvá životů
            
            // zrojová voblast srdička ve spritesheetu 'různé'
            const Rectangle srdicko_rect = {2,503,96,83};
            
            // srdíček budem vykreslovat v řadě za sebou furt stejnej maximální počet,
            // akorát jenom když budem vykreslovat ty který by přesahovali aktualní počet Davidovejch
            // životů, tak je budeme malovat černý
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
        UnloadSound ( zvuk_zaghrouta );
    
        return 0;
    }
    


    Krok třináct: sebratelný věci ❤️ 🌟

    Přidáme si na mapu sebratelný bonusy, léčivý srdíčko a Davidovu hvězdu. Srdíčko bude léčit Davida vo jeden život, hvězda dá Davidoj dočasnou nezranitelnost a bude moct instantně potlouct duchy tim že se jich dotkne ( sem si pouštěla videjka ruznejch starodávnejch plošinovek pro inspiraci a todlecto s tou hvězdou sem tam viděla v Márijoj 😁 eště jednu věc sem tam vokoukla, uvidite asi až uplně nakonec 😁 😁)

    Ve vobligátní složšce 'src' si vytvoříme novej hlavičkovej soubor 'sebratelne.h', kde bude struktura reprezentujicí ty dva druhy sebratelnejch věcí:

    #ifndef _DAVID_A_DUCHOVE_SEBRATELNE_H_
    #define _DAVID_A_DUCHOVE_SEBRATELNE_H_
    
    #include <raylib.h>
    #include <math.h>
    #include <stdlib.h>
    
    extern Texture2D textura_ruzne;
    
    // uděláme si tam taovej jednoduchej efekt tý sebratelný věci, rotaci kolem svý vosy
    // todle je doba toho točení :O ;D
    #define CAS_ROTACE_SEBRATELNE_VECI_MAX 3.0f
    
    // budem mit dvě sebratelný věci, lečivý srdičko a magickou hvězdu
    // pro voba dva druhy věcí budem používat stejnej voběkt/strukturu.
    // By sme ale poznali, kterejže bonus z tědlech dvou má ta sebratelná věc reprezentovat,
    // tak ji to nastavíme jako jako proměnou typu enum
    // (podobně jako už nastavujem třeba druh střely)
    enum DruhSebratelneVeci {SEBRATELNE_SRDICKO, SEBRATELNA_HVEZDA};
    
    // voblasti podtextur srdička a magický hvězdy ve spritesheetu 'různé'
    const Rectangle SRDICKO_TXTOBLAST_RECT = {2,503,96,83}, HVEZDA_TXTOBLAST_RECT = {2,758,74,80};
    
    // struktura tý naší sebratelný věci
    typedef struct Sebratelne
    {
        // sebratelnej bonus musí mit ňáký vokraje, do kterejch David muže svým hitboxem vlízt a 
        // a jakoby ten bonus sebrat. Vykreslovací vobdelnik budem použivat na vykreslování efektu tý rotace
        Rectangle okraje, vykreslovaci_rect;
        
        // druh tý sebratelný věci (muže bejt srdičko nebo hvězda)
        enum DruhSebratelneVeci druh;
        
        // relativní čas
        // budem jim řídit tu rotaci vykreslovaný textury
        float relativni_cas;
        
        // voboba proměny aktivní u duchů nebo střel,
        // když bude bonus sebranej tak už ho nebudem vykreslovat ani aktualizovat
        bool sebrano;
    }
    Sebratelne;
    
    
    void aktualizovatSebratelnouVec(Sebratelne * vec, float dt)
    {
        // když už je věc Davidem sebraná tak ji nebudem aktualizovat
        if(vec->sebrano)
            return;
        
        // přičteme si deltu k relativnímu času a uděláme na něm modulo maximálním časem rotace,
        // takle zařídíme by byl náš čas furt v rosahu nula až maximální čas rotace, navíc se vyhnem
        // možnýmu přehoupnutí floatu zpátky někam na začátek až by nám třeba (nějak za strašně dlouho)
        // přetekla proměná
        // ( fmodf je funkce na dělání modula s floatama, z knihovny math.h )
        vec->relativni_cas += dt;
        vec->relativni_cas = fmodf(vec->relativni_cas, CAS_ROTACE_SEBRATELNE_VECI_MAX);
        
        // noa budem dělat rotaci toho vykreslovacího vobdelnika
        // chcem dosáhnout efektu rotace tý věci kolem svý vlastní vosy (podobně jako se točej třeba vypadlý věci v minecraftu
        // když je vyhodíme z inventáře). Toho dosáhnem tak že budem tomu vobdelniku podle uplynulýho postupně zmenčovat šiřku až
        // nebude mit vubec žádnou. Aby se nám ten vobelnik neposouval jakoby ke svýmu levýmu vokraji, tak musíme to zmenčování kompenzovat
        // vodpovidajicím posunem iksový souřadnice směrem doprava, by se jakože ten vobdelnik smrskával z vobou stran současně.
        // Noa jakmile se smrskne uplně někam na nulu, tak ho zase začnem zvěčovat.
        // Jenže chcem by se nám ta věc jakože točila kolem tý svý vosy, takže budem chtít by při tom zvěčování měl veskutečnosti zápornou
        // šířku, by se nám textura vykreslila převráceně.
        // Takže teďko sme si tu věc překlopili vo 180 stupňů, chcem ale 360 jakože uplně dokola, takže zase začnem zmenčovat ten překlopenej 
        // vobdelnik až na nulu a pak zase začnem zvěčovat vobdelnik z nuly na normální šiřku (a při tom furt kompenzovat ten iksovej posun)
        
        float pomer; // bude v rosahu -1 až 1, by sme s nim mohli překlápět šiřku vobdelnika
        
        // v první půlce času rotace budem překlápět z maximalní šiřky do minimální
        // (poměr pude pomaličku z jedničky na minus jedna)
        if(vec->relativni_cas <= CAS_ROTACE_SEBRATELNE_VECI_MAX/2)
        {
            pomer = 1.0f - (vec->relativni_cas / (CAS_ROTACE_SEBRATELNE_VECI_MAX/2))*2.0f;
        }
        
        // v druhý půlce času pudem navopak vod minus jedničky k jedničce
        else
        {        
            pomer = 1.0f - ((vec->relativni_cas - (CAS_ROTACE_SEBRATELNE_VECI_MAX/2)) / (CAS_ROTACE_SEBRATELNE_VECI_MAX/2))*2.0f;
            pomer*=-1.0f;
        }
        // (sem to takle vyifovala ale de to řešit i čistě matematikózně)
        
        vec->vykreslovaci_rect = (Rectangle){
                // absolutní hotnotou dosahnem toho že to měnění iksovýho posunu bude mit jakoby 2x víc věčí 'frekvenci' než
                // překlápětí šiřky ( za dobu jednoho uplnýho překlopení textury uděláme 2x tam a zpátky tim iksovým posunem)
                .x = vec->okraje.x + vec->okraje.width/2.0f - vec->okraje.width/2.0f * fabsf(pomer),
                .y = vec->okraje.y,
                .width = vec->okraje.width * pomer,
                .height = vec->okraje.height,
        };
    
    }
    
    
    void vykreslitSebratelnouVec(Sebratelne * vec)
    {
        if(vec->sebrano)
            return;
        // texturu sebratelný věci vyberem podle atrubutu 'druh'
        switch(vec->druh)
        {
            case SEBRATELNE_SRDICKO:
            {
                Rectangle src = SRDICKO_TXTOBLAST_RECT;
                // (raylib nechce texturu ve funkci DrawTexturePro překlápět když neni záporná šířka ve zdrojovým rectanglu 'src',
                // na překlopenou šiřku v rectanglu 'dest' neregauje, myslimže to je bug. pokud se ale pletu a ukaže se žeto je feature
                // nóó tak se ke zdrojačku vrátim a upravim ho by v aktualizovávací funkci využival src vobdelnik)
                if(vec->vykreslovaci_rect.width < 0.0f)
                {
                    vec->vykreslovaci_rect.width*=-1.0f;
                    src.width *= -1.0f;
                }
                DrawTexturePro(textura_ruzne,src,vec->vykreslovaci_rect,(Vector2){0,0},0.0f,WHITE);
                break;
            }
            case SEBRATELNA_HVEZDA:
            {
                Rectangle src = HVEZDA_TXTOBLAST_RECT;
                if(vec->vykreslovaci_rect.width < 0.0f)
                {
                    vec->vykreslovaci_rect.width*=-1.0f;
                    src.width *= -1.0f;
                }
                 DrawTexturePro(textura_ruzne,src,vec->vykreslovaci_rect,(Vector2){0,0},0.0f,WHITE);
                break;
            }
            default:
                break;
        }
        
    #ifdef DEBUG
                DrawRectangleLines(vec->okraje.x,vec->okraje.y,vec->okraje.width,vec->okraje.height,GREEN);
    #endif
    }
    
    Sebratelne * vygenerovatSebratelnouVec(Vector2 kde, enum DruhSebratelneVeci druh)
    {
        Sebratelne * s = calloc(1,sizeof(Sebratelne));
        if(!s)
            return NULL;
        
        // vejšku a šiřku sebratelný věci nastavíme na velikost jednoho bloku dlaždicový mapy
        // textury sou +- čtvercový a ňáký malý nepřesnosti se snad stratěj :O ;D
        s->okraje = (Rectangle){kde.x,kde.y,BLOK_SIRKA,BLOK_VYSKA};
        s->vykreslovaci_rect = (Rectangle){kde.x,kde.y,BLOK_SIRKA,BLOK_VYSKA};
        s->druh = druh;
        return s;
    }
    
    #endif
    

    Upravíme si Davida v souboru 'david.h', přidáme mu atributy pro ten hvězdnej bonus a upravíme aktualizovávací a vykreslovací funkci:

    #ifndef _DAVID_A_DUCHOVE_DAVID_H_
    #define _DAVID_A_DUCHOVE_DAVID_H_
    
    #include "animace.h"
    #include "mapa.h"
    #include "projektily.h"
    
    extern Sound zvuk_kroku;
    extern Sound zvuk_skoku;
    extern Sound zvuk_vystrel;
    
    // načtem si zvuk pádu kterej budem hrát dycky když nám David zahučí někam do ďoury v zemi
    extern Sound zvuk_padu;
    
    #define DAVID_F_SIRKA 150.0f
    #define DAVID_F_VYSKA 240.0f
    
    Rectangle david_framy_behu[] = {
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    };
    
    Rectangle david_framy_skoku[] = {
    
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*0,DAVID_F_SIRKA,DAVID_F_VYSKA},
    
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA}
    
    
    };
    
    Rectangle david_framy_idle[] = {
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*3,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    Rectangle david_framy_sed[] = {
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*4,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*5,DAVID_F_VYSKA*1,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*0,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*1,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*2,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
        {DAVID_F_SIRKA*3,DAVID_F_VYSKA*2,DAVID_F_SIRKA,DAVID_F_VYSKA},
    };
    
    #define RYCHLOST_CHUZE_DAVIDA 350.0f
    #define RYCHLOST_SKOKU_DAVIDA -15.0f
    #define GRAVITACE_DAVIDA 40.0f
    #define RYCHLOST_STREL_DAVIDA 800.0f
    #define STRILECI_COOLDOWN_DAVIDA 0.25f
    #define POCET_STREL_DAVIDA_MAX 32
    #define POCET_ZIVOTU_DAVIDA_MAX 10
    #define BLIKACI_CAS_DAVIDA 0.5f
    
    // maximální doba trvání bonusu
    #define HVEZDNY_CAS_DAVIDA 14.5f
    
    // bonus rychlosti chůze davida jestli sebral hvězdu
    #define HVEZDNA_RYCHLOST_CHUZE_DAVIDA 200.0f
    
    typedef struct David {
        
        Animace animace_beh;
        Animace animace_idle;
        Animace animace_sed;
        Animace animace_skok;
    
        Animace * aktualni_animace;
    
        Vector2 pozice;
        
        Rectangle okraje;
        Rectangle hitbox; 
        
        int smer;
        
        Mapa * mapa;
    
        bool zdaSkace;
        float vertikalni_rychlost;
        
        Strela * strely;
        float strileci_cooldown;
        
        int zivoty;
        
        float blikaci_cas;
        bool zranitelny;
        
        // kolik času trvání bonusu eště zbejvá
        float hvezdny_bonus_cas;
        
        // jestli má bonus
        bool ma_bonus;
    
    } David;
    
    
    void aktualizovatDavida ( David * david, float dt )
    {
    
        if ( IsKeyDown ( KEY_UP ) ) {
    
            if ( david->aktualni_animace == &david->animace_sed ) {
                david->aktualni_animace->pauznuta = false;
                david->aktualni_animace->reverzne=true;
    
                if ( david->aktualni_animace->index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
    
            } else if ( !david->zdaSkace ) {
                PlaySound ( zvuk_skoku );
                david->zdaSkace = true;
                david->animace_skok.index = 0;
                
                // jestli má david bonus tak mu zvednem rychlost skákání na 150%
                david->vertikalni_rychlost = david->ma_bonus ? RYCHLOST_SKOKU_DAVIDA*1.5f : RYCHLOST_SKOKU_DAVIDA;
            }
        }
        
        // když hráč zmáčkne mezernik, tak se David pokusí vystřelit z tý svý pistolky
        if ( IsKeyDown ( KEY_SPACE ) ) {
            // vystřelit mužeme jenom když uplynula čekací doba mezi výstřelama resp. střílecí cooldown je menší nebo rovnej nule
            if ( david->strileci_cooldown <= 0.0f ) {
                // projdeme si celej davidův zásobník a pokusíme se v něm najít střelu, kterou budeme moct použít
                // to poznáme tak, že bude mit atribut aktivní nastavenej na nulu
                for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
                    if ( !david->strely[i].aktivni ) {
                        
                        // pokud sme takovou střelu našli, tak si vybereme pro upravování atributů
                        Strela * s = david->strely + i;
    
                        // nejdřiv ji nastavíme novou polohu,
                        //to znamená přibližně někam na konec hlavně tý pistolky co má david v rukou
                        
                        //nj jenže david muže stát, sedět na zemi, muže koukat z prava doleva, nebo muže dokonce právě vstávat ze země
                        // všecky tydlecty eventualitky jakoby musíme pokrejt
                        if ( david->aktualni_animace != &david->animace_sed )
                            s->pozice = ( Vector2 ) {
                            // střelu umisťujem podle toho jakým směrem david kouká
                            david->smer==1? david->pozice.x+DAVID_F_SIRKA - 25: david->pozice.x+25,
                            david->pozice.y + DAVID_F_VYSKA/2 - 36
                        };
                        else {
                            // pokud david má jako aktuální animaci sedání, tak si zistíme index a vo ten budeme posouvat iksovou a ypsilonovou
                            // souřadnici střely. Neni to uplně přesný ale na to nikdo koukat nebude :D
                            int index = david->animace_sed.index;
                            s->pozice = ( Vector2 ) {
                                david->smer==1? david->pozice.x+DAVID_F_SIRKA - 25 - index*5: david->pozice.x+25 + index*5,david->pozice.y + DAVID_F_VYSKA/2 - 26 - 8 + index*14
                            };
    
                        }
                        
                        //polohu máme, teďko nastavíme další atributy střely
                        
                        // nastavíme střele rychlost, zohledníme i směr kterým poletí, ten vodpovídá
                        // směru kterým David právě teďko kouká
                        s->rychlost = RYCHLOST_STREL_DAVIDA * ( float ) david->smer;
                        
                        // vynulujem relativní čas
                        s->relativni_cas = 0.0f;
                        
                        // nastavíme dobu života třeba na čtyry vteřiny
                        s->doba_zivota = 4.0f;
                        
                        // a aktivujem
                        s->aktivni=true;
                        
                        // střelu máme upravenou, ukazatel už nepotřebujem
                        s=0;
    
                        // ..a když sme aktivovali střelu, tak sme vlastně vystřelili, takže nastavíme střílecí čekací dobu
                        // na maximální hodnotu
                        david->strileci_cooldown = STRILECI_COOLDOWN_DAVIDA;
                        
                        // zahrajem zvuk výstřelu
                        PlaySound ( zvuk_vystrel );
                        
                        // a přerušíme hledací for cyklus
                        break;
                    }
                }
            }
    
            if ( david->aktualni_animace != &david->animace_sed ) {
                david->aktualni_animace = & david->animace_idle;
                david->aktualni_animace->index = 0;
                david->aktualni_animace->relativni_cas = 0.0f;
            }
        }
    
    
        
        if ( IsKeyDown ( KEY_LEFT ) && david->pozice.x > 0 && david->aktualni_animace != &david->animace_sed ) {
            
            david->smer = -1;
            
            Rectangle prepozice = david->okraje;
            
            // zohledníme možnej hvězdnej bonus rychosti
            prepozice.x -= (RYCHLOST_CHUZE_DAVIDA + ( david->ma_bonus* HVEZDNA_RYCHLOST_CHUZE_DAVIDA )) * dt;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
    
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->hitbox.x = david->okraje.x + 10;
                
                david->aktualni_animace = &david->animace_beh;
                }
    
            }
        
        else if ( IsKeyDown ( KEY_RIGHT ) && david->pozice.x < david->mapa->sirka*BLOK_SIRKA - DAVID_F_SIRKA && david->aktualni_animace != &david->animace_sed ) {
    
            david->smer = 1;
            Rectangle prepozice = david->okraje;
            
            // zohledníme možnej hvězdnej bonus rychosti
            prepozice.x += (RYCHLOST_CHUZE_DAVIDA + ( david->ma_bonus* HVEZDNA_RYCHLOST_CHUZE_DAVIDA )) * dt;
            
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                david->aktualni_animace = & david->animace_idle;
            } else {
                david->okraje.x = prepozice.x;
                david->pozice.x = david->okraje.x - 45;
                david->hitbox.x = david->okraje.x + 10;
                
                david->aktualni_animace = & david->animace_beh;
                } 
        }
        // jestli je máčkutej na klávesnici čudlik šipky dolu, tak začnem přehrávat animaci sednutí
        // si na zadek
        else if ( IsKeyDown ( KEY_DOWN ) ) {
    
            david->aktualni_animace = & david->animace_sed;
            david->aktualni_animace->reverzne = false;
            david->aktualni_animace->pauznuta = false;
            }
            
        else if ( david->aktualni_animace != &david->animace_sed ) {
            david->aktualni_animace = & david->animace_idle;
            }
            
        Rectangle prepozice = david->okraje;
        prepozice.y += 5;
        if ( ! kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
            david->zdaSkace = true;
        }
    
        if ( david->zdaSkace ) {
    
            david->vertikalni_rychlost += dt * GRAVITACE_DAVIDA;
            
            Rectangle prepozice = david->okraje;
            prepozice.y += david->vertikalni_rychlost;
    
            if ( kolizeRectSeBlokemMapy ( prepozice, david->mapa ) ) {
                
                david->vertikalni_rychlost = 0.0f;
                david->zdaSkace = false;
    
                david->okraje.y =  ceil ( ( david->okraje.y + david->okraje.height  ) /BLOK_VYSKA ) * BLOK_VYSKA - david->okraje.height - 1;
    
                if ( david->aktualni_animace == &david->animace_beh ) {
                    david->aktualni_animace->index = david->animace_skok.index +5;
                    david->aktualni_animace->reverzne = david->animace_skok.reverzne;
                }
    
            } else {
                
                david->aktualni_animace = & david->animace_skok;
                
                david->okraje.y += david->vertikalni_rychlost;
    
            }
    
            // aktualizujem po dopadu taky hitbox
            david->hitbox.y = david->okraje.y + 12;
            david->pozice.y = david->okraje.y - 3;
            
    
        }
    
        david->aktualni_animace->zrcadlit = david->smer<0;
    
    
        if ( david->aktualni_animace == &david->animace_sed ) {
            
            // pokud má David jako aktualní animaci sedání, tak mu musíme nastavit hitbox podle jednotlivejch framů tý animace
            // asi to takle nebude uplně přesný, nicmeně pro náš učel to je dostatečně přesný, schvalně si zapněte v main.c DEBUG :D ;D
            david->hitbox= ( Rectangle ) {
                david->pozice.x + 55 + david->smer* ( -5*david->animace_sed.index ), david->pozice.y + 10 + 13*david->animace_sed.index, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30-13*david->animace_sed.index
            };
            
            
            if ( david->animace_sed.pauznuta ) {
                if ( david->animace_sed.index == 0 ) {
                    david->aktualni_animace = & david->animace_idle;
                }
            }
    
        }
    
        else if ( david->aktualni_animace == &david->animace_beh ) {
            if ( !IsSoundPlaying ( zvuk_kroku ) ) {
                PlaySound ( zvuk_kroku );
            }
        }
        
        if ( david->pozice.y > BLOK_VYSKA*13 ) {
            if ( !IsSoundPlaying ( zvuk_padu ) ) {
                PlaySound ( zvuk_padu );
            }
    
            david->zivoty--;
        }
        
        if ( david->aktualni_animace == &david->animace_skok && IsSoundPlaying ( zvuk_kroku ) ) {
            StopSound ( zvuk_kroku );
        }
        
        if ( david->strileci_cooldown > 0.0f ) {
            david->strileci_cooldown -= dt;
        }
        
        // pokud je davidův blikací čas věčí než nula, tak vod něj vodečtem časovou deltu
        // a uděláme Davida nezranitelnýho, páč furt eště bliká
        if ( david->blikaci_cas > 0.0f ) {
            david->blikaci_cas -= dt;
            david->zranitelny = false;
        } else {
            //ale jestli už doblikal, tak už zase zranitelnej bude
            david->zranitelny = true;
        }
        
        // jestli má david bonus tak má nejspiš i nenulovej hvězdnej čas
        // budem ho každým krokem vodečitat noa dokavaď davidoj ňákej bude eště zbejvat,
        // tak mu budem zapínat nezranitelnost (resp. vypínat zranitelnost :D)
        // noa až čas dojde tak mu vypnem ten atribut 'ma_bonus' pochopytelně :D ;D
        if ( david->ma_bonus ) {
            david->hvezdny_bonus_cas -=dt;
    
            if ( david->hvezdny_bonus_cas>0.0f ) {
                david->zranitelny = false;
            } else {
                david->ma_bonus = false;
            }
        }
        
        for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
            aktualizovatStrelu ( david->strely+i, david->mapa,dt );
        }
    
        aktualizovatAnimaci ( david->aktualni_animace, dt );
    
    }
    
    // funkce na vykreslování Davida
    void vykreslitDavida ( David * david )
    {
        // pokud je David nezranitelnej, tak bude červeně blikat
        // podělíme si blikací čas ňákým kouskem kterej nám bude určovat periodu blikání
        // tou desetinou bliknem nějak 10x za vteřinu
        
        // přidáme sem i efekt hvězdnýho bonusu, když bude mit david sebranou hvězdu, tak ho budem
        // vykreslovat žlutě. Aby ale hráč poznal že bonus brzy muže skončit, tak až zbejvajicí hvězdnej čas
        // bude třeba pětina max hodnoty, tak začne žlutě blikat (podobně jako když je raněnej, akorátže žlutě)
        if ( !david->zranitelny ) {
            Color barva;
            if ( david->ma_bonus ) {
                if ( david->hvezdny_bonus_cas > HVEZDNY_CAS_DAVIDA/5.0f ) {
                    barva = YELLOW;
                } else {
                    barva = ( int ) ( david->hvezdny_bonus_cas/0.1f ) %2 ? WHITE : YELLOW;
                }
            } else {
                barva = ( int ) ( david->blikaci_cas/0.1f ) %2 ? WHITE : RED;
            }
            vykreslitAnimaci ( david->aktualni_animace, david->pozice, barva );
        } else {
            vykreslitAnimaci ( david->aktualni_animace, david->pozice, WHITE );
        }
        
        for ( size_t i=0; i<POCET_STREL_DAVIDA_MAX; i++ ) {
            vykreslitStrelu ( david->strely+i );
        }
    
    #ifdef DEBUG
        DrawRectangleLines ( david->okraje.x, david->okraje.y, david->okraje.width, david->okraje.height, GREEN );
        // nově teďko vykreslujem červeně i ten hitbox
        DrawRectangleLines ( david->hitbox.x, david->hitbox.y, david->hitbox.width, david->hitbox.height, RED );
    #endif
    }
    
    #endif
    

    Uplně stejně jako sme si do souboru levelu 'level.h' předtim přidali duchy, si tam teďko přidáme i bonusy, eště musíme u duchů zohlednit tu kolizi se zabijáckým blikacím Davidem:

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    
    // naimportujem si ty sebratelný věci
    #include "sebratelne.h"
    
    // zvuky
    extern Sound zvuk_zasah;
    extern Sound zvuk_kontakt;
    
    // zvuk sebrání některýho toho bonusu
    extern Sound zvuk_powerup;
    
    #define MAPA_MAX_VYSKA 10
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // struktura levelu
    typedef struct Level {
        
        Duch ** duchove;
        size_t pocet_duchu;
        
        Duch ** burkinatori;
        size_t pocet_burkinatoru;
        
        // podobně jako duchy si vyrobíme i ty sebratelný věci
        Sebratelne ** sebratelne_veci;
        size_t pocet_sebratelnych_veci;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Duch ** burkinatori = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Sebratelne ** sebratelne_veci = (Sebratelne **)malloc ( sizeof ( Sebratelne * ) * 256 );
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        // 'Q' jako burkinátor (vono se to prej správně piše ňák s kvé jakože 'burqa' nebo jak)
        // 'S' jao srdičko, 'H' jako hvězda
        enum herniVec {N,D,B,Q,S,H};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // musíme si tam dát ňáký ty bonusy
        // (zatim to nemáme vybalancovaný, hvězda by asi jako měla bejt víc zácnej bonus)
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
        int seg5 [] = {
    
            0,0,0,0,0,
            B,0,Q,0,B,
        };
        int seg6 [] = {
    
            0,0,0,0,0,0,0,0,0,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,B,0,B,0,
            0,0,B,0,B,0,0,0,B,0,0,B,0,B,0,
            B,Q,B,Q,B,Q,0,Q,B,Q,0,B,Q,B,B,
        };
        int seg7 [] = {
    
            0,0,0,0,0,0,0,0,0,B,0,0,0,0,0,
            0,0,0,0,0,0,0,0,B,B,0,0,0,0,0,
            0,0,0,0,0,0,0,B,B,B,0,0,0,0,0,
            0,0,0,0,0,0,B,B,B,B,0,0,0,0,0,
            0,0,0,0,0,B,B,B,B,B,0,0,0,0,0,
            0,0,0,0,B,B,B,B,B,B,0,0,0,0,0,
            0,0,0,B,B,B,B,B,B,B,0,0,0,0,0,
            0,0,B,B,B,B,B,B,B,B,0,0,0,0,0,
            0,B,B,B,B,B,B,B,B,B,0,0,0,0,0,
            B,B,B,B,B,B,B,B,B,B,Q,Q,Q,Q,B,
        };
        int seg8 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg9 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,H,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg10 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,S,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg11 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,D,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg12 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,B,0,
            0,B,0,B,0,
            B,B,B,B,B
        };
        int seg13 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,B,0,0, 0,0,0,0,0,
            0,B,B,D,0, D,0,D,0,B,
            B,B,B,B,B, B,B,B,B,B,
        };
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {5,2,seg5},
            ( SegmentMapy ) {15,5,seg6},
            ( SegmentMapy ) {15,10,seg7},
            ( SegmentMapy ) {10,5,seg8},
            ( SegmentMapy ) {5,5,seg9},
            ( SegmentMapy ) {5,5,seg10},
            ( SegmentMapy ) {5,5,seg11},
            ( SegmentMapy ) {5,5,seg12},
            ( SegmentMapy ) {10,5,seg13},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
        size_t burkinatoru = 0;
        
        // počitat si budem i sebratelný věci pochopytelně :D ;D
        size_t sebratelnych_veci = 0;
        
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            duchove[duchu++] = duch;
                        }
                        break;
                    case Q:
                        //vyrobíme burkinátora
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA + BLOK_VYSKA*3,
                            };
                            Duch * duch = vygenerovatBurkinatora ( pozice );
                            burkinatori[burkinatoru++] = duch;
                        }
                        break;
                    case S:
                        //vyrobíme srdíčko
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNE_SRDICKO );
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    case H:
                        //vyrobíme bonusovou hvězdu
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNA_HVEZDA );
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            zbyva_delka-=sirka_segmentu;
        }
        
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
        burkinatori = realloc ( burkinatori, sizeof ( Duch * ) * burkinatoru );
        
        // realokujem i ty sebratelný věci
        sebratelne_veci = realloc ( sebratelne_veci, sizeof ( Sebratelne * ) * sebratelnych_veci );
    
        // nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
        
        // napcem tam i burkinátory
        lvl->pocet_burkinatoru = burkinatoru;
        lvl->burkinatori = burkinatori;
        
        // a nacpem tam taky bonusy
        lvl->pocet_sebratelnych_veci = sebratelnych_veci;
        lvl->sebratelne_veci = sebratelne_veci;
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        for ( size_t i=0; i<lvl->pocet_burkinatoru; i++ ) {
            freeDucha ( lvl->burkinatori[i] );
        }
        free ( lvl->burkinatori );
        
        // musíme uvolnit taky sebratelný věci
        for ( size_t i=0; i<lvl->pocet_sebratelnych_veci; i++ ) {
            free ( lvl->sebratelne_veci[i] );
        }
        free ( lvl->sebratelne_veci );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    void aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        Strela * strely = david->strely;
        
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            if ( ! lvl->duchove[i]->chcipe )
    
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            s->aktivni = false;
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
            
            // pohlídáme si kolizi Davida s duchem, pokud se srazej tak duch Davida zraní
            // kolizi zistíme raylibí funkcí 'CheckCollisionRecs' do který nacpem hitboxy vobou herních entit
            if ( !lvl->duchove[i]->chcipe && CheckCollisionRecs ( lvl->duchove[i]->hitbox, david->hitbox ) ) {
                if ( david->zranitelny ) {
                    
                    // zahrajem zvuk kontaktu
                    // (vlastně nvm jestli to má bejt jakože zvuk co vydává duch nebo david :D )
                    PlaySound ( zvuk_kontakt );
                    
                    // vodečtem davidoj život
                    david->zivoty--;
                    
                    // nastavíme davidoj blikací čas dočasný nezranitelnosti..
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    
                    // ..a zapnem mu tu nezranitelnost
                    david->zranitelny = false;
                    
                    // pokud má ňákou vertikální rychlost směrem nahoru k hornímu vokraji vobrazkovky,
                    // tak mu ji snižime na nulu. Vono to vytváří takovej psychochologickej efekt jakože
                    // hráče ty duchové chytaj a bráněj mu v pohybu :O ;D
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // přidáme si sem to zabíjení duchů tim hvězdičkovým bonusem
                else if ( david->ma_bonus ) {
                    lvl->duchove[i]->hp = 0;
                }
            }
    
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                    
                    // podobně jako sme hlídali zásah hitboxu ducha davidovou střelou,
                    // tak budeme klídat zásah davida střelou ducha
                    if ( CheckCollisionPointRec ( strela_ducha->pozice, david->hitbox ) ) {
                        strela_ducha->aktivni = false;
    
                        if ( david->zranitelny ) {
                            // v poctatě to samý jako při kontaktu
                            PlaySound ( zvuk_kontakt );
                            david->zivoty--;
                            david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                            david->zranitelny = false;
                        }
                    }
                }
            }
        }
        
        // vicemeně skoro uplně stejně si sem přidáme aktualizaci burkinátorů, jako sme napsali aktualizaci vobyč duchů
        for ( size_t i =0; i<lvl->pocet_burkinatoru; i++ ) {
    
            if ( fabsf ( david->pozice.x - lvl->burkinatori[i]->okraje.x ) > NUTNA_VZDALENOST )
                continue;
            
            if ( ! lvl->burkinatori[i]->chcipe )
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->burkinatori[i]->hitbox ) ) {
                            s->aktivni = false;
                            lvl->burkinatori[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                    
                }
                
            // zkusíme kolizi s davidem
            if( ! lvl->burkinatori[i]->chcipe && CheckCollisionRecs ( lvl->burkinatori[i]->hitbox, david->hitbox )) {
                if ( david->zranitelny ) {
                    PlaySound ( zvuk_kontakt );
                    david->zivoty--;
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // sem si taky přidáme to zabíjení burkinátorů magickou hvězdou
                else if ( david->ma_bonus ) {
                    lvl->burkinatori[i]->hp = 0;
                }
            }
    
            
            aktualizovatBurkinatora ( lvl->burkinatori[i], david->pozice.x, dt );
            
        }
        
        // a budeme aktualizovat sebratelný věci
        // kouknem jesli má věc minimální nutnou vzdálenost, jestli jo tak se kouknem jestli ji de sebrat a jestli má
        // kolizi s Davidovým hitboxem, jestli jo, tak ji David jakože sebere
        for ( size_t i = 0; i< lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( david->pozice.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                if ( !lvl->sebratelne_veci[i]->sebrano && CheckCollisionRecs ( lvl->sebratelne_veci[i]->okraje, david->hitbox ) ) {
    
                    lvl->sebratelne_veci[i]->sebrano = true;
                    PlaySound ( zvuk_powerup );
    
                    switch ( lvl->sebratelne_veci[i]->druh ) {
                    case SEBRATELNA_HVEZDA:
                        //hvězda aktivuje bonus a nastaví hvězdnej čas
                        {
                            david->ma_bonus = true;
                            david->hvezdny_bonus_cas = HVEZDNY_CAS_DAVIDA;
                        }
                        break;
                    case SEBRATELNE_SRDICKO:
                        //srdičko přidá davidoj jeden život
                        {
                            david->zivoty++;
                            // davidovy životy by asi jako možná neměli překročit maximum
                            if ( david->zivoty > POCET_ZIVOTU_DAVIDA_MAX ) {
                                david->zivoty = POCET_ZIVOTU_DAVIDA_MAX;
                            }
                        }
                        break;
                    default:
                        break;
                    }
    
                }
                aktualizovatSebratelnouVec ( lvl->sebratelne_veci[i],dt );
            }
    
        }
        
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    
        // vykreslíme burkinátory
        for ( size_t i = 0; i < lvl->pocet_burkinatoru; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->burkinatori[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->burkinatori[i] );
            }
        }
        
        // vykreslíme sebratelný věci
        for ( size_t i = 0; i < lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitSebratelnouVec ( lvl->sebratelne_veci[i] );
            }
    
        }
        
    }
    
    #endif
    

    V 'main.c' si přidáme zvuk sebrání bonusu a inicializujem Davidoj ty nový jeho atributy:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    Sound zvuk_zaghrouta;
    Sound zvuk_powerup;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        zvuk_zaghrouta = LoadSound ( "assets/zaghrouta.ogg" );
        zvuk_powerup = LoadSound ( "assets/powerup.wav" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidovy vnitřní časovače střílecího cooldownu a času blikání resp. dočasný
            // nezranitelnosti po nepřátelským zásahu ie. islamistickým duchem nebo rudou kulkou
            .strileci_cooldown = 0.0f,
            .blikaci_cas = 0.0f,
                        
            // nastavíme počet životů na max a atribut zranitelnosti na true
            .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
            .zranitelny = true,
            
            // nastavíme atributy vokolo bonusu
            .ma_bonus = false,
            .hvezdny_bonus_cas = 0.0f,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            //aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            //aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            // nakreslíme HUD - takový to herní menu co ukazuje počet životů, skóre a tak
            // (nám to vykresluje jenom počet životů)
            // po tom co sme vypli kameru, malujeme bez tý kamerový transformace, takže nebudem
            // mit problem trefit levej spodní vokraj vobrazovky kde si budeme malovat
            // takovou řadu srdíček který budou jakože ukazovat kolik Davidoj zbejvá životů
            
            // zrojová voblast srdička ve spritesheetu 'různé'
            const Rectangle srdicko_rect = {2,503,96,83};
            
            // srdíček budem vykreslovat v řadě za sebou furt stejnej maximální počet,
            // akorát jenom když budem vykreslovat ty který by přesahovali aktualní počet Davidovejch
            // životů, tak je budeme malovat černý
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
        UnloadSound ( zvuk_zaghrouta );
        UnloadSound ( zvuk_powerup );
    
        return 0;
    }
    


    Krok čtrnáct: hudba 🎼

    Chtělo by to ňákou hudbu asi 😁 😜 Zatim si tam přidáme dvě, jednu normální herní, druhou kterou pustíme dycky když bude David pod vlivem hvězdnýho bonusu (v tom márijoj to taky takle maj, když mario sebere hvězdu tak se taky dočasně přepne hudba).

    V 'main.c' si načtem hudební streamy (musej se načíst a pak uvolnit uplně stejně jako zvuky nebo textury), vytvoříme si ukazatel jakože na aktuální zvolenej hudební stream a v herním loopu ho budem aktualizovat (se předpokládá že hudemní stream je víc věčí kus paměti takže ho asi jako nebudem načítat celej soubor najednou jako třeba vobyč zvuky, ale jak už jako napovídá to slovičko 'stream' v názvu, budem ho číst z disku po malejch kouskách v řadě za sebou. Noa to načitání malejch kousků nám zařizuje v raylibu tamta funkce 'UpdateMusicStream')

    Takže si teda jako upravíme tamten 'main.c' soubor:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    Sound zvuk_zaghrouta;
    Sound zvuk_powerup;
    
    // hudby
    // máme zatim dvě, hudba_lvl jakože levelu, která bude normálně hrát na pozadí,
    // druhá je hudba která bude hrát když David sebere bonus
    Music hudba_lvl;
    Music hudba_bonus;
    
    //ukazatel na právě hranou hudbu
    Music * hudba_aktualni;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        zvuk_zaghrouta = LoadSound ( "assets/zaghrouta.ogg" );
        zvuk_powerup = LoadSound ( "assets/powerup.wav" );
        
        //načtem hudby
        hudba_lvl = LoadMusicStream ( "assets/waltz_of_the_ghosts.ogg" );
        hudba_bonus = LoadMusicStream ( "assets/for_a_few_shekels_more_band.ogg" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidovy vnitřní časovače střílecího cooldownu a času blikání resp. dočasný
            // nezranitelnosti po nepřátelským zásahu ie. islamistickým duchem nebo rudou kulkou
            .strileci_cooldown = 0.0f,
            .blikaci_cas = 0.0f,
                        
            // nastavíme počet životů na max a atribut zranitelnosti na true
            .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
            .zranitelny = true,
            
            // nastavíme atributy vokolo bonusu
            .ma_bonus = false,
            .hvezdny_bonus_cas = 0.0f,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        // nastavíme aktuální hudbu
        hudba_aktualni = &hudba_lvl;
        
        // zapnem normální hudbu levelu
        PlayMusicStream( hudba_lvl );
        
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            //aktualizujeme hudbu, na kterou ukazuje ukazatel 'hudba_aktualni'
            UpdateMusicStream ( *hudba_aktualni );
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            //aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            //aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            // nakreslíme HUD - takový to herní menu co ukazuje počet životů, skóre a tak
            // (nám to vykresluje jenom počet životů)
            // po tom co sme vypli kameru, malujeme bez tý kamerový transformace, takže nebudem
            // mit problem trefit levej spodní vokraj vobrazovky kde si budeme malovat
            // takovou řadu srdíček který budou jakože ukazovat kolik Davidoj zbejvá životů
            
            // zrojová voblast srdička ve spritesheetu 'různé'
            const Rectangle srdicko_rect = {2,503,96,83};
            
            // srdíček budem vykreslovat v řadě za sebou furt stejnej maximální počet,
            // akorát jenom když budem vykreslovat ty který by přesahovali aktualní počet Davidovejch
            // životů, tak je budeme malovat černý
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // musíme uvolnit i muziku
        UnloadMusicStream ( hudba_lvl );
        UnloadMusicStream ( hudba_bonus );
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
        UnloadSound ( zvuk_zaghrouta );
        UnloadSound ( zvuk_powerup );
    
        return 0;
    }
    

    Do souboru 'level.h' přidáme do aktualizovávací funkce levelu přepínání aktualní zvolený hudby, přepínat budem na hudbu bonusu podle toho, jestli David sebral hvězdu a vypínat podle toho jestli už nemá aktivní atribut bonusu:

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    #include "sebratelne.h"
    
    // zvuky
    extern Sound zvuk_zasah;
    extern Sound zvuk_kontakt;
    extern Sound zvuk_powerup;
    
    // zpřístupníme si sem z 'main.c' hudby a ukazatel na aktuální muziku  
    extern Music hudba_lvl;
    extern Music hudba_bonus;
    extern Music * hudba_aktualni;
    
    #define MAPA_MAX_VYSKA 10
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // struktura levelu
    typedef struct Level {
        
        Duch ** duchove;
        size_t pocet_duchu;
        
        Duch ** burkinatori;
        size_t pocet_burkinatoru;
        
        // podobně jako duchy si vyrobíme i ty sebratelný věci
        Sebratelne ** sebratelne_veci;
        size_t pocet_sebratelnych_veci;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Duch ** burkinatori = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Sebratelne ** sebratelne_veci = (Sebratelne **)malloc ( sizeof ( Sebratelne * ) * 256 );
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        // 'Q' jako burkinátor (vono se to prej správně piše ňák s kvé jakože 'burqa' nebo jak)
        // 'S' jao srdičko, 'H' jako hvězda
        enum herniVec {N,D,B,Q,S,H};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // musíme si tam dát ňáký ty bonusy
        // (zatim to nemáme vybalancovaný, hvězda by asi jako měla bejt víc zácnej bonus)
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
        int seg5 [] = {
    
            0,0,0,0,0,
            B,0,Q,0,B,
        };
        int seg6 [] = {
    
            0,0,0,0,0,0,0,0,0,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,B,0,B,0,
            0,0,B,0,B,0,0,0,B,0,0,B,0,B,0,
            B,Q,B,Q,B,Q,0,Q,B,Q,0,B,Q,B,B,
        };
        int seg7 [] = {
    
            0,0,0,0,0,0,0,0,0,B,0,0,0,0,0,
            0,0,0,0,0,0,0,0,B,B,0,0,0,0,0,
            0,0,0,0,0,0,0,B,B,B,0,0,0,0,0,
            0,0,0,0,0,0,B,B,B,B,0,0,0,0,0,
            0,0,0,0,0,B,B,B,B,B,0,0,0,0,0,
            0,0,0,0,B,B,B,B,B,B,0,0,0,0,0,
            0,0,0,B,B,B,B,B,B,B,0,0,0,0,0,
            0,0,B,B,B,B,B,B,B,B,0,0,0,0,0,
            0,B,B,B,B,B,B,B,B,B,0,0,0,0,0,
            B,B,B,B,B,B,B,B,B,B,Q,Q,Q,Q,B,
        };
        int seg8 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg9 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,H,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg10 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,S,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg11 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,D,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg12 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,B,0,
            0,B,0,B,0,
            B,B,B,B,B
        };
        int seg13 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,B,0,0, 0,0,0,0,0,
            0,B,B,D,0, D,0,D,0,B,
            B,B,B,B,B, B,B,B,B,B,
        };
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {5,2,seg5},
            ( SegmentMapy ) {15,5,seg6},
            ( SegmentMapy ) {15,10,seg7},
            ( SegmentMapy ) {10,5,seg8},
            ( SegmentMapy ) {5,5,seg9},
            ( SegmentMapy ) {5,5,seg10},
            ( SegmentMapy ) {5,5,seg11},
            ( SegmentMapy ) {5,5,seg12},
            ( SegmentMapy ) {10,5,seg13},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
        size_t burkinatoru = 0;
        
        // počitat si budem i sebratelný věci pochopytelně :D ;D
        size_t sebratelnych_veci = 0;
        
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            duchove[duchu++] = duch;
                        }
                        break;
                    case Q:
                        //vyrobíme burkinátora
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA + BLOK_VYSKA*3,
                            };
                            Duch * duch = vygenerovatBurkinatora ( pozice );
                            burkinatori[burkinatoru++] = duch;
                        }
                        break;
                    case S:
                        //vyrobíme srdíčko
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNE_SRDICKO );
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    case H:
                        //vyrobíme bonusovou hvězdu
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNA_HVEZDA );
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            zbyva_delka-=sirka_segmentu;
        }
        
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
        burkinatori = realloc ( burkinatori, sizeof ( Duch * ) * burkinatoru );
        
        // realokujem i ty sebratelný věci
        sebratelne_veci = realloc ( sebratelne_veci, sizeof ( Sebratelne * ) * sebratelnych_veci );
    
        // nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
        
        // napcem tam i burkinátory
        lvl->pocet_burkinatoru = burkinatoru;
        lvl->burkinatori = burkinatori;
        
        // a nacpem tam taky bonusy
        lvl->pocet_sebratelnych_veci = sebratelnych_veci;
        lvl->sebratelne_veci = sebratelne_veci;
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        for ( size_t i=0; i<lvl->pocet_burkinatoru; i++ ) {
            freeDucha ( lvl->burkinatori[i] );
        }
        free ( lvl->burkinatori );
        
        // musíme uvolnit taky sebratelný věci
        for ( size_t i=0; i<lvl->pocet_sebratelnych_veci; i++ ) {
            free ( lvl->sebratelne_veci[i] );
        }
        free ( lvl->sebratelne_veci );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    void aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        Strela * strely = david->strely;
        
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            if ( ! lvl->duchove[i]->chcipe )
    
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            s->aktivni = false;
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
            
            // pohlídáme si kolizi Davida s duchem, pokud se srazej tak duch Davida zraní
            // kolizi zistíme raylibí funkcí 'CheckCollisionRecs' do který nacpem hitboxy vobou herních entit
            if ( !lvl->duchove[i]->chcipe && CheckCollisionRecs ( lvl->duchove[i]->hitbox, david->hitbox ) ) {
                if ( david->zranitelny ) {
                    
                    // zahrajem zvuk kontaktu
                    // (vlastně nvm jestli to má bejt jakože zvuk co vydává duch nebo david :D )
                    PlaySound ( zvuk_kontakt );
                    
                    // vodečtem davidoj život
                    david->zivoty--;
                    
                    // nastavíme davidoj blikací čas dočasný nezranitelnosti..
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    
                    // ..a zapnem mu tu nezranitelnost
                    david->zranitelny = false;
                    
                    // pokud má ňákou vertikální rychlost směrem nahoru k hornímu vokraji vobrazkovky,
                    // tak mu ji snižime na nulu. Vono to vytváří takovej psychochologickej efekt jakože
                    // hráče ty duchové chytaj a bráněj mu v pohybu :O ;D
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // přidáme si sem to zabíjení duchů tim hvězdičkovým bonusem
                else if ( david->ma_bonus ) {
                    lvl->duchove[i]->hp = 0;
                }
            }
    
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                    
                    // podobně jako sme hlídali zásah hitboxu ducha davidovou střelou,
                    // tak budeme klídat zásah davida střelou ducha
                    if ( CheckCollisionPointRec ( strela_ducha->pozice, david->hitbox ) ) {
                        strela_ducha->aktivni = false;
    
                        if ( david->zranitelny ) {
                            // v poctatě to samý jako při kontaktu
                            PlaySound ( zvuk_kontakt );
                            david->zivoty--;
                            david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                            david->zranitelny = false;
                        }
                    }
                }
            }
        }
        
        // vicemeně skoro uplně stejně si sem přidáme aktualizaci burkinátorů, jako sme napsali aktualizaci vobyč duchů
        for ( size_t i =0; i<lvl->pocet_burkinatoru; i++ ) {
    
            if ( fabsf ( david->pozice.x - lvl->burkinatori[i]->okraje.x ) > NUTNA_VZDALENOST )
                continue;
            
            if ( ! lvl->burkinatori[i]->chcipe )
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->burkinatori[i]->hitbox ) ) {
                            s->aktivni = false;
                            lvl->burkinatori[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                    
                }
                
            // zkusíme kolizi s davidem
            if( ! lvl->burkinatori[i]->chcipe && CheckCollisionRecs ( lvl->burkinatori[i]->hitbox, david->hitbox )) {
                if ( david->zranitelny ) {
                    PlaySound ( zvuk_kontakt );
                    david->zivoty--;
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // sem si taky přidáme to zabíjení burkinátorů magickou hvězdou
                else if ( david->ma_bonus ) {
                    lvl->burkinatori[i]->hp = 0;
                }
            }
    
            
            aktualizovatBurkinatora ( lvl->burkinatori[i], david->pozice.x, dt );
            
        }
        
        // jestli David už nemá bonus ale furt je aktivní hudba bonusu,
        // tak zapnem normální hudbu levelu a nastavíme ji jako aktualní hudbu
        // (hudbu bonusu nemusíme vypínat, tim že přepnem ukazatel ji stejně nebudem aktualizovat)
        if ( !david->ma_bonus && hudba_aktualni == &hudba_bonus ) {
            PlayMusicStream ( hudba_lvl );
            hudba_aktualni = &hudba_lvl;
        }
        
        // a budeme aktualizovat sebratelný věci
        // kouknem jesli má věc minimální nutnou vzdálenost, jestli jo tak se kouknem jestli ji de sebrat a jestli má
        // kolizi s Davidovým hitboxem, jestli jo, tak ji David jakože sebere
        for ( size_t i = 0; i< lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( david->pozice.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                if ( !lvl->sebratelne_veci[i]->sebrano && CheckCollisionRecs ( lvl->sebratelne_veci[i]->okraje, david->hitbox ) ) {
    
                    lvl->sebratelne_veci[i]->sebrano = true;
                    PlaySound ( zvuk_powerup );
    
                    switch ( lvl->sebratelne_veci[i]->druh ) {
                    case SEBRATELNA_HVEZDA:
                        //hvězda aktivuje bonus a nastaví hvězdnej čas
                        {
                            david->ma_bonus = true;
                            david->hvezdny_bonus_cas = HVEZDNY_CAS_DAVIDA;
                            
                            // pauznem hudbu levelu
                            // (pozor, sou tam dvě funkce, pause stream a stop stream. Když pustíme pauznutou hudbu tak přehrávání
                            // pokračuje vod místa kde přestalo, stopnutá hraje vod začátku)
                            PauseMusicStream ( hudba_lvl );
                            
                            // přetočíme hudbu bonusu na čas vodpovidajicí 24.4 sekund
                            // ( v david.h jestli si jakoby pamatujete sme nastavovali takovej divnej čas trvání hvězdnýho bonusu.
                            // Je to kuli trvání useku hudby, kterej trvá právě vod těch 24.4 s až 24.4 + nějakejch těch čtrnáct seknud)
                            SeekMusicStream ( hudba_bonus, 24.4f );
                            
                            //začnem hrát hudbu bonusu a nastavíme na ni ukazatel aktualní hudby
                            PlayMusicStream ( hudba_bonus );
                            hudba_aktualni = &hudba_bonus;
                        }
                        break;
                    case SEBRATELNE_SRDICKO:
                        //srdičko přidá davidoj jeden život
                        {
                            david->zivoty++;
                            // davidovy životy by asi jako možná neměli překročit maximum
                            if ( david->zivoty > POCET_ZIVOTU_DAVIDA_MAX ) {
                                david->zivoty = POCET_ZIVOTU_DAVIDA_MAX;
                            }
                        }
                        break;
                    default:
                        break;
                    }
    
                }
                aktualizovatSebratelnouVec ( lvl->sebratelne_veci[i],dt );
            }
    
        }
        
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    
        // vykreslíme burkinátory
        for ( size_t i = 0; i < lvl->pocet_burkinatoru; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->burkinatori[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->burkinatori[i] );
            }
        }
        
        // vykreslíme sebratelný věci
        for ( size_t i = 0; i < lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitSebratelnouVec ( lvl->sebratelne_veci[i] );
            }
    
        }
        
    }
    
    #endif
    

    Takže zkompilujte a našponujte uši 🎶 👂 😁 😜

    Krok patnáct: parallax 🏞️

    Ten svět ve kterým se David pohybuje je takovej děsně prázdnej 😮 🙄 Přidáme na pozadí ten velkej horrorověhovorkovej velkej měsic z prvního kroku, před nim budem vykreslovat takovou texturu siluety jeruzalemskýho hradu. Texturu hradu vykreslíme trošku věčí než bude naše herní vobrazovka a budem texturou hejbat vopačným směrem, než se bude pohybovat David - když David pude doprava, budem texturou hejbat doleva, když david poleze nahoru, budem texturu posouvat dolu, Tomudlectomu triku se řiká hele 'paralaxní scrolling' prej 😮 😜.

    Tim dosáhnem iluze takovýho jakože mirně trojrozměrnýho světa, páč v normálním světě to taky takle funguje 😮 😜 Si přectavte že uhanite někam svým 6-ti válcem s uhlikovou stopou jakou má dohromady celý mladý piráctvo a protože se vam do cesty připlete nějakej vožralej strejček na kole, nevosvětlenej koloběžkář nebo tvl ňákej pitoma kolečkovejch bruslích dokonce a protože se to nedá předjet a začnete se za volantem strašně nudit a misto věnování se řízení budete z nudy koukat bokem z vokýnka (tvl ty cyklisti a jiný si neuvědomujou jak děsně moc riskujou tim svým věčným vybržďováním, jednou ňákýho zplacatim a vlastně zato ani nebudu moct 😮 😅) jak venku ubihá krajinka. Nejvíc nejrychlejc se budou pohybovat stromy někde hnedka u silnice, trošku pomalejc se budou pohybovat vod silnice trošku zdálenější věci jako třeba domečky, víc pomalej se bude hejbat hodně zdálenej les někde na kopci noa uplně pomaličku se budou hejbat hory děsně dáááááááááleko na horizontu, ty budou skoro nehejbavý. Uděláme to podobně, nejvíc nejrychlejc se bude hejbat David po herní mapě, za nim se pomalejc bude jebat ta silueta hradu noa měsic necháme statickej, páč je jakoby táák moc daleko a táák moc velikej, že se Davidovo hejbání po tý mapě na poloze měsice vubec nemuže projevit 😮 😜

    Máme jenom takovej jednoduchej parallax, nacpem ho rovnou jenom do souboru 'main.c':

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    Texture2D textura_hrad;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    Sound zvuk_zaghrouta;
    Sound zvuk_powerup;
    
    // hudby
    // máme zatim dvě, hudba_lvl jakože levelu, která bude normálně hrát na pozadí,
    // druhá je hudba která bude hrát když David sebere bonus
    Music hudba_lvl;
    Music hudba_bonus;
    
    //ukazatel na právě hranou hudbu
    Music * hudba_aktualni;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        textura_hrad = LoadTexture ( "assets/hrad2.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        zvuk_zaghrouta = LoadSound ( "assets/zaghrouta.ogg" );
        zvuk_powerup = LoadSound ( "assets/powerup.wav" );
        
        //načtem hudby
        hudba_lvl = LoadMusicStream ( "assets/waltz_of_the_ghosts.ogg" );
        hudba_bonus = LoadMusicStream ( "assets/for_a_few_shekels_more_band.ogg" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        //vygenerujeme si herní level
        level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
        
        //alokujeme si 'pole' střel pomocí funkce calloc (se vod malloc liší tim, že nám alokovanou paměť vynuluje,
        // první argument je počet alokovanejch struktur, druhej velikost jedný tý struktury)
        david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        // kdyžuž máme vyrobený animace, tak si mužeme vyrobit Davida
        David david = {
                        
            .animace_beh = david_beh,
            .animace_idle = david_idle,
            .animace_sed = david_sed,
            .animace_skok = david_skok,
             
            .aktualni_animace = NULL,
    
            // necháme ho na herní mapu spadnou z vejšky
            .pozice = {0,0},
                        
    
            .smer = 1,
            
            // nastavíme mapu na tu skovanou ve struktuře levelu
            .mapa = level->dlazdicova_mapa,
            
            .vertikalni_rychlost = 0.0f,
            .zdaSkace = true,
            
            // nastavíme ukazatel střel na ty naše callocem vygenerovaný střely
            .strely = david_strely,
                        
            //vynulujeme davidovy vnitřní časovače střílecího cooldownu a času blikání resp. dočasný
            // nezranitelnosti po nepřátelským zásahu ie. islamistickým duchem nebo rudou kulkou
            .strileci_cooldown = 0.0f,
            .blikaci_cas = 0.0f,
                        
            // nastavíme počet životů na max a atribut zranitelnosti na true
            .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
            .zranitelny = true,
            
            // nastavíme atributy vokolo bonusu
            .ma_bonus = false,
            .hvezdny_bonus_cas = 0.0f,
    
        };
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        // nastavíme aktuální hudbu
        hudba_aktualni = &hudba_lvl;
        
        // zapnem normální hudbu levelu
        PlayMusicStream( hudba_lvl );
        
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            //aktualizujeme hudbu, na kterou ukazuje ukazatel 'hudba_aktualni'
            UpdateMusicStream ( *hudba_aktualni );
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            
            //aktualizujem Davida
            aktualizovatDavida(&david, dt);
            
            //aktualizujem level
            aktualizovatLevel ( level, &david, dt );
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // první kus našeho parallaxu
            // hovorka se asi jako bojí děsně velkejch měsiců když je furt v horrorovejch komixech kreslí,
            // tak mu uděláme radost na na pozadí vykreslíme supr strašidelnej měsíc :D :D
            float mensi_rozmer = MIN ( GetRenderWidth(),GetRenderHeight() );
            DrawTexturePro ( textura_mesic, ( Rectangle ) {
                0,0,textura_mesic.width,textura_mesic.height
            }, ( Rectangle ) {
                GetRenderWidth() /2,GetRenderHeight() /2,mensi_rozmer*1.5, mensi_rozmer*1.5
            }, ( Vector2 ) {
                mensi_rozmer*1.5/2,mensi_rozmer*1.5/2
            },0, ( Color ) {
                102, 191, 255, 128
            } );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
            
            //vykreslíme parallax
    
            // to je jakože takový pozadí, který se různě pomaličku posouvá, když se hráč pohybuje na mapě a vytváří to
            // víc lepší iluzi že se hráč jakože někam pohybuje
            // todle je zatim dělaný jentak na hrubo, vykresluje to takovou siluletu jeruzalémskýho hradu která se děsně pomaličku posouvá
            // když David poskakuje nebo de dopředu
    
    
            // velikost tý textury hradu
            Rectangle hrad_zdroj = {0,0,1024,512};
            
            // cílovej vobdelnik hradu
            // uděláme ho 2x delší než je šířka vobrazovky a budem 
            // (asi to nebude moc dobře fungovat na uzkejch vobrazovkách, tam by sme asi jako museli zvolit
            // ňákej uplně jinej koncept, nvm)
            Rectangle hrad_cil = {
                .x = kamera.target.x - GetRenderWidth() /priblizeni,
                .y = kamera.target.y - GetRenderWidth() /2/priblizeni,
                // vodelnik taky bude muset bejt 2x širší než vyšší, by se nám moc nezdeformovala textura
                .width = GetRenderWidth() /priblizeni*2,
                .height = GetRenderWidth() /2/priblizeni*2,
            };
            
            // počátek/origin toho velkýho rectanglu budem určovat z mezí vobrazovky
            // musíme si pohlídat když hráč stojí u kraje mapy by nám tam nevylezla někam doprostředka vobrazovky hrana textury :D
            float hrad_y_posun_paralax = -300.0f + 300.0f * kamera.target.y/kamera_target_max_y;
            float hrad_x_posun_paralax = -GetRenderWidth() /priblizeni/2 + GetRenderWidth() /priblizeni * ( kamera.target.x - kamera_target_min_x ) /kamera_target_max_x;
    
            // noa vykreslíme ten náš parallax
            DrawTexturePro ( textura_hrad, hrad_zdroj, hrad_cil, ( Vector2 ) {
                hrad_x_posun_paralax,hrad_y_posun_paralax
            },0,WHITE );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            // nakreslíme HUD - takový to herní menu co ukazuje počet životů, skóre a tak
            // (nám to vykresluje jenom počet životů)
            // po tom co sme vypli kameru, malujeme bez tý kamerový transformace, takže nebudem
            // mit problem trefit levej spodní vokraj vobrazovky kde si budeme malovat
            // takovou řadu srdíček který budou jakože ukazovat kolik Davidoj zbejvá životů
            
            // zrojová voblast srdička ve spritesheetu 'různé'
            const Rectangle srdicko_rect = {2,503,96,83};
            
            // srdíček budem vykreslovat v řadě za sebou furt stejnej maximální počet,
            // akorát jenom když budem vykreslovat ty který by přesahovali aktualní počet Davidovejch
            // životů, tak je budeme malovat černý
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
        UnloadTexture ( textura_hrad );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // musíme uvolnit i muziku
        UnloadMusicStream ( hudba_lvl );
        UnloadMusicStream ( hudba_bonus );
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
        UnloadSound ( zvuk_zaghrouta );
        UnloadSound ( zvuk_powerup );
    
        return 0;
    }
    


    Krok šestnáct: menu a gameover 😭

    Vyrobíme si pro hru takový jednoduchý hlavní menu, vlastně to ani žádný menu nebude páč tam jenom budem čekat na máčknutí čudliku 'enter' na klávesnici. Celý to bude jakože na židovským hřbitově, vepředu se bude za náhrobkem skovávat David s flintou, na pozadí budou levitovat duchové, noa nad tim všim bude nápis s názvem tý hry a pod tim blikavej text s nápisem že má jakože hráč máčknout enter. Až hráč enter máčkne, tak se přepnem normálně do hry, respektive menu nám při máčknutí entru vygeneruje level a v tom hlavním while loopu nás pustí dál.

    Pak si taky vyrobíme ňákou uplně jednoduchou vobrazovku s textem 'game over' kterou budem zobrazovat při prohře, jakože když Davidoj dojdou všecky životy. Uděláme ji tak že budem furt vykresovat level ale už ho nebudem aktualizovat, překrejem ho ňákým černým polopruhledným smutečním vobdelnikem a přes něj vykreslíme ten text (z textury, raylib má sice možnosti rendorvat text z fontu, ale nevidim tam žádnou jednoduchou možnost ziskat budoucí rozměry vyrendrovanýho textu. Nastavit origin redrovanýmu textu de, ale neznáme ty jeho rozměry by sme ho kecli někam na správný misto, asi si to máme sami ňák vypočitat z vlastností fontu a na to sou lidi moc líný, dyď to vidite na mě, taky jako rači hnedka použiju texturu 😁 😁) a vyzvem hráče znova k máčknutí enteru. Když to udělá tak se vrátíme zpátky do toho hlavního menu.

    (raylib má prej ňákou svou knihovničku a nástroj na vyrábění gui, to bysme mohli vyzkoušet někdy příště jestli se vam tednlecten protiduchovní antiterroristickej blogisek bude libit)

    Nejdřiv si vyrobíme to menu, nóó takže zase vyrobíme novej soubor 'menu.h' v tý složšce 'src' a nacpem do něj ňákej takovejdle zdroják, kterej bude primárně sloužit k vykreslování menu (zatim takovej jakože nástřel jenom pro defaultní rozlišení, eště s tou podobou nejsem uplně spokojená a asi to celý překopu):

    #ifndef _DAVID_A_DUCHOVE_MENU_H_
    #define _DAVID_A_DUCHOVE_MENU_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    
    // budeme potřebovat hodně vobrázků
    extern Texture2D textura_duchove_spritesheet;
    extern Texture2D textura_menu_titulek;
    extern Texture2D textura_menu_pozadi;
    extern Texture2D textura_menu_pozadi2;
    extern Texture2D textura_menu_david;
    extern Texture2D textura_menu_zmackni_enter;
    
    // počet duchů vykreslenejch v menu
    // duchové maj jakoby levitovat po řbitově
    #define MENU_DUCHU 6
    
    // pro každýho ducha si budem pamatovat jeho texturu....
    Rectangle menu_duchove [MENU_DUCHU];
    
    // ....ypsilonovej posun....
    float menu_y_duchu [MENU_DUCHU];
    // ....a ypsilonovou rychlost
    float menu_rychlost_duchu [MENU_DUCHU];
    
    // pro efekt blikání textu (a vlastně i houpání Davida) si budem počítat 
    const float menu_fade_max = 100.0f;
    float menu_fade = menu_fade_max;
    
    // jestli k blikací proměný deltu přičitame nebo vodčitáme
    int menu_fade_smer=-1;
    
    void vygenerovatMenu()
    {
        // nastavíme duchům nahodnou texturu, ypsilonovou polohu i rychlost
        for ( size_t i=0; i<MENU_DUCHU; i++ ) {
            menu_duchove[i]= ( Rectangle ) {
                0 + 85 * ( rand() %6 ),0 + 240 * ( rand() %2 ),85,240
            };
            menu_y_duchu[i] = ( float ) GetRandomValue ( 250,350 );
            menu_rychlost_duchu[i] = ( float ) GetRandomValue ( 100,150 );
        }
    }
    
    void aktualizovatVykreslitMenu ( float dt )
    {
        // větší rozměr z šiřky a vyšky vobrazovky
        float vetsi_rozmer = MAX ( GetRenderWidth(),GetRenderHeight() );
        
        // vykreslíme ten fialovej řbitov na pozadí
        DrawTexturePro ( textura_menu_pozadi, ( Rectangle ) {
            0,0,textura_menu_pozadi.width,textura_menu_pozadi.height
        }, ( Rectangle ) {
            GetRenderWidth() /2,GetRenderHeight() /2,vetsi_rozmer, vetsi_rozmer
        }, ( Vector2 ) {
            vetsi_rozmer/2,vetsi_rozmer/2
        },0,WHITE );
    
        // minimálnáí a maximální vyspilonová vejška ducha
        const float min_vejska = 250.0f;
        const float max_vejska = 350.0f;
    
        // střed ypsilonový trajektorie ducha
        const float stred_y = ( max_vejska + min_vejska ) /2.0f;
        
        // maximální možná zdálenost kterou duch muže mit vod tamtoho ypsilonovýho středu tý trajektorie
        const float max_vzdalenost = max_vejska - stred_y;
        
        // šiřka a vejška ducha
        const float duch_sirka = GetRenderWidth() / ( MENU_DUCHU );
        const float duch_vyska = duch_sirka / ( 85.0f/240.0f );
    
        for ( size_t i=0; i<MENU_DUCHU; i++ ) {
    
            // aktualizace ypsilonovejch poloch a ryhclostí duchů
            // (je tam přidaný brždění podle zdálenosti vod středu tý jejich ypsilonový trajektorie by se jakože houpali plynule)
            
            menu_y_duchu[i] += ( menu_rychlost_duchu[i]/4 + menu_rychlost_duchu[i] * ( 1.0f - fabsf ( menu_y_duchu[i] - stred_y ) /max_vzdalenost ) ) *dt;
            if ( menu_y_duchu[i]>max_vejska ) {
                menu_y_duchu[i] = max_vejska;
                menu_rychlost_duchu[i]=-fabsf ( menu_rychlost_duchu[i] );
            } else if ( menu_y_duchu[i]<min_vejska ) {
                menu_y_duchu[i] = min_vejska;
                menu_rychlost_duchu[i]=fabsf ( menu_rychlost_duchu[i] );
            }
    
            DrawTexturePro (
                textura_duchove_spritesheet,
                menu_duchove[i],
                ( Rectangle ) {GetRenderWidth() / ( MENU_DUCHU ) * i,menu_y_duchu[i],duch_sirka, duch_vyska},
                ( Vector2 ) { 0,0 },0.0f, WHITE
            );
        }
        
        // vykreslíme hrobečky
        DrawTexturePro ( textura_menu_pozadi2, ( Rectangle ) {
            0,0,textura_menu_pozadi2.width,textura_menu_pozadi2.height
        }, ( Rectangle ) {
            GetRenderWidth() /2,GetRenderHeight() /2,vetsi_rozmer, vetsi_rozmer
        }, ( Vector2 ) {
            vetsi_rozmer/2,vetsi_rozmer/2
        },0,WHITE );
        
        // vykreslíme stín Davida
        // (jak stín tak i David se budou trošku houpat (měnit svuj uhel) podle tý fade proměný)
        DrawTexturePro ( textura_menu_david, ( Rectangle ) {
            0,0,textura_menu_david.width,textura_menu_david.height
        }, ( Rectangle ) {
            vetsi_rozmer/4- 40 + ( 10* ( menu_fade/menu_fade_max ) ),GetRenderHeight()+ vetsi_rozmer/8,vetsi_rozmer/2, vetsi_rozmer/2
        }, ( Vector2 ) {
            vetsi_rozmer/4,vetsi_rozmer/2
        },menu_fade/menu_fade_max * 3 - 1.5f,Fade ( BLACK,0.25f ) );
        
        // vykreslíme normálního Davida
        DrawTexturePro ( textura_menu_david, ( Rectangle ) {
            0,0,textura_menu_david.width,textura_menu_david.height
        }, ( Rectangle ) {
            vetsi_rozmer/4,GetRenderHeight()+ vetsi_rozmer/8,vetsi_rozmer/2, vetsi_rozmer/2
        }, ( Vector2 ) {
            vetsi_rozmer/4,vetsi_rozmer/2
        },menu_fade/menu_fade_max * 3 - 1.5f,WHITE );
    
        // vykreslíme titulek
        DrawTexture ( textura_menu_titulek,GetRenderWidth() /2 - textura_menu_titulek.width/2,0,WHITE );
    
        // aktualizujeme tu fadeovací proměnou
        // (asi by sme mohli nahradit sinusovkou nebo něčim a mit to hladčejší a bez tý 'směrový' proměný)
        menu_fade+=menu_fade_smer * dt * 250.0f;
        if ( menu_fade<=0.0f ) {
            menu_fade_smer = 1;
        } else if ( menu_fade>=menu_fade_max ) {
            menu_fade_smer = -1;
        }
    
        // vykreslíme nápis s tim mačkáním enteru
        DrawTexture ( textura_menu_zmackni_enter,GetRenderWidth() /2 - textura_menu_zmackni_enter.width/2,GetRenderHeight() - textura_menu_zmackni_enter.height,Fade ( WHITE,0.5f + 0.5f * menu_fade/menu_fade_max ) );
    }
    
    #endif
    

    Do 'level.h' si přidáme enum s možnejma návratovejma hodnotama funkce aktualizace levelu noa upravíme tu funkci by nám tydlecty hodnoty vracela a dávala takle vědět hlavnímu hernímu loopu co se jakože děje a jak má přepinat hudby a ty vobrazovky. Budem mit tři návratový různý hodnoty, jednu pro výhru, druhou pro prohru noa třetí pro pokračování hry. Zatim nebudem zohledňovat výhru, jenom budem vracet kód prohry když Davidoj dojdou životy, ve vostatních připadech kód pokračování hry. Takže si teda jako upravíme ten soubor 'level.h':

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    #include "sebratelne.h"
    
    // zvuky
    extern Sound zvuk_zasah;
    extern Sound zvuk_kontakt;
    extern Sound zvuk_powerup;
    
    extern Music hudba_lvl;
    extern Music hudba_bonus;
    extern Music * hudba_aktualni;
    
    #define MAPA_MAX_VYSKA 10
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // návratový stavy aktululizace levelu
    // LVL_POKRACUJE znamená že level neskončil a hraje se dál,
    // LVL_VYHRA znamená že david vyhrál,
    // LVL_PROHRA znamená že david umřel, v 'main.c' na to budem reagovat aktivováním
    // tý game over vobrazovky
    enum LevelStatus {LVL_POKRACUJE, LVL_VYHRA, LVL_PROHRA};
    
    // struktura levelu
    typedef struct Level {
        
        Duch ** duchove;
        size_t pocet_duchu;
        
        Duch ** burkinatori;
        size_t pocet_burkinatoru;
        
        // podobně jako duchy si vyrobíme i ty sebratelný věci
        Sebratelne ** sebratelne_veci;
        size_t pocet_sebratelnych_veci;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Duch ** burkinatori = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Sebratelne ** sebratelne_veci = (Sebratelne **)malloc ( sizeof ( Sebratelne * ) * 256 );
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        // 'Q' jako burkinátor (vono se to prej správně piše ňák s kvé jakože 'burqa' nebo jak)
        // 'S' jao srdičko, 'H' jako hvězda
        enum herniVec {N,D,B,Q,S,H};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // musíme si tam dát ňáký ty bonusy
        // (zatim to nemáme vybalancovaný, hvězda by asi jako měla bejt víc zácnej bonus)
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
        int seg5 [] = {
    
            0,0,0,0,0,
            B,0,Q,0,B,
        };
        int seg6 [] = {
    
            0,0,0,0,0,0,0,0,0,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,B,0,B,0,
            0,0,B,0,B,0,0,0,B,0,0,B,0,B,0,
            B,Q,B,Q,B,Q,0,Q,B,Q,0,B,Q,B,B,
        };
        int seg7 [] = {
    
            0,0,0,0,0,0,0,0,0,B,0,0,0,0,0,
            0,0,0,0,0,0,0,0,B,B,0,0,0,0,0,
            0,0,0,0,0,0,0,B,B,B,0,0,0,0,0,
            0,0,0,0,0,0,B,B,B,B,0,0,0,0,0,
            0,0,0,0,0,B,B,B,B,B,0,0,0,0,0,
            0,0,0,0,B,B,B,B,B,B,0,0,0,0,0,
            0,0,0,B,B,B,B,B,B,B,0,0,0,0,0,
            0,0,B,B,B,B,B,B,B,B,0,0,0,0,0,
            0,B,B,B,B,B,B,B,B,B,0,0,0,0,0,
            B,B,B,B,B,B,B,B,B,B,Q,Q,Q,Q,B,
        };
        int seg8 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg9 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,H,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg10 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,S,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg11 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,D,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg12 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,B,0,
            0,B,0,B,0,
            B,B,B,B,B
        };
        int seg13 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,B,0,0, 0,0,0,0,0,
            0,B,B,D,0, D,0,D,0,B,
            B,B,B,B,B, B,B,B,B,B,
        };
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {5,2,seg5},
            ( SegmentMapy ) {15,5,seg6},
            ( SegmentMapy ) {15,10,seg7},
            ( SegmentMapy ) {10,5,seg8},
            ( SegmentMapy ) {5,5,seg9},
            ( SegmentMapy ) {5,5,seg10},
            ( SegmentMapy ) {5,5,seg11},
            ( SegmentMapy ) {5,5,seg12},
            ( SegmentMapy ) {10,5,seg13},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
        size_t burkinatoru = 0;
        
        // počitat si budem i sebratelný věci pochopytelně :D ;D
        size_t sebratelnych_veci = 0;
        
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            duchove[duchu++] = duch;
                        }
                        break;
                    case Q:
                        //vyrobíme burkinátora
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA + BLOK_VYSKA*3,
                            };
                            Duch * duch = vygenerovatBurkinatora ( pozice );
                            burkinatori[burkinatoru++] = duch;
                        }
                        break;
                    case S:
                        //vyrobíme srdíčko
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNE_SRDICKO );
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    case H:
                        //vyrobíme bonusovou hvězdu
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNA_HVEZDA );
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            zbyva_delka-=sirka_segmentu;
        }
        
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
        burkinatori = realloc ( burkinatori, sizeof ( Duch * ) * burkinatoru );
        
        // realokujem i ty sebratelný věci
        sebratelne_veci = realloc ( sebratelne_veci, sizeof ( Sebratelne * ) * sebratelnych_veci );
    
        // nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
        
        // napcem tam i burkinátory
        lvl->pocet_burkinatoru = burkinatoru;
        lvl->burkinatori = burkinatori;
        
        // a nacpem tam taky bonusy
        lvl->pocet_sebratelnych_veci = sebratelnych_veci;
        lvl->sebratelne_veci = sebratelne_veci;
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
    
        return lvl;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        for ( size_t i=0; i<lvl->pocet_burkinatoru; i++ ) {
            freeDucha ( lvl->burkinatori[i] );
        }
        free ( lvl->burkinatori );
        
        // musíme uvolnit taky sebratelný věci
        for ( size_t i=0; i<lvl->pocet_sebratelnych_veci; i++ ) {
            free ( lvl->sebratelne_veci[i] );
        }
        free ( lvl->sebratelne_veci );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        free ( lvl );
    }
    
    // aktualizovatLevel teďko vrací navratovou hodnotu
    enum LevelStatus aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        Strela * strely = david->strely;
        
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            if ( ! lvl->duchove[i]->chcipe )
    
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            s->aktivni = false;
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
            
            // pohlídáme si kolizi Davida s duchem, pokud se srazej tak duch Davida zraní
            // kolizi zistíme raylibí funkcí 'CheckCollisionRecs' do který nacpem hitboxy vobou herních entit
            if ( !lvl->duchove[i]->chcipe && CheckCollisionRecs ( lvl->duchove[i]->hitbox, david->hitbox ) ) {
                if ( david->zranitelny ) {
                    
                    // zahrajem zvuk kontaktu
                    // (vlastně nvm jestli to má bejt jakože zvuk co vydává duch nebo david :D )
                    PlaySound ( zvuk_kontakt );
                    
                    // vodečtem davidoj život
                    david->zivoty--;
                    
                    // nastavíme davidoj blikací čas dočasný nezranitelnosti..
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    
                    // ..a zapnem mu tu nezranitelnost
                    david->zranitelny = false;
                    
                    // pokud má ňákou vertikální rychlost směrem nahoru k hornímu vokraji vobrazkovky,
                    // tak mu ji snižime na nulu. Vono to vytváří takovej psychochologickej efekt jakože
                    // hráče ty duchové chytaj a bráněj mu v pohybu :O ;D
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // přidáme si sem to zabíjení duchů tim hvězdičkovým bonusem
                else if ( david->ma_bonus ) {
                    lvl->duchove[i]->hp = 0;
                }
            }
    
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                    
                    // podobně jako sme hlídali zásah hitboxu ducha davidovou střelou,
                    // tak budeme klídat zásah davida střelou ducha
                    if ( CheckCollisionPointRec ( strela_ducha->pozice, david->hitbox ) ) {
                        strela_ducha->aktivni = false;
    
                        if ( david->zranitelny ) {
                            // v poctatě to samý jako při kontaktu
                            PlaySound ( zvuk_kontakt );
                            david->zivoty--;
                            david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                            david->zranitelny = false;
                        }
                    }
                }
            }
        }
        
        // vicemeně skoro uplně stejně si sem přidáme aktualizaci burkinátorů, jako sme napsali aktualizaci vobyč duchů
        for ( size_t i =0; i<lvl->pocet_burkinatoru; i++ ) {
    
            if ( fabsf ( david->pozice.x - lvl->burkinatori[i]->okraje.x ) > NUTNA_VZDALENOST )
                continue;
            
            if ( ! lvl->burkinatori[i]->chcipe )
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->burkinatori[i]->hitbox ) ) {
                            s->aktivni = false;
                            lvl->burkinatori[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                    
                }
                
            // zkusíme kolizi s davidem
            if( ! lvl->burkinatori[i]->chcipe && CheckCollisionRecs ( lvl->burkinatori[i]->hitbox, david->hitbox )) {
                if ( david->zranitelny ) {
                    PlaySound ( zvuk_kontakt );
                    david->zivoty--;
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // sem si taky přidáme to zabíjení burkinátorů magickou hvězdou
                else if ( david->ma_bonus ) {
                    lvl->burkinatori[i]->hp = 0;
                }
            }
    
            
            aktualizovatBurkinatora ( lvl->burkinatori[i], david->pozice.x, dt );
            
        }
        
        // jestli David už nemá bonus ale furt je aktivní hudba bonusu,
        // tak zapnem normální hudbu levelu a nastavíme ji jako aktualní hudbu
        // (hudbu bonusu nemusíme vypínat, tim že přepnem ukazatel ji stejně nebudem aktualizovat)
        if ( !david->ma_bonus && hudba_aktualni == &hudba_bonus ) {
            PlayMusicStream ( hudba_lvl );
            hudba_aktualni = &hudba_lvl;
        }
        
        // a budeme aktualizovat sebratelný věci
        // kouknem jesli má věc minimální nutnou vzdálenost, jestli jo tak se kouknem jestli ji de sebrat a jestli má
        // kolizi s Davidovým hitboxem, jestli jo, tak ji David jakože sebere
        for ( size_t i = 0; i< lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( david->pozice.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                if ( !lvl->sebratelne_veci[i]->sebrano && CheckCollisionRecs ( lvl->sebratelne_veci[i]->okraje, david->hitbox ) ) {
    
                    lvl->sebratelne_veci[i]->sebrano = true;
                    PlaySound ( zvuk_powerup );
    
                    switch ( lvl->sebratelne_veci[i]->druh ) {
                    case SEBRATELNA_HVEZDA:
                        //hvězda aktivuje bonus a nastaví hvězdnej čas
                        {
                            david->ma_bonus = true;
                            david->hvezdny_bonus_cas = HVEZDNY_CAS_DAVIDA;
                            
                            // pauznem hudbu levelu
                            // (pozor, sou tam dvě funkce, pause stream a stop stream. Když pustíme pauznutou hudbu tak přehrávání
                            // pokračuje vod místa kde přestalo, stopnutá hraje vod začátku)
                            PauseMusicStream ( hudba_lvl );
                            
                            // přetočíme hudbu bonusu na čas vodpovidajicí 24.4 sekund
                            // ( v david.h jestli si jakoby pamatujete sme nastavovali takovej divnej čas trvání hvězdnýho bonusu.
                            // Je to kuli trvání useku hudby, kterej trvá právě vod těch 24.4 s až 24.4 + nějakejch těch čtrnáct seknud)
                            SeekMusicStream ( hudba_bonus, 24.4f );
                            
                            //začnem hrát hudbu bonusu a nastavíme na ni ukazatel aktualní hudby
                            PlayMusicStream ( hudba_bonus );
                            hudba_aktualni = &hudba_bonus;
                        }
                        break;
                    case SEBRATELNE_SRDICKO:
                        //srdičko přidá davidoj jeden život
                        {
                            david->zivoty++;
                            // davidovy životy by asi jako možná neměli překročit maximum
                            if ( david->zivoty > POCET_ZIVOTU_DAVIDA_MAX ) {
                                david->zivoty = POCET_ZIVOTU_DAVIDA_MAX;
                            }
                        }
                        break;
                    default:
                        break;
                    }
    
                }
                aktualizovatSebratelnouVec ( lvl->sebratelne_veci[i],dt );
            }
    
        }
        
        // jestli David nemá žádný životy tak prohrál,
        // jinak pokračujem ve hře
        if ( david->zivoty <= 0 ) {
            return LVL_PROHRA;
        }
    
        return LVL_POKRACUJE;
        
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    
        // vykreslíme burkinátory
        for ( size_t i = 0; i < lvl->pocet_burkinatoru; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->burkinatori[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->burkinatori[i] );
            }
        }
        
        // vykreslíme sebratelný věci
        for ( size_t i = 0; i < lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitSebratelnouVec ( lvl->sebratelne_veci[i] );
            }
    
        }
        
    }
    
    #endif
    

    V 'main.c' si načtem novou hudbu pro gameover (je to budoucí hymna uzemí v současnosti dočasně kotrolovanýho samozvaným separatistickým barbarským terroristickým pseudostátem palestina 😛 😛) a zohledníme ty návratový hodnoty z funkce na aktualizovávání levelu. Přidáme si tam přepínání a vykreslování tří takovejch jakože pomyslnejch vobrazovek, jedna bude to hlavní menu, druhá hra a třetí gameover, držet to budem taky v ňákým enum a přepínat vobrazovku budem právě tou návratovou hodnotou aktualizace levelu. Screen management je uplně primitivní, sem přidala ňáký tři ify do hlavního loopu, takle naprasit to je možný že máme ty vobrazovky jednoduchoučký aže jich je málo. Jestli máme jakože v týdlectý hře ňák pokračovat tak asi jako dobudoucna budem potřebovat ňákej jakože víc lepčejší system vobrazovek a jejich přepinání.

    Takže teda jako nová podoba 'main.c' je takovádlenc:

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    #include "menu.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // přidáme si enum popisující na který vobrazovce jakože sme,
    // jestli tý s menu, tý s herním levelem nebo tý s game over
    enum KteraObrazovka {OBRAZOVKA_HLAVNI_MENU, OBRAZOVKA_HRA, OBRAZOVKA_GAME_OVER};
    
    enum KteraObrazovka obrazovka = OBRAZOVKA_HLAVNI_MENU;
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    Texture2D textura_hrad;
    
    //textury menu a 'gui' prvků
    Texture2D textura_menu_titulek;
    Texture2D textura_menu_pozadi;
    Texture2D textura_menu_pozadi2;
    Texture2D textura_menu_game_over;
    Texture2D textura_menu_zmackni_enter;
    Texture2D textura_menu_david;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    Sound zvuk_zaghrouta;
    Sound zvuk_powerup;
    
    // hudby
    Music hudba_lvl;
    Music hudba_bonus;
    
    // přidáme si hudby pro menu a game over
    Music hudba_menu;
    Music hudba_game_over;
    
    //ukazatel na právě hranou hudbu
    Music * hudba_aktualni;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        textura_hrad = LoadTexture ( "assets/hrad2.png" );
        textura_menu_titulek = LoadTexture ( "assets/title.png" );
        textura_menu_pozadi = LoadTexture ( "assets/gy.png" );
        textura_menu_pozadi2 = LoadTexture ( "assets/gy_hroby.png" );
        textura_menu_game_over = LoadTexture ( "assets/game_over.png" );
        textura_menu_zmackni_enter = LoadTexture ( "assets/zmackni_enter.png" );
        textura_menu_david = LoadTexture ( "assets/koli.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        zvuk_zaghrouta = LoadSound ( "assets/zaghrouta.ogg" );
        zvuk_powerup = LoadSound ( "assets/powerup.wav" );
        
        //načtem hudby
        hudba_lvl = LoadMusicStream ( "assets/waltz_of_the_ghosts.ogg" );
        hudba_bonus = LoadMusicStream ( "assets/for_a_few_shekels_more_band.ogg" );
        hudba_menu = LoadMusicStream ( "assets/ghost_trip.ogg" );
        hudba_game_over = LoadMusicStream ( "assets/hatikva.ogg" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        David david;
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        // nastavíme aktuální hudbu na hudbu menu
        hudba_aktualni = &hudba_menu;
        
        //vygenerujem si hlavní menu a zapnem vodpovidajicí muziku
        vygenerovatMenu();
        PlayMusicStream ( hudba_menu );
        
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            //aktualizujeme hudbu, na kterou ukazuje ukazatel 'hudba_aktualni'
            UpdateMusicStream ( *hudba_aktualni );
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            if ( obrazovka == OBRAZOVKA_HLAVNI_MENU ) {
                BeginDrawing();
                // GetRenderHeight a GetRenderWidth je skoro to samý co GetScreenHeight a GetScreenWidth jenom s tim rozdílem
                // že to započitává DPI hele https://cs.wikipedia.org/wiki/DPI, jakože počet pixelů na jednotku délky
                // (na vobyčejným počitači nás to asi nemusí moc trápit, na mobilním zařizení by to ale bylo zásadní)
                DrawRectangleGradientV ( 0,0,GetRenderWidth(),GetRenderHeight(),DARKBLUE,BLACK );
    
                //aktualizujeme a vykreslíme menu
                aktualizovatVykreslitMenu ( dt );
                EndDrawing();
    
                if ( IsKeyPressed ( KEY_ENTER ) ) {
    
                    // pokud ukazatel na strukturu level neni vynulovanej, tak to pravděpodobně znamená že se už jednou hrálo a
                    // že musíme starej level uklidit by sme mohli vygenerovat novej
                    if ( level != NULL ) {
                        freeLevel ( level );
                        
                        // uklidíme i střely, idkyž by asi jako bylo víc lepčejší každý prostě nastavit atribut 'aktivni' na false :D
                        free ( david_strely );
                    }
                    
                    //vygenerujeme si herní level
                    level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
    
    
                    david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
                    
                    //inicializujeme si davida
                    david = (David){
                        
                        .animace_beh = david_beh,
                        .animace_idle = david_idle,
                        .animace_sed = david_sed,
                        .animace_skok = david_skok,
                        .aktualni_animace = NULL,
                        .pozice = {0,0},
                        .smer = 1,
                        .mapa = level->dlazdicova_mapa,
                        .vertikalni_rychlost = 0.0f,
                        .zdaSkace = true,
                        .strely = david_strely,
                        .strileci_cooldown = 0.0f,
                        .blikaci_cas = 0.0f,
                        .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
                        .zranitelny = true,
                        .ma_bonus = false,
                        .hvezdny_bonus_cas = 0.0f,
    
                    };
    
                    //nastavíme ukazatel aktuální animace na animaci 'idle'
                    david.aktualni_animace = &david.animace_idle;
                    
                    //podle aktuální pozice nastavíme okraje oběktu a hitbox
                    david.okraje = ( Rectangle ) {
                        david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
                    };
                    david.hitbox = ( Rectangle ) {
                        david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
                    };
    
                    //vypnem hudbu menu
                    StopMusicStream ( hudba_menu );
                    
                    // vypnem hudbu levelu (by sme ji restartovali aby nám nehrála třeba někde vodprostředka)
                    StopMusicStream ( hudba_lvl );
                    
                    // zapnem hudbu levelu
                    PlayMusicStream ( hudba_lvl );
                    
                    // a nastavíme jeji adresu do ukazatele na aktuální hudbu, by se nám muzika taky aktualizovala, bez  toho by nehrála :D
                    hudba_aktualni = &hudba_lvl;
                    
                    //nakonec přepnem vobrazovku
                    obrazovka = OBRAZOVKA_HRA;
                }
    
                // vykreslujem menu, takže nás další věci nezajímaj a přeskočíme je tim, že skočíme na začátek dalšího while cyklusu
                continue;
            }
            
            
            if ( obrazovka == OBRAZOVKA_HRA ) {
    
                // aktualizujem davida
                // funkce žere ukazatel, takže davida tam nacpem tak, že tam strčíme jeho adresu
                aktualizovatDavida ( &david, dt );
                
                // aktualizujem level
                enum LevelStatus status = aktualizovatLevel ( level, &david, dt );
    
                // podle návratový hodnoty určíme, jesttli se hraje dál nebo jestli nám David umřel a musíme
                // přepnout na 'game over' nebo jestli vyhrál a musíme se vrátit zpátky do hlavního menu
                // (ve finální verzi tý hry by sme asi měli mit ňáký hi-score nebo tak něco)
                // jenom tady přepínáme muziku a aktualní 'vobrazovku'
                if ( status == LVL_PROHRA ) {
                    obrazovka = OBRAZOVKA_GAME_OVER;
                    StopMusicStream ( hudba_lvl );
                    StopMusicStream ( hudba_bonus );
                    PlayMusicStream ( hudba_game_over );
                    hudba_aktualni = &hudba_game_over;
    
                } else if ( status == LVL_VYHRA ) {
                    StopMusicStream ( hudba_lvl );
                    StopMusicStream ( hudba_bonus );
    
                    PlayMusicStream ( hudba_menu );
                    hudba_aktualni = &hudba_menu;
                    obrazovka = OBRAZOVKA_HLAVNI_MENU;
    
                }
            }
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // první kus našeho parallaxu
            // hovorka se asi jako bojí děsně velkejch měsiců když je furt v horrorovejch komixech kreslí,
            // tak mu uděláme radost na na pozadí vykreslíme supr strašidelnej měsíc :D :D
            float mensi_rozmer = MIN ( GetRenderWidth(),GetRenderHeight() );
            DrawTexturePro ( textura_mesic, ( Rectangle ) {
                0,0,textura_mesic.width,textura_mesic.height
            }, ( Rectangle ) {
                GetRenderWidth() /2,GetRenderHeight() /2,mensi_rozmer*1.5, mensi_rozmer*1.5
            }, ( Vector2 ) {
                mensi_rozmer*1.5/2,mensi_rozmer*1.5/2
            },0, ( Color ) {
                102, 191, 255, 128
            } );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
            
            //vykreslíme parallax
    
            // to je jakože takový pozadí, který se různě pomaličku posouvá, když se hráč pohybuje na mapě a vytváří to
            // víc lepší iluzi že se hráč jakože někam pohybuje
            // todle je zatim dělaný jentak na hrubo, vykresluje to takovou siluletu jeruzalémskýho hradu která se děsně pomaličku posouvá
            // když David poskakuje nebo de dopředu
    
    
            // velikost tý textury hradu
            Rectangle hrad_zdroj = {0,0,1024,512};
            
            // cílovej vobdelnik hradu
            // uděláme ho 2x delší než je šířka vobrazovky a budem 
            // (asi to nebude moc dobře fungovat na uzkejch vobrazovkách, tam by sme asi jako museli zvolit
            // ňákej uplně jinej koncept, nvm)
            Rectangle hrad_cil = {
                .x = kamera.target.x - GetRenderWidth() /priblizeni,
                .y = kamera.target.y - GetRenderWidth() /2/priblizeni,
                // vodelnik taky bude muset bejt 2x širší než vyšší, by se nám moc nezdeformovala textura
                .width = GetRenderWidth() /priblizeni*2,
                .height = GetRenderWidth() /2/priblizeni*2,
            };
            
            // počátek/origin toho velkýho rectanglu budem určovat z mezí vobrazovky
            // musíme si pohlídat když hráč stojí u kraje mapy by nám tam nevylezla někam doprostředka vobrazovky hrana textury :D
            float hrad_y_posun_paralax = -300.0f + 300.0f * kamera.target.y/kamera_target_max_y;
            float hrad_x_posun_paralax = -GetRenderWidth() /priblizeni/2 + GetRenderWidth() /priblizeni * ( kamera.target.x - kamera_target_min_x ) /kamera_target_max_x;
    
            // noa vykreslíme ten náš parallax
            DrawTexturePro ( textura_hrad, hrad_zdroj, hrad_cil, ( Vector2 ) {
                hrad_x_posun_paralax,hrad_y_posun_paralax
            },0,WHITE );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            
            const Rectangle srdicko_rect = {2,503,96,83};
            
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
            
            // 'obrazovka' game over
            if ( obrazovka == OBRAZOVKA_GAME_OVER ) {
                // pokud david umře, tak už nebudeme herní věci aktualizovat ale budem je furt vykreslovat
                // všecko překryjeme smutečním černým poloprusvitným vobdelnikem....
                DrawRectangle ( 0,0,GetRenderWidth(),GetRenderHeight(), ( Color ) {
                    0,0,0,128
                } );
                // .... přes kterej namalujeme velkej zelenej text s nápisem 'game over'....
                DrawTexture ( textura_menu_game_over,GetRenderWidth() /2 - textura_menu_game_over.width/2,GetRenderHeight() /3 - textura_menu_game_over.height/2,WHITE );
                // ....a textem, že má hráč zmáčknout na klávesnici čudlik 'enter'
                DrawTexture ( textura_menu_zmackni_enter,GetRenderWidth() /2 - textura_menu_zmackni_enter.width/2,GetRenderHeight() - textura_menu_zmackni_enter.height,WHITE );
    
                if ( IsKeyPressed ( KEY_ENTER ) ) {
                    // noa když ten čudlik hráč zmáčkne, tak přepnem muziku, a přepnem vobrazovku
                    StopMusicStream ( hudba_game_over );
                    PlayMusicStream ( hudba_menu );
                    hudba_aktualni = &hudba_menu;
                    obrazovka = OBRAZOVKA_HLAVNI_MENU;
                }
    
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
        UnloadTexture ( textura_hrad );
        UnloadTexture ( textura_menu_titulek );
        UnloadTexture ( textura_menu_pozadi );
        UnloadTexture ( textura_menu_pozadi2 );
        UnloadTexture ( textura_menu_david );
        UnloadTexture ( textura_ruzne );
        UnloadTexture ( textura_menu_zmackni_enter );
        UnloadTexture ( textura_menu_game_over );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // musíme uvolnit i muziku
        UnloadMusicStream ( hudba_lvl );
        UnloadMusicStream ( hudba_bonus );
        UnloadMusicStream ( hudba_menu );
        UnloadMusicStream ( hudba_game_over );
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
        UnloadSound ( zvuk_zaghrouta );
        UnloadSound ( zvuk_powerup );
    
        return 0;
    }
    


    Krok sedumnáct: vítězství a izraelckej praporek nad Jeruzalémem 🫡 🇮🇱!!!!

    Jako prozatim poslední krok si přidáme ňáký Davidovo možný vítězství nad duchama. V tom márijoj sem viděla uplně supr věc co se nám hodí přesně nakonec herního levelu: totiž že mário dělá když doběhne na konec herní mapy tak tam je dycky na stožáru vlajka asi ňákýho hlavníh zlýho, noa mário vyskočí a tu vlajku strhne a nahradí ji praporkem se svým vlastním xiftem 😮 😁 My uděláme taky vyměnu praporku, na konec mapy si přidáme stožár na kterým bude pověšená terroristická vlajka noa když se David toho vlajkovýho stojanu dotkne svým hitboxem, tak handru nahradíme poctivou vlajkou státu Izrael (v ňákým možným budoucím kroku by sme si pak mohli udělat aby ta terroristická handra eště hořela až pojede z toho stojanu dolu)

    Vyrobíme si ve složšce 'src' novej soubor 'stojan.h' a nacpem tam tendlecten kód:

    #ifndef _DAVID_A_DUCHOVE_STOJAN_H_
    #define _DAVID_A_DUCHOVE_STOJAN_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    
    extern Texture2D textura_ruzne;
    
    // jak dlouho bude na stojanu trvat vyměna vlajky
    #define PREVLAJKOVAVACI_CAS_STOJANU 2.0f
    
    // voblasti textur stojanu a vlajek v textuře 'různé'
    const Rectangle ISRA_VLAJKA_RECT = (Rectangle){2,590,160,80};
    const Rectangle BUBU_VLAJKA_RECT = (Rectangle){2,674,160,80};
    const Rectangle STOJAN_RECT = (Rectangle){2,2,18,497};
    
    typedef struct Stojan
    {
        Rectangle okraje;
        
        // vobdelniky popsiujicí polohu a voblast vobou vlajek
        Rectangle vlajka_puvodni, vlajka_nova;
        
        float relativni_cas;
        
        // stojan bude mit vlastně jakoby tři stavy, defaultní, kdy na něm
        // bude plandat bubu vlajka, pak ňákej přechodnej kdy se dole voběví
        // nová vlajka a začnou se vyměňovat,
        // noa pak ňákej třetí stav, kdy už ta změna jakoby dojede do konce
        // ty tři stavy popišem dvouma boolama (pokud sou voba false tak platí jakoby ten třetí stav) 
        bool prevlajkovava_se, uz_se_prevlajkoval_uplne;
        
    }
    Stojan;
    
    Stojan * vygenerovatStojan(Vector2 kde)
    {
        Stojan * s = calloc(1,sizeof(Stojan));
        if(!s) return NULL;
        
        s->okraje = (Rectangle){kde.x,kde.y - STOJAN_RECT.height,STOJAN_RECT.width,STOJAN_RECT.height};
        s->vlajka_puvodni = (Rectangle){kde.x + STOJAN_RECT.width/2.0f, kde.y - STOJAN_RECT.height,BUBU_VLAJKA_RECT.width,BUBU_VLAJKA_RECT.height};
        s->vlajka_nova = (Rectangle){kde.x + STOJAN_RECT.width/2.0f, kde.y - STOJAN_RECT.height,ISRA_VLAJKA_RECT.width,ISRA_VLAJKA_RECT.height};
        
        return s;
    }
    
    void aktualizovatStojan(Stojan * stojan, float dt)
    {
        // stojan budem aktualizovat jenom když se mění vlajka, až se vymění,
        // tak už aktualizovat nebudem
        if(!stojan->prevlajkovava_se || stojan->uz_se_prevlajkoval_uplne)
            return;
        
        // jestli už uplynul převlajkovávací čas tak se stojan určitě převlajkoval
        float progress = stojan->relativni_cas/PREVLAJKOVAVACI_CAS_STOJANU;
        if(progress>1.0f)
        {
            progress = 1.0f;
            stojan->prevlajkovava_se = false;
            stojan->uz_se_prevlajkoval_uplne = true;
            
        }
        
        // vlajky budem posouvat tou pomocnou normalizovanou hodnotou progress, prostě tim čislem
        // vynásobíme vejšku ve který tu vlajku chcem, jednu vlajku budem pronásobovat rovnou, drhuou převrácenou hodnotou
        stojan->vlajka_puvodni.y = (STOJAN_RECT.height - BUBU_VLAJKA_RECT.height) * (progress) + stojan->okraje.y;
        stojan->vlajka_nova.y = (STOJAN_RECT.height - ISRA_VLAJKA_RECT.height) * (1.0f - progress) + stojan->okraje.y;
        
        
        stojan->relativni_cas += dt;
        
        
    }
    
    void vykreslitStojan(Stojan * stojan)
    {
        DrawTexturePro(textura_ruzne,STOJAN_RECT,stojan->okraje,(Vector2){0,0},0.0f,DARKBLUE);
        
        // stará vlajka muže bejt vidět jenom dokavaď se stojan uplně nepřevlajkoval
        if(!stojan->uz_se_prevlajkoval_uplne)
        {
            DrawTexturePro(textura_ruzne,BUBU_VLAJKA_RECT,stojan->vlajka_puvodni,(Vector2){0,0},0.0f,SKYBLUE);
        }
        // nová vlajka muže bejt logicky vidět jenom když se stojan převlajkovává nebo už celej převlajkoval
        if(stojan->prevlajkovava_se || stojan->uz_se_prevlajkoval_uplne)
        {
            DrawTexturePro(textura_ruzne,ISRA_VLAJKA_RECT,stojan->vlajka_nova,(Vector2){0,0},0.0f,SKYBLUE);
        }
    }
    
    #endif
    

    V 'level.h' si vyrobíme ten stojan někde u konce herní mapy a v aktualizaci levelu budem hlídat to převlajkovávání, když se s nim začne tak sopnem muziku, zahrajem vitěznou znělku a až převlakovávání skončí tak se vrátíme zpátky do hlavního menu (eště tam zapošiju možnej leak při selhání konstruktorů. Sem to chtěla puvodně nechat bejt a zavtipkovat že to necháme na zdejších autistech který se nato asi jako nevydržej koukat noa nakonec to ani sama nevydržim a musim to ňák zapošít :'D 😁 😁 😜) :

    #ifndef _DAVID_A_DUCHOVE_LEVEL_H_
    #define _DAVID_A_DUCHOVE_LEVEL_H_
    
    #include <raylib.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include "mapa.h"
    #include "david.h"
    #include "duch.h"
    #include "sebratelne.h"
    
    // přidáme si stojan
    #include "stojan.h"
    
    // zvuky
    extern Sound zvuk_zasah;
    extern Sound zvuk_kontakt;
    extern Sound zvuk_powerup;
    
    // zvuk pro výhru
    extern Sound zvuk_vyhra;
    
    extern Music hudba_lvl;
    extern Music hudba_bonus;
    extern Music * hudba_aktualni;
    
    #define MAPA_MAX_VYSKA 10
    #define NUTNA_VZDALENOST (BLOK_SIRKA * 20)
    
    // návratový stavy aktululizace levelu
    enum LevelStatus {LVL_POKRACUJE, LVL_VYHRA, LVL_PROHRA};
    
    // struktura levelu
    typedef struct Level {
        
        Duch ** duchove;
        size_t pocet_duchu;
        
        Duch ** burkinatori;
        size_t pocet_burkinatoru;
        
        Sebratelne ** sebratelne_veci;
        size_t pocet_sebratelnych_veci;
        
        // level bude vobsahovat jednu instanci stojanu
        Stojan * stojan;
    
        Mapa * dlazdicova_mapa;
    
    } Level;
    
    typedef struct SegmentMapy {
        int sirka;
        int vyska;
        int  * pole;
    } SegmentMapy;
    
    
    // funkce na vygenerování náhodnýho levelu, vlastně něco jako konstruktor
    // první argument 'šiřka' je počet kostek jak má bejt level dlouhej (předpokládá se čislo věčí dvacíti a dělitelný pěti)
    // druhej textura tý dlaždicový mapy
    Level * vygenerovatLevel ( int sirka, Texture2D texturaTiledMapy )
    {
        Level * lvl = (Level * )malloc ( sizeof ( Level ) );
        Mapa * mapa = (Mapa * )malloc ( sizeof ( Mapa ) );
    
        Duch ** duchove = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Duch ** burkinatori = (Duch **)malloc ( sizeof ( Duch * ) * 256 );
        Sebratelne ** sebratelne_veci = (Sebratelne **)malloc ( sizeof ( Sebratelne * ) * 256 );
        
        if ( !lvl || !mapa || !duchove || !burkinatori || !sebratelne_veci ) {
            goto neni_pamet;
        }
        
        // enum který nám bude popisovat jednotlivý prvky mapy,
        // 'N' jakože nic, 'B' jakože blok, 'D' jakože duch
        // 'Q' jako burkinátor (vono se to prej správně piše ňák s kvé jakože 'burqa' nebo jak)
        // 'S' jao srdičko, 'H' jako hvězda
        enum herniVec {N,D,B,Q,S,H};
    
        // pole jednotlivejch segmentů, ze kterejch budeme skládat tu mapu
        // musíme si tam dát ňáký ty bonusy
        // (zatim to nemáme vybalancovaný, hvězda by asi jako měla bejt víc zácnej bonus)
        
        int seg1 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            B,B,B,B,B,
        };
        int seg2 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,B,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
    
        int seg3 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,B,0,D,0, 0,D,0,B,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg4 [] =
    
        {
    
            0,0,0,0,0,
            B,0,0,0,B,
        };
        int seg5 [] = {
    
            0,0,0,0,0,
            B,0,Q,0,B,
        };
        int seg6 [] = {
    
            0,0,0,0,0,0,0,0,0,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,0,0,B,0,
            0,0,0,0,B,0,0,0,B,0,0,B,0,B,0,
            0,0,B,0,B,0,0,0,B,0,0,B,0,B,0,
            B,Q,B,Q,B,Q,0,Q,B,Q,0,B,Q,B,B,
        };
        int seg7 [] = {
    
            0,0,0,0,0,0,0,0,0,B,0,0,0,0,0,
            0,0,0,0,0,0,0,0,B,B,0,0,0,0,0,
            0,0,0,0,0,0,0,B,B,B,0,0,0,0,0,
            0,0,0,0,0,0,B,B,B,B,0,0,0,0,0,
            0,0,0,0,0,B,B,B,B,B,0,0,0,0,0,
            0,0,0,0,B,B,B,B,B,B,0,0,0,0,0,
            0,0,0,B,B,B,B,B,B,B,0,0,0,0,0,
            0,0,B,B,B,B,B,B,B,B,0,0,0,0,0,
            0,B,B,B,B,B,B,B,B,B,0,0,0,0,0,
            B,B,B,B,B,B,B,B,B,B,Q,Q,Q,Q,B,
        };
        int seg8 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,D,D, D,D,0,0,0,
            0,0,B,B,B, B,B,B,0,0,
            B,B,B,B,B, B,B,B,B,B,
        };
        int seg9 [] =
    
        {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,H,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg10 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,S,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg11 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,D,0,0,
            0,B,B,B,0,
            B,B,B,B,B
        };
        int seg12 [] = {
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,B,0,
            0,B,0,B,0,
            B,B,B,B,B
        };
        int seg13 [] =
    
        {
            0,0,0,0,0, 0,0,0,0,0,
            0,0,0,0,0, 0,0,0,0,0,
            0,0,B,0,0, 0,0,0,0,0,
            0,B,B,D,0, D,0,D,0,B,
            B,B,B,B,B, B,B,B,B,B,
        };
    
        SegmentMapy segmenty [] = {
            ( SegmentMapy ) {5,5,seg1},
            ( SegmentMapy ) {5,5,seg2},
            ( SegmentMapy ) {10,5,seg3},
            ( SegmentMapy ) {5,2,seg4},
            ( SegmentMapy ) {5,2,seg5},
            ( SegmentMapy ) {15,5,seg6},
            ( SegmentMapy ) {15,10,seg7},
            ( SegmentMapy ) {10,5,seg8},
            ( SegmentMapy ) {5,5,seg9},
            ( SegmentMapy ) {5,5,seg10},
            ( SegmentMapy ) {5,5,seg11},
            ( SegmentMapy ) {5,5,seg12},
            ( SegmentMapy ) {10,5,seg13},
        };
    
        // počet těch segmentů ze kterejch budem vybírat
        const size_t segmentu = sizeof ( segmenty ) /sizeof ( SegmentMapy );
    
        // alokujem si bloky dlaždicový mapy
        int ** bloky = calloc ( MAPA_MAX_VYSKA, sizeof ( int * ) * MAPA_MAX_VYSKA );
    
        if ( !bloky ) {
            goto neni_pamet;
        }
    
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            bloky[i] = calloc ( sirka,sizeof ( int ) );
            if ( !bloky[i] ) {
                goto neni_pamet;
            }
        }
    
        // prvních a posledních deset sloupečků herní mapy bude placka,
        for ( size_t i=0; i<10; i++ ) {
            bloky[MAPA_MAX_VYSKA-1][i]=GetRandomValue ( 0,6 ) + 1; //vybíráme náhodnou texturu
            bloky[MAPA_MAX_VYSKA-1][ sirka - i - 1 ]=GetRandomValue ( 0,6 ) + 1;
        }
    
        int zbyva_delka = sirka - 10;
        
        size_t duchu = 0;
        size_t burkinatoru = 0;
        size_t sebratelnych_veci = 0;
        
        while ( zbyva_delka >= 15 ) {
            
            // vyberem si náhodnej segment
            int index = GetRandomValue ( 0,segmentu-1 );
            
            int vyska_segmentu = segmenty[index].vyska;
            int sirka_segmentu = segmenty[index].sirka;
    
            if ( sirka_segmentu > zbyva_delka -10 ) {
                continue;
            }
    
            // noa teďko si projdem celý pole toho náhodně vybranýho segmentu....
            for ( size_t segment_y = 0; segment_y < vyska_segmentu; segment_y++ ) {
                for ( size_t segment_x = 0; segment_x < sirka_segmentu; segment_x++ ) {
                    int hodnota = segmenty[index].pole[segment_x + segment_y * sirka_segmentu];
    
                    // ....a podle toho na jakou hodnotu sme tam narazili se budem chovat
                    switch ( hodnota ) {
                    case B:
                        // vyrobíme náhodnej blok mapy
                        // zarovnáváme to k dolnímu vokraji mapy
                        bloky[segment_y + MAPA_MAX_VYSKA - vyska_segmentu][segment_x + ( sirka - zbyva_delka )] = GetRandomValue ( 0,6 ) + 1;
                        break;
                    case D:
                        //vyrobíme na tý pozici ducha
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA - 161,
                            };
                            Duch * duch = vygenerovatDucha ( pozice );
                            if(!duch) goto neni_pamet;
                            duchove[duchu++] = duch;
                        }
                        break;
                    case Q:
                        //vyrobíme burkinátora
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA + BLOK_VYSKA*3,
                            };
                            Duch * duch = vygenerovatBurkinatora ( pozice );
                            if(!duch) goto neni_pamet;
                            burkinatori[burkinatoru++] = duch;
                        }
                        break;
                    case S:
                        //vyrobíme srdíčko
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNE_SRDICKO );
                            if(!vec) goto neni_pamet;
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    case H:
                        //vyrobíme bonusovou hvězdu
                        {
                            Vector2 pozice = {
                                .x = ( segment_x + ( sirka - zbyva_delka ) ) * BLOK_SIRKA,
                                .y = ( segment_y + MAPA_MAX_VYSKA - vyska_segmentu ) * BLOK_VYSKA,
                            };
                            Sebratelne * vec = vygenerovatSebratelnouVec ( pozice,SEBRATELNA_HVEZDA );
                            if(!vec) goto neni_pamet;
                            sebratelne_veci[sebratelnych_veci++] = vec;
                        }
                        break;
                    default:
                        break;
                    };
    
                }
    
            }
    
            zbyva_delka-=sirka_segmentu;
        }
        
        duchove = realloc ( duchove, sizeof ( Duch * ) * duchu );
        burkinatori = realloc ( burkinatori, sizeof ( Duch * ) * burkinatoru );
        sebratelne_veci = realloc ( sebratelne_veci, sizeof ( Sebratelne * ) * sebratelnych_veci );
        
        // nvm jestli se muže reallokace pokazit když jenom zmenčujem :D
        // rači budem předpokládat že jo
        if ( duchu && !duchove ) {
            goto neni_pamet;
        }
        if ( burkinatoru && !burkinatori ) {
            goto neni_pamet;
        }
        if ( sebratelnych_veci && !sebratelne_veci ) {
            goto neni_pamet;
        }
    
        // nacpem duchy do tý struktury levelu
        lvl->pocet_duchu = duchu;
        lvl->duchove = duchove;
        
        // napcem tam i burkinátory
        lvl->pocet_burkinatoru = burkinatoru;
        lvl->burkinatori = burkinatori;
        
        // a nacpem tam taky bonusy
        lvl->pocet_sebratelnych_veci = sebratelnych_veci;
        lvl->sebratelne_veci = sebratelne_veci;
    
        // strčíme bloky do mapy
        mapa->bloky = bloky;
        mapa->sirka = sirka;
        mapa->vyska = MAPA_MAX_VYSKA;
        mapa->textura = texturaTiledMapy;
        
        // a mapu strčíme do levelu
        lvl->dlazdicova_mapa = mapa;
        
        // u konce mapy vygenerujem stojan
        Stojan * stojan = vygenerovatStojan ( ( Vector2 ) {( sirka-5 ) *BLOK_SIRKA,720} );
        lvl->stojan = stojan;
    
        return lvl;
    neni_pamet:
    
        if ( lvl->duchove ) {
            for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
                if ( lvl->duchove[i] ) {
                    freeDucha ( lvl->duchove[i] );
                }
            }
            free ( lvl->duchove );
        }
    
        if ( lvl->burkinatori ) {
            for ( size_t i=0; i<lvl->pocet_burkinatoru; i++ ) {
                if ( lvl->burkinatori[i] ) {
                    freeDucha ( lvl->burkinatori[i] );
                }
            }
            free ( lvl->burkinatori );
        }
    
        if ( lvl->sebratelne_veci ) {
            for ( size_t i=0; i<lvl->pocet_sebratelnych_veci; i++ ) {
                if ( lvl->sebratelne_veci[i] ) {
                    free ( lvl->sebratelne_veci[i] );
                }
            }
            free ( lvl->sebratelne_veci );
        }
    
        if ( lvl->dlazdicova_mapa ) {
            if ( lvl->dlazdicova_mapa->bloky ) {
                for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
                    if ( lvl->dlazdicova_mapa->bloky[i] ) {
                        free ( lvl->dlazdicova_mapa->bloky[i] );
                    }
                }
                free ( lvl->dlazdicova_mapa->bloky );
            }
            free ( lvl->dlazdicova_mapa );
        }
    
        if ( bloky ) {
            for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
                if ( bloky[i] ) {
                    free ( bloky[i] );
                }
            }
            free ( bloky );
        }
    
        if ( lvl ) {
            free ( lvl );
        }
    
        return NULL;
    }
    
    void freeLevel ( Level * lvl )
    {
        for ( size_t i=0; i<lvl->pocet_duchu; i++ ) {
            freeDucha ( lvl->duchove[i] );
        }
        free ( lvl->duchove );
        
        for ( size_t i=0; i<lvl->pocet_burkinatoru; i++ ) {
            freeDucha ( lvl->burkinatori[i] );
        }
        free ( lvl->burkinatori );
        
        for ( size_t i=0; i<lvl->pocet_sebratelnych_veci; i++ ) {
            free ( lvl->sebratelne_veci[i] );
        }
        free ( lvl->sebratelne_veci );
        
        for ( size_t i=0; i<MAPA_MAX_VYSKA; i++ ) {
            free ( lvl->dlazdicova_mapa->bloky[i] );
        }
        free ( lvl->dlazdicova_mapa->bloky );
        free ( lvl->dlazdicova_mapa );
        
        // uklidíme stojan
        free ( lvl->stojan );
        
        free ( lvl );
    }
    
    // aktualizovatLevel teďko vrací navratovou hodnotu
    enum LevelStatus aktualizovatLevel ( Level * lvl, David * david, float dt )
    {
        Strela * strely = david->strely;
        
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            
            if(fabsf ( david->pozice.x - lvl->duchove[i]->okraje.x ) > NUTNA_VZDALENOST)
                continue;
            
            if ( ! lvl->duchove[i]->chcipe )
    
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->duchove[i]->hitbox ) ) {
                            
                            s->aktivni = false;
                            lvl->duchove[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                }
    
            aktualizovatDucha ( lvl->duchove[i], lvl->dlazdicova_mapa, dt );
            
            // pohlídáme si kolizi Davida s duchem, pokud se srazej tak duch Davida zraní
            // kolizi zistíme raylibí funkcí 'CheckCollisionRecs' do který nacpem hitboxy vobou herních entit
            if ( !lvl->duchove[i]->chcipe && CheckCollisionRecs ( lvl->duchove[i]->hitbox, david->hitbox ) ) {
                if ( david->zranitelny ) {
                    
                    // zahrajem zvuk kontaktu
                    // (vlastně nvm jestli to má bejt jakože zvuk co vydává duch nebo david :D )
                    PlaySound ( zvuk_kontakt );
                    
                    // vodečtem davidoj život
                    david->zivoty--;
                    
                    // nastavíme davidoj blikací čas dočasný nezranitelnosti..
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    
                    // ..a zapnem mu tu nezranitelnost
                    david->zranitelny = false;
                    
                    // pokud má ňákou vertikální rychlost směrem nahoru k hornímu vokraji vobrazkovky,
                    // tak mu ji snižime na nulu. Vono to vytváří takovej psychochologickej efekt jakože
                    // hráče ty duchové chytaj a bráněj mu v pohybu :O ;D
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // přidáme si sem to zabíjení duchů tim hvězdičkovým bonusem
                else if ( david->ma_bonus ) {
                    lvl->duchove[i]->hp = 0;
                }
            }
    
            for ( size_t j=0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                Strela * strela_ducha = &lvl->duchove[i]->strely[j];
                if ( strela_ducha->aktivni ) {
                    aktualizovatStrelu ( strela_ducha,lvl->dlazdicova_mapa, dt );
                    
                    // podobně jako sme hlídali zásah hitboxu ducha davidovou střelou,
                    // tak budeme klídat zásah davida střelou ducha
                    if ( CheckCollisionPointRec ( strela_ducha->pozice, david->hitbox ) ) {
                        strela_ducha->aktivni = false;
    
                        if ( david->zranitelny ) {
                            // v poctatě to samý jako při kontaktu
                            PlaySound ( zvuk_kontakt );
                            david->zivoty--;
                            david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                            david->zranitelny = false;
                        }
                    }
                }
            }
        }
        
        // vicemeně skoro uplně stejně si sem přidáme aktualizaci burkinátorů, jako sme napsali aktualizaci vobyč duchů
        for ( size_t i =0; i<lvl->pocet_burkinatoru; i++ ) {
    
            if ( fabsf ( david->pozice.x - lvl->burkinatori[i]->okraje.x ) > NUTNA_VZDALENOST )
                continue;
            
            if ( ! lvl->burkinatori[i]->chcipe )
                for ( size_t j = 0; j < POCET_STREL_DAVIDA_MAX; j++ ) {
                    Strela * s = strely + j;
                    if ( s->aktivni ) {
                        if ( CheckCollisionPointRec ( s->pozice, lvl->burkinatori[i]->hitbox ) ) {
                            s->aktivni = false;
                            lvl->burkinatori[i]->hp--;
                            PlaySound ( zvuk_zasah );
                        }
                    }
                    
                }
                
            // zkusíme kolizi s davidem
            if( ! lvl->burkinatori[i]->chcipe && CheckCollisionRecs ( lvl->burkinatori[i]->hitbox, david->hitbox )) {
                if ( david->zranitelny ) {
                    PlaySound ( zvuk_kontakt );
                    david->zivoty--;
                    david->blikaci_cas = BLIKACI_CAS_DAVIDA;
                    if ( david->vertikalni_rychlost < 0.0f ) {
                        david->vertikalni_rychlost = 0.0f;
                    }
    
                }
                // sem si taky přidáme to zabíjení burkinátorů magickou hvězdou
                else if ( david->ma_bonus ) {
                    lvl->burkinatori[i]->hp = 0;
                }
            }
    
            
            aktualizovatBurkinatora ( lvl->burkinatori[i], david->pozice.x, dt );
            
        }
        
        // přidáme si sem stojan
        
        // pokud neni převlajkovanej a dojde kolizi s davidem
        if ( !lvl->stojan->uz_se_prevlajkoval_uplne && CheckCollisionRecs ( lvl->stojan->okraje, david->hitbox ) ) {
            
            // tak si pohlídáme by se nám přepnuly ty převlakovávací booly
            // ( by sme měli asi 'zapouzdřit' do tý struktury stojanu)
            if ( !lvl->stojan->prevlajkovava_se && !lvl->stojan->uz_se_prevlajkoval_uplne ) {
                lvl->stojan->prevlajkovava_se=true;
            }
    
            // vypnem hudby a zapnem znělku vítězství (pokud eště nehraje)
            if ( !IsSoundPlaying ( zvuk_vyhra ) ) {
    
                StopMusicStream ( hudba_lvl );
                StopMusicStream ( hudba_bonus );
                PlaySound ( zvuk_vyhra );
            }
        }
    
        aktualizovatStojan ( lvl->stojan,dt );
        
        // jestli se už převlajkoval a už dohrál zvuk výhry tak se vrátíme zpátky do hlavního menu
        if ( lvl->stojan->relativni_cas > PREVLAJKOVAVACI_CAS_STOJANU && !IsSoundPlaying ( zvuk_vyhra ) ) {
            return LVL_VYHRA;
        }
    
        // přidali sme si sem podminku hlidajicí převlajkovávání stojanu, by nám nedošlo ke kolizi přepínání hudeb,
        // páč se muže stát že David strhne bubu vlajku a ve stejný době mu třeba skončí hvězdej bonus. To by nám
        // vlezlo do tý vítězný znělky hraný jakoby tim stojanem 
        if ( !david->ma_bonus && hudba_aktualni == &hudba_bonus && lvl->stojan->relativni_cas < 0.01f ) {
            PlayMusicStream ( hudba_lvl );
            hudba_aktualni = &hudba_lvl;
        }
        
        // a budeme aktualizovat sebratelný věci
        // kouknem jesli má věc minimální nutnou vzdálenost, jestli jo tak se kouknem jestli ji de sebrat a jestli má
        // kolizi s Davidovým hitboxem, jestli jo, tak ji David jakože sebere
        for ( size_t i = 0; i< lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( david->pozice.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                if ( !lvl->sebratelne_veci[i]->sebrano && CheckCollisionRecs ( lvl->sebratelne_veci[i]->okraje, david->hitbox ) ) {
    
                    lvl->sebratelne_veci[i]->sebrano = true;
                    PlaySound ( zvuk_powerup );
    
                    switch ( lvl->sebratelne_veci[i]->druh ) {
                    case SEBRATELNA_HVEZDA:
                        //hvězda aktivuje bonus a nastaví hvězdnej čas
                        {
                            david->ma_bonus = true;
                            david->hvezdny_bonus_cas = HVEZDNY_CAS_DAVIDA;
                            
                            // pauznem hudbu levelu
                            // (pozor, sou tam dvě funkce, pause stream a stop stream. Když pustíme pauznutou hudbu tak přehrávání
                            // pokračuje vod místa kde přestalo, stopnutá hraje vod začátku)
                            PauseMusicStream ( hudba_lvl );
                            
                            // přetočíme hudbu bonusu na čas vodpovidajicí 24.4 sekund
                            // ( v david.h jestli si jakoby pamatujete sme nastavovali takovej divnej čas trvání hvězdnýho bonusu.
                            // Je to kuli trvání useku hudby, kterej trvá právě vod těch 24.4 s až 24.4 + nějakejch těch čtrnáct seknud)
                            SeekMusicStream ( hudba_bonus, 24.4f );
                            
                            //začnem hrát hudbu bonusu a nastavíme na ni ukazatel aktualní hudby
                            PlayMusicStream ( hudba_bonus );
                            hudba_aktualni = &hudba_bonus;
                        }
                        break;
                    case SEBRATELNE_SRDICKO:
                        //srdičko přidá davidoj jeden život
                        {
                            david->zivoty++;
                            // davidovy životy by asi jako možná neměli překročit maximum
                            if ( david->zivoty > POCET_ZIVOTU_DAVIDA_MAX ) {
                                david->zivoty = POCET_ZIVOTU_DAVIDA_MAX;
                            }
                        }
                        break;
                    default:
                        break;
                    }
    
                }
                aktualizovatSebratelnouVec ( lvl->sebratelne_veci[i],dt );
            }
    
        }
        
        // jestli David nemá žádný životy tak prohrál,
        // jinak pokračujem ve hře
        if ( david->zivoty <= 0 ) {
            return LVL_PROHRA;
        }
    
        return LVL_POKRACUJE;
        
    }
    
    // vykreslíme level
    void vykreslitLevel ( Level * lvl, Camera2D * kamera )
    {
        float min_x = kamera->target.x - GetRenderWidth() / 2.0f / kamera->zoom;
        float max_x = kamera->target.x + GetRenderWidth() / 2.0f / kamera->zoom;
        vykreslitMapu ( lvl->dlazdicova_mapa,min_x,max_x );
    
        // vykreslíme všecky viditelný duchy a všecky střely duchů
        for ( size_t i = 0; i < lvl->pocet_duchu; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->duchove[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->duchove[i] );
            }
    
            for ( size_t j =0; j<ZASOBNIK_STREL_DUCHA; j++ ) {
                vykreslitStrelu ( lvl->duchove[i]->strely + j );
            }
        }
        
    
        // vykreslíme burkinátory
        for ( size_t i = 0; i < lvl->pocet_burkinatoru; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->burkinatori[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitDucha ( lvl->burkinatori[i] );
            }
        }
        
        // vykreslíme sebratelný věci
        for ( size_t i = 0; i < lvl->pocet_sebratelnych_veci; i++ ) {
            if ( fabsf ( kamera->target.x - lvl->sebratelne_veci[i]->okraje.x ) < NUTNA_VZDALENOST ) {
                vykreslitSebratelnouVec ( lvl->sebratelne_veci[i] );
            }
    
        }
    
        // musíme vykreslit i stojan
        vykreslitStojan ( lvl->stojan );
        
    }
    
    #endif
    

    V souboru 'main.c' si načtem tu znělku pro vítězství, je poměrně krátká tak ji načtem jako zvuk (ikdyž to je teda jako asi už celkem nahraně, nvm)

    // naimportujem si knihovny
    #include <math.h>
    #include <stdlib.h>
    #include <raylib.h>
    #include <time.h>
    
    // Pokuď vodkomentujeme, tak to zkompiluje preprocesorovou podmínkou vypnutý věci
    // napřiklad se kolem některejch herních voběktů budou vykreslovat okraje
    // #define DEBUG
    
    // naimportujem si vlastní hlavičky
    #include "animace.h"
    #include "david.h"
    #include "projektily.h"
    #include "level.h"
    #include "menu.h"
    
    //makra na zišťování minimální a maximální hodnoty
    #ifndef MAX
    #define MAX(a, b) ((a)>(b)? (a) : (b))
    #define MIN(a, b) ((a)<(b)? (a) : (b))
    #endif
    
    // šířka a výška vokna
    #define HERNI_SIRKA 1280
    #define HERNI_VYSKA 960
    
    // kolik kostek bude dlouhá naše herní mapa
    #define DELKA_LEVELU_BLOKU 100
    
    // přidáme si enum popisující na který vobrazovce jakože sme,
    // jestli tý s menu, tý s herním levelem nebo tý s game over
    enum KteraObrazovka {OBRAZOVKA_HLAVNI_MENU, OBRAZOVKA_HRA, OBRAZOVKA_GAME_OVER};
    
    enum KteraObrazovka obrazovka = OBRAZOVKA_HLAVNI_MENU;
    
    // textury
    Texture2D textura_mesic;
    Texture2D textura_david_spritesheet;
    Texture2D textura_kameny;
    Texture2D textura_duchove_spritesheet;
    Texture2D textura_ruzne;
    Texture2D textura_hrad;
    
    //textury menu a 'gui' prvků
    Texture2D textura_menu_titulek;
    Texture2D textura_menu_pozadi;
    Texture2D textura_menu_pozadi2;
    Texture2D textura_menu_game_over;
    Texture2D textura_menu_zmackni_enter;
    Texture2D textura_menu_david;
    
    // zvuky
    Sound zvuk_kroku;
    Sound zvuk_skoku;
    Sound zvuk_vystrel;
    Sound zvuk_duch_chcip;
    Sound zvuk_duch_strela;
    Sound zvuk_zasah;
    Sound zvuk_kontakt;
    Sound zvuk_padu;
    Sound zvuk_zaghrouta;
    Sound zvuk_powerup;
    
    // přidáme si znělku výhry
    Sound zvuk_vyhra;
    
    // hudby
    Music hudba_lvl;
    Music hudba_bonus;
    Music hudba_menu;
    Music hudba_game_over;
    
    //ukazatel na právě hranou hudbu
    Music * hudba_aktualni;
    
    int main ( void )
    {
        // nastavíme generátor nahodnejch čisel nějakým seedem
        // (vobvykle se tam strká aktualní čas ale mužeme si tam dát
        // třeba ňákou konstantu by sme to měli vopakovatelný a mohli reprodukovat stejnej level)
        SetRandomSeed ( time ( 0 ) );
    
        SetConfigFlags ( FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT );
    
        InitWindow ( HERNI_SIRKA, HERNI_VYSKA, "David a duchove" );
    
        InitAudioDevice();
    
        SetTargetFPS ( 60 );
    
        // načtem soubory textur
        textura_david_spritesheet = LoadTexture ( "assets/david.png" );
        textura_mesic = LoadTexture ( "assets/moon.png" );
        textura_kameny = LoadTexture ( "assets/kameny.png" );
        textura_duchove_spritesheet = LoadTexture ( "assets/duchove.png" );
        textura_ruzne = LoadTexture ( "assets/misc.png" );
        textura_hrad = LoadTexture ( "assets/hrad2.png" );
        textura_menu_titulek = LoadTexture ( "assets/title.png" );
        textura_menu_pozadi = LoadTexture ( "assets/gy.png" );
        textura_menu_pozadi2 = LoadTexture ( "assets/gy_hroby.png" );
        textura_menu_game_over = LoadTexture ( "assets/game_over.png" );
        textura_menu_zmackni_enter = LoadTexture ( "assets/zmackni_enter.png" );
        textura_menu_david = LoadTexture ( "assets/koli.png" );
        
        // načtem zvuky
        zvuk_kroku = LoadSound ( "assets/kroky.wav" );
        zvuk_skoku = LoadSound ( "assets/skok.wav" );
        zvuk_vystrel = LoadSound ( "assets/bum.wav" );
        zvuk_duch_chcip = LoadSound ( "assets/duch_chcip.wav" );
        zvuk_duch_strela = LoadSound ( "assets/duch_strela.wav" );
        zvuk_zasah = LoadSound ( "assets/zasah.wav" );
        zvuk_kontakt = LoadSound ( "assets/kontakt.wav" );
        zvuk_padu = LoadSound ( "assets/pad.wav" );
        zvuk_zaghrouta = LoadSound ( "assets/zaghrouta.ogg" );
        zvuk_powerup = LoadSound ( "assets/powerup.wav" );
        zvuk_vyhra = LoadSound ( "assets/Victory!.wav" );
        
        //načtem hudby
        hudba_lvl = LoadMusicStream ( "assets/waltz_of_the_ghosts.ogg" );
        hudba_bonus = LoadMusicStream ( "assets/for_a_few_shekels_more_band.ogg" );
        hudba_menu = LoadMusicStream ( "assets/ghost_trip.ogg" );
        hudba_game_over = LoadMusicStream ( "assets/hatikva.ogg" );
        
        Camera2D kamera = {
            
            //posun 'středu' kamery, posunem na střed vobrazovky
            .offset = ( Vector2 ) { GetRenderWidth() / 2.0f, GetRenderHeight() / 2.0f },
            // souřadnice cíle, na co jakože kamera kouká
            .target = ( Vector2 ) {0,0},
            // uhel náklonu kamery ve stupních
            .rotation = 0.0f,
            //přiblížení
            .zoom = 1.0f
        };
        
        //ukazatel, kde si budeme držet vygenerovanej level
        Level * level = NULL;
        // ukazatel, kterej bude držet 'pole' davidovejch střel
        Strela * david_strely = NULL;
        
        // animace běhu
        Animace david_beh = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_behu, .pocet_framu = sizeof ( david_framy_behu ) /sizeof ( Rectangle )
        };
        // animace idle, jakože když se fláká a nic nedělá. Je to takový pérování nohama na místě
        Animace david_idle = {
            .trvani_framu = 1.0f/15.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_idle, .pocet_framu = sizeof ( david_framy_idle ) /sizeof ( Rectangle )
        };
    
        Animace david_sed = {
            .trvani_framu = 1.0f/30.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = false,
            .textura = textura_david_spritesheet, .framy = david_framy_sed, .pocet_framu = sizeof ( david_framy_sed ) /sizeof ( Rectangle )
        };
    
        // animace skoku, david tam vicemeně jenom máchá nožičkama ve vzduchu
        Animace david_skok = {
            .trvani_framu = 1.0f/10.0f, .relativni_cas=0.0f, .index = 0,
            .jojo = true, .reverzne = false, .zrcadlit = false, .loopovat = true,
            .textura = textura_david_spritesheet, .framy = david_framy_skoku, .pocet_framu = sizeof ( david_framy_skoku ) /sizeof ( Rectangle )
        };
        
        
        David david;
    
        // nastavíme ukazatel aktuální animace na animaci 'idle'
        david.aktualni_animace = &david.animace_idle;
                    
        // podle aktuální pozice nastavíme okraje oběktu a teďko nově i hitbox
        david.okraje = ( Rectangle ) {
            david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
        };
        david.hitbox = ( Rectangle ) {
            david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
        };
        
        // nastavíme aktuální hudbu na hudbu menu
        hudba_aktualni = &hudba_menu;
        
        //vygenerujem si hlavní menu a zapnem vodpovidajicí muziku
        vygenerovatMenu();
        PlayMusicStream ( hudba_menu );
        
        
        while ( !WindowShouldClose() ) {
    
            float dt = GetFrameTime();
            
            //aktualizujeme hudbu, na kterou ukazuje ukazatel 'hudba_aktualni'
            UpdateMusicStream ( *hudba_aktualni );
            
            // spočitáme si přiblížení naší kamery
            // uděláme to tak, že si spočitáme poměr skutečný šířky obrazovky s naší 'virtuální' požadovanou,
            // to samý uděláme se skutečnou a požadovanou vejškou, noa vybereme tu menší hodnotu
            // (jak se to chová si mužeme vyzkoušet behem hry, když budeme ruzně měnit velikost vokna)
            const float priblizeni = MIN ( ( float ) GetRenderWidth() / HERNI_SIRKA, ( float ) GetRenderHeight() / HERNI_VYSKA );
    
            // nastavíme atribut 'zoom' tou naší spočitanou hodnotou
            kamera.zoom = priblizeni;
            //nastavíme posun kamery na velikost půlky vobrazovky
            kamera.offset = ( Vector2 ) {
                GetScreenWidth() /2, GetScreenHeight() /2
            };
            if ( obrazovka == OBRAZOVKA_HLAVNI_MENU ) {
                BeginDrawing();
                // GetRenderHeight a GetRenderWidth je skoro to samý co GetScreenHeight a GetScreenWidth jenom s tim rozdílem
                // že to započitává DPI hele https://cs.wikipedia.org/wiki/DPI, jakože počet pixelů na jednotku délky
                // (na vobyčejným počitači nás to asi nemusí moc trápit, na mobilním zařizení by to ale bylo zásadní)
                DrawRectangleGradientV ( 0,0,GetRenderWidth(),GetRenderHeight(),DARKBLUE,BLACK );
    
                //aktualizujeme a vykreslíme menu
                aktualizovatVykreslitMenu ( dt );
                EndDrawing();
    
                if ( IsKeyPressed ( KEY_ENTER ) ) {
    
                    // pokud ukazatel na strukturu level neni vynulovanej, tak to pravděpodobně znamená že se už jednou hrálo a
                    // že musíme starej level uklidit by sme mohli vygenerovat novej
                    if ( level != NULL ) {
                        freeLevel ( level );
                        
                        // uklidíme i střely, idkyž by asi jako bylo víc lepčejší každý prostě nastavit atribut 'aktivni' na false :D
                        free ( david_strely );
                    }
                    
                    //vygenerujeme si herní level
                    level = vygenerovatLevel ( DELKA_LEVELU_BLOKU,textura_kameny );
                    
                    // správně by jsme asi jako měli ňák líp informovat uživatele že se něco pokazilo třeba ňákým logem
                    // takle by na to koukal jako péro z gauče co se jako pokazilo že hra hnedka spadla :D :D
                    // to až příště jestli budete hodný :D :D :D ;D
                    if(! level) return 1;
    
    
                    david_strely = calloc ( POCET_STREL_DAVIDA_MAX,sizeof ( Strela ) );
                    if(!david_strely)
                    {
                        freeLevel(level);
                        return 1;
                    }
                    
                    //inicializujeme si davida
                    david = (David){
                        
                        .animace_beh = david_beh,
                        .animace_idle = david_idle,
                        .animace_sed = david_sed,
                        .animace_skok = david_skok,
                        .aktualni_animace = NULL,
                        .pozice = {0,0},
                        .smer = 1,
                        .mapa = level->dlazdicova_mapa,
                        .vertikalni_rychlost = 0.0f,
                        .zdaSkace = true,
                        .strely = david_strely,
                        .strileci_cooldown = 0.0f,
                        .blikaci_cas = 0.0f,
                        .zivoty = POCET_ZIVOTU_DAVIDA_MAX,
                        .zranitelny = true,
                        .ma_bonus = false,
                        .hvezdny_bonus_cas = 0.0f,
    
                    };
    
                    //nastavíme ukazatel aktuální animace na animaci 'idle'
                    david.aktualni_animace = &david.animace_idle;
                    
                    //podle aktuální pozice nastavíme okraje oběktu a hitbox
                    david.okraje = ( Rectangle ) {
                        david.pozice.x + 45, david.pozice.y +8, DAVID_F_SIRKA -90, DAVID_F_VYSKA - 10
                    };
                    david.hitbox = ( Rectangle ) {
                        david.pozice.x + 55, david.pozice.y +20, DAVID_F_SIRKA -110, DAVID_F_VYSKA-30
                    };
    
                    //vypnem hudbu menu
                    StopMusicStream ( hudba_menu );
                    
                    // vypnem hudbu levelu (by sme ji restartovali aby nám nehrála třeba někde vodprostředka)
                    StopMusicStream ( hudba_lvl );
                    
                    // zapnem hudbu levelu
                    PlayMusicStream ( hudba_lvl );
                    
                    // a nastavíme jeji adresu do ukazatele na aktuální hudbu, by se nám muzika taky aktualizovala, bez  toho by nehrála :D
                    hudba_aktualni = &hudba_lvl;
                    
                    //nakonec přepnem vobrazovku
                    obrazovka = OBRAZOVKA_HRA;
                }
    
                // vykreslujem menu, takže nás další věci nezajímaj a přeskočíme je tim, že skočíme na začátek dalšího while cyklusu
                continue;
            }
            
            
            if ( obrazovka == OBRAZOVKA_HRA ) {
    
                // aktualizujem davida
                // funkce žere ukazatel, takže davida tam nacpem tak, že tam strčíme jeho adresu
                aktualizovatDavida ( &david, dt );
                
                // aktualizujem level
                enum LevelStatus status = aktualizovatLevel ( level, &david, dt );
    
                // podle návratový hodnoty určíme, jesttli se hraje dál nebo jestli nám David umřel a musíme
                // přepnout na 'game over' nebo jestli vyhrál a musíme se vrátit zpátky do hlavního menu
                // (ve finální verzi tý hry by sme asi měli mit ňáký hi-score nebo tak něco)
                // jenom tady přepínáme muziku a aktualní 'vobrazovku'
                if ( status == LVL_PROHRA ) {
                    obrazovka = OBRAZOVKA_GAME_OVER;
                    StopMusicStream ( hudba_lvl );
                    StopMusicStream ( hudba_bonus );
                    PlayMusicStream ( hudba_game_over );
                    hudba_aktualni = &hudba_game_over;
    
                } else if ( status == LVL_VYHRA ) {
                    StopMusicStream ( hudba_lvl );
                    StopMusicStream ( hudba_bonus );
    
                    PlayMusicStream ( hudba_menu );
                    hudba_aktualni = &hudba_menu;
                    obrazovka = OBRAZOVKA_HLAVNI_MENU;
    
                }
            }
            
            // nastavíme cíl kamery na střed davida
            kamera.target = ( Vector2 ) {
                david.okraje.x + david.okraje.width / 2.0f, david.okraje.y + david.okraje.height / 2.0f
            };
            
            const float kamera_target_min_x = GetRenderWidth() / 2.0f / priblizeni;
            const float kamera_target_max_x = DELKA_LEVELU_BLOKU * BLOK_SIRKA - GetRenderWidth() /2/priblizeni;
            const float kamera_target_max_y = GetRenderHeight() / 2.0f / priblizeni - DAVID_F_VYSKA + BLOK_VYSKA*5;
    
            // pohlídáme si ty minimální a maximální možný hodnoty
            kamera.target.x = MAX ( kamera.target.x, kamera_target_min_x );
            kamera.target.x = MIN ( kamera.target.x, kamera_target_max_x );
            kamera.target.y = MIN ( kamera.target.y, kamera_target_max_y );
    
            // zapnem vykreslování
            BeginDrawing();
    
            // vykreslíme ten gradient
            DrawRectangleGradientV ( 0,0,GetScreenWidth(),GetScreenHeight(),DARKBLUE,BLACK );
            
            // první kus našeho parallaxu
            // hovorka se asi jako bojí děsně velkejch měsiců když je furt v horrorovejch komixech kreslí,
            // tak mu uděláme radost na na pozadí vykreslíme supr strašidelnej měsíc :D :D
            float mensi_rozmer = MIN ( GetRenderWidth(),GetRenderHeight() );
            DrawTexturePro ( textura_mesic, ( Rectangle ) {
                0,0,textura_mesic.width,textura_mesic.height
            }, ( Rectangle ) {
                GetRenderWidth() /2,GetRenderHeight() /2,mensi_rozmer*1.5, mensi_rozmer*1.5
            }, ( Vector2 ) {
                mensi_rozmer*1.5/2,mensi_rozmer*1.5/2
            },0, ( Color ) {
                102, 191, 255, 128
            } );
            
            // aktivujem transformování tou naší kamerou
            // takže jakoby vykreslujem to, co kamera vidí
            BeginMode2D ( kamera );
            
            //vykreslíme parallax
    
            // to je jakože takový pozadí, který se různě pomaličku posouvá, když se hráč pohybuje na mapě a vytváří to
            // víc lepší iluzi že se hráč jakože někam pohybuje
            // todle je zatim dělaný jentak na hrubo, vykresluje to takovou siluletu jeruzalémskýho hradu která se děsně pomaličku posouvá
            // když David poskakuje nebo de dopředu
    
    
            // velikost tý textury hradu
            Rectangle hrad_zdroj = {0,0,1024,512};
            
            // cílovej vobdelnik hradu
            // uděláme ho 2x delší než je šířka vobrazovky a budem 
            // (asi to nebude moc dobře fungovat na uzkejch vobrazovkách, tam by sme asi jako museli zvolit
            // ňákej uplně jinej koncept, nvm)
            Rectangle hrad_cil = {
                .x = kamera.target.x - GetRenderWidth() /priblizeni,
                .y = kamera.target.y - GetRenderWidth() /2/priblizeni,
                // vodelnik taky bude muset bejt 2x širší než vyšší, by se nám moc nezdeformovala textura
                .width = GetRenderWidth() /priblizeni*2,
                .height = GetRenderWidth() /2/priblizeni*2,
            };
            
            // počátek/origin toho velkýho rectanglu budem určovat z mezí vobrazovky
            // musíme si pohlídat když hráč stojí u kraje mapy by nám tam nevylezla někam doprostředka vobrazovky hrana textury :D
            float hrad_y_posun_paralax = -300.0f + 300.0f * kamera.target.y/kamera_target_max_y;
            float hrad_x_posun_paralax = -GetRenderWidth() /priblizeni/2 + GetRenderWidth() /priblizeni * ( kamera.target.x - kamera_target_min_x ) /kamera_target_max_x;
    
            // noa vykreslíme ten náš parallax
            DrawTexturePro ( textura_hrad, hrad_zdroj, hrad_cil, ( Vector2 ) {
                hrad_x_posun_paralax,hrad_y_posun_paralax
            },0,WHITE );
    
            // vykreslíme level
            vykreslitLevel( level, &kamera);
            
            // vykreslíme davida
            vykreslitDavida(&david);
            
            DrawRectangleGradientV ( kamera.target.x - GetRenderWidth() / 2 / priblizeni,BLOK_VYSKA*10, GetRenderWidth()/priblizeni,BLOK_VYSKA*3,BLANK, BLACK );
            // a pod tim všecko vyčerníme černým vodelnikem, kterej hezky navazuje na ten náš černej gradient
            DrawRectangle ( kamera.target.x - GetRenderWidth() /2/priblizeni,BLOK_VYSKA*13,GetRenderWidth() /priblizeni,GetRenderHeight()/priblizeni,BLACK );
            
            // vypneme kameru
            EndMode2D();
            
            
            const Rectangle srdicko_rect = {2,503,96,83};
            
            for ( int i = 0; i < POCET_ZIVOTU_DAVIDA_MAX; i++ ) {
                Rectangle cil = {
                    .x = i*srdicko_rect.width/2,
                    .y = GetScreenHeight() - srdicko_rect.height/2,
                    .width = srdicko_rect.width/2,
                    .height = srdicko_rect.height/2,
                };
                DrawTexturePro ( textura_ruzne,srdicko_rect,cil, ( Vector2 ) {
                    0,0
                },0.0f,i<david.zivoty? WHITE:BLACK );
            }
            
            // 'obrazovka' game over
            if ( obrazovka == OBRAZOVKA_GAME_OVER ) {
                // pokud david umře, tak už nebudeme herní věci aktualizovat ale budem je furt vykreslovat
                // všecko překryjeme smutečním černým poloprusvitným vobdelnikem....
                DrawRectangle ( 0,0,GetRenderWidth(),GetRenderHeight(), ( Color ) {
                    0,0,0,128
                } );
                // .... přes kterej namalujeme velkej zelenej text s nápisem 'game over'....
                DrawTexture ( textura_menu_game_over,GetRenderWidth() /2 - textura_menu_game_over.width/2,GetRenderHeight() /3 - textura_menu_game_over.height/2,WHITE );
                // ....a textem, že má hráč zmáčknout na klávesnici čudlik 'enter'
                DrawTexture ( textura_menu_zmackni_enter,GetRenderWidth() /2 - textura_menu_zmackni_enter.width/2,GetRenderHeight() - textura_menu_zmackni_enter.height,WHITE );
    
                if ( IsKeyPressed ( KEY_ENTER ) ) {
                    // noa když ten čudlik hráč zmáčkne, tak přepnem muziku, a přepnem vobrazovku
                    StopMusicStream ( hudba_game_over );
                    PlayMusicStream ( hudba_menu );
                    hudba_aktualni = &hudba_menu;
                    obrazovka = OBRAZOVKA_HLAVNI_MENU;
                }
    
            }
    
            // a skončíme s vykreslováním by se naše scéna poslala na monitor
            EndDrawing();
        }
    
        CloseWindow();
        
        // uvolníme naše vlastní struktury
        if ( david_strely ) {
            free ( david_strely );
        }
        if ( level ) {
            freeLevel ( level );
        }
    
        //uklidíme textury
        UnloadTexture ( textura_mesic );
        UnloadTexture ( textura_david_spritesheet );
        UnloadTexture ( textura_kameny );
        UnloadTexture ( textura_duchove_spritesheet );
        UnloadTexture ( textura_ruzne );
        UnloadTexture ( textura_hrad );
        UnloadTexture ( textura_menu_titulek );
        UnloadTexture ( textura_menu_pozadi );
        UnloadTexture ( textura_menu_pozadi2 );
        UnloadTexture ( textura_menu_david );
        UnloadTexture ( textura_ruzne );
        UnloadTexture ( textura_menu_zmackni_enter );
        UnloadTexture ( textura_menu_game_over );
    
        // vypnem audio zařízení
        CloseAudioDevice();
        
        // musíme uvolnit i muziku
        UnloadMusicStream ( hudba_lvl );
        UnloadMusicStream ( hudba_bonus );
        UnloadMusicStream ( hudba_menu );
        UnloadMusicStream ( hudba_game_over );
        
        // a taky uvolníme zvuky
        UnloadSound ( zvuk_kroku );
        UnloadSound ( zvuk_skoku );
        UnloadSound ( zvuk_vystrel );
        UnloadSound ( zvuk_duch_chcip );
        UnloadSound ( zvuk_duch_strela );
        UnloadSound ( zvuk_zasah );
        UnloadSound ( zvuk_kontakt );
        UnloadSound ( zvuk_padu );
        UnloadSound ( zvuk_zaghrouta );
        UnloadSound ( zvuk_powerup );
        UnloadSound ( zvuk_vyhra );
    
        return 0;
    }
    

    Noa tramtadadá, když David doběhne až na konec mapy tak strhne praporek a vítězství!!


    Tudů

    Rozhodně to neni ani zdaleka žádná hotová hra, eště nám toho jakoby děsně moc chybí udělat, si přectavte že by ste u takovýdle věci měli třeba hodinu denně sedět a pařit to, nóó byste se jako brzy začali nudit 😁 😁

    Určitě to jako chce víc pestřejší škálu nepřátel různejch, chce to víc zbraní páč ta pistolka je děsně nudná (vo tom anketa dole), chce to víc složitějšejší a variabilnějšejší herní svět noa ňáký víc lepčejší efekty, třeba softwérový kuličky co duchové a David střílej by asi jako měli mit ňákej efekt když něco zasahnou, takle prostě mizej, taky nám možná chybí ve spritesheetu ňáká Davidova chcípací animace kterou by sme mohli dycky zahrát když mu dojdou životy, to jak se ta hra skokově šprajce při gameover je takový vošklivý. A taky by to asi jako chtělo ňákej příběch s ňákou zápletkou.

    jóóóóóó jestli v týdlectý duchařině budem pokračovat tak toho jako máme před sebou eště dost 😁 😜

    Credits

    Vobrázky sem vyraběla sama z různejch věcí který sem našla na netu, hudba a zvuky věčinou pocházej z opengameartu. Konkretně to sou:

           

    Hodnocení: 93 %

            špatnédobré        

    Anketa

    V příštím díle by měl David proti duchům kromě jinýho používat taky:
     (63 %)
     (29 %)
     (33 %)
     (46 %)
     (17 %)
     (21 %)
     (25 %)
     (42 %)
     (25 %)
     (25 %)
    Celkem 24 hlasů

    Obrázky

    David a duchové 🤴 👻, obrázek 1 David a duchové 🤴 👻, obrázek 2 David a duchové 🤴 👻, obrázek 3 David a duchové 🤴 👻, obrázek 4 David a duchové 🤴 👻, obrázek 5 David a duchové 🤴 👻, obrázek 6 David a duchové 🤴 👻, obrázek 7 David a duchové 🤴 👻, obrázek 8 David a duchové 🤴 👻, obrázek 9 David a duchové 🤴 👻, obrázek 10 David a duchové 🤴 👻, obrázek 11

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    Gréta avatar 27.11.2023 20:31 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Příloha:

    videjko s gameplay v přiloze by sme si jako nekazili voči jenom gifama :P :P :D ;D

    Gréta avatar 29.11.2023 17:50 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    update: v kroku 16 hele řikám že tam neni funkce na měření velikosti textu nicmeně sem to už našla, maj tam na todle funkce MeasureText a MeasureTextEx hele :O :D

    (blog už nejde editovat páč je moc velkej (hází to ňákou javovskou vyjímku) tak to pišu sem :D)

    27.11.2023 20:49 DDBc
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    proč jsi ho udělala tak ošklivýho?
    Gréta avatar 29.11.2023 17:19 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    sem ho jenom trochu víc zrůžověla jinak to je voriginál :D ;D

    boužel ty materiály který sem na to našla sou ňákejch 10 roků starý šikly by se ňáký víc novější :D ;D

    27.11.2023 21:19 Mazal Tov
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Dozije tenhle blog rana nebo bude davidovan?
    Gréta avatar 29.11.2023 17:19 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    vlastikroot avatar 27.11.2023 22:21 vlastikroot | skóre: 24 | blog: vlastikovo | Milevsko
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Hodne dobry :-D Jako upgrade bych videl vic druhu nepratel, napr. duch s vybusninou, ktera vybouchne v nahodnej okamzik a zabije jak Davida (pokud bude pobliz), tak duchy kolem. Nebo ducha odpalujici rakety letici balistickou drahou na Davida. A tajny tunely by taky staly za to.
    We will destroys the Christian's legion ... and the cross, will be inverted
    Gréta avatar 29.11.2023 17:20 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ruža Becelin avatar 27.11.2023 22:27 Ruža Becelin | skóre: 40 | blog: RuzaBecelinBlog
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Paradni ukazka, jak se dela plosinovka :-)
    Gréta avatar 29.11.2023 17:21 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Blaazen avatar 28.11.2023 01:33 Blaazen | skóre: 24 | blog: BL
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ty farářové maj poslední dobou fakt problémy, asi je posednul ďábel, nebo něco takovýho, hele :-)
    Glee avatar 28.11.2023 03:07 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ty farářové
    Ti
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    28.11.2023 09:21 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jihočeši žádné "ti" nepoužívají (no dobře, jako třetí pád ve druhé osobě jednotného čísla, dejme tomu, ale zde se jedná o první pád množného čísla ve třetí osobě).
    28.11.2023 12:27 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Opravdovi jihocesi mluvili Nemecky, ale byli vyhnani novou republikou a dekrety pana presidenta.
    28.11.2023 13:00 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Opravdovi jihocesi(c)(r)(tm) prisli spolu s ostanima slovanama nekdy v sestem, sedmem stoleti. Predtim to nebyli jihocesi ale ostenfrankove. A nikdo je od te doby nevyhnal, jen se ruzni zlocinci v prubehu staleti pokusili o prevychovu.
    28.11.2023 13:16 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Neresim, co bylo pred vice nez 1300 lety. Resim, co bylo pred ani ne osmdesati lety a co ma jeste pametniky. Chces tvrdit, ze se nejednalo o vyhnani spoluobcanu nejdrive z rozhodnuti majority a nasledne z rozhodnuti presidenta?
    28.11.2023 13:54 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Mavas opravdovymi jihocehy nebo nemeckou naplavou? Vyber si...
    28.11.2023 14:11 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Mluvim o skupine spoluobcanu, ktera zde zila po stovky let a ktera prisla kolonizovat pohranici na pozvani ceskeho krale Ottokara...
    28.11.2023 14:27 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    ... a pak jim prislo jako dobry napad si misto vdeku zahajlovat a kolaborovat s okupantem.
    28.11.2023 20:33 GG
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A ten se jim zahy odmenil povolavacim rozkazem.
    29.11.2023 10:13 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Kdo konkretne?
    29.11.2023 11:12 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Kdo konkretne ne?
    29.11.2023 12:08 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Zase kolektivni vina, co?
    29.11.2023 13:45 jozka | skóre: 19 | blog: jozkovo
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Odkdy je to spatne?
    30.11.2023 07:04 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Vzdycky to bylo spatne. Kolektivni vinu uplatnuji totalitni rezimy - dle tridniho puvodu, dle rasy, dle nabozenstvi a dle narodnosti.
    30.11.2023 08:52 jozka | skóre: 19 | blog: jozkovo
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    No, mam vuci nasemu soucasnemu rezimu spoustu vyhrad, ale tohle jsem zatim nepouzil. Ale dobre, pisu si... Valgrind povazuje soucasny rezim za totalitni.
    30.11.2023 12:32 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak v nekterych aspektech jiste totalitni jiz dnes a rozhodne k totalite smerujici. Od roku 90 se mira osobni svobody permanentne snizuje. Kdo to nevidi, je idiot.
    30.11.2023 14:27 jozka | skóre: 19 | blog: jozkovo
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak moment... totalitni nebo v nekterych aspektech totalitni.

    Lze byt v nekterych aspektech tehotny?
    1.12.2023 08:26 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Mira totality a svobody je skala, ne binarni flag. Srouby se postupne utahuji, to snad empiricky vidi kazdy.
    tehotny?
    Kdyz uz, tak tehotnAAA!!! Muzu se toto netyka. A byt tehotna je proste flag, takze neco jineho.
    1.12.2023 09:39 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Lze byt v nekterych aspektech tehotny?
    Ano, ano.
    1.12.2023 09:49 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    TehotnA kdyz uz! Muz nemuze mit tehotenstvi!
    1.12.2023 09:57 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Evoluce :-) Co kdyz se to seme u jednoho gaye v prdeli jednou ujme a otehotni? :-)
    1.12.2023 10:23 jozka | skóre: 19 | blog: jozkovo
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak prijde na svet dalsi pravnik, no co uz...
    2.12.2023 08:14 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To je vědecký pokrok.

    Sovětští vědci před pár desetiletími rozdojili kozla.

    Američtí vědci před pár roky rozdojili transsexuála.

    Takže taková falešná ženská může "své" přidělené dítě* dokonce i kojit.

    * Dítě odebrané heterosexuálnímu páru se závadným smýšlením.
    2.12.2023 10:36 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ne, žádný pokrok to není. O oktivace laktačních žláz u domestikovaných savců existují zprávy tisíce let do minulosti. Proběhl sice nějaký výzkum jak by se toho dalo využít cíleně, ale celkově je to k ničemu - generované množství mléka je tak zanedbatelné, že se nedá použít pro kojení ani jako doplněk. O průmyslové produkci ani nemluvě.

    5.12.2023 06:42 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To nevysvětluj mě ale Američanům, ti ze sebe dělají mistry světa a myslí si že jsou ve všem první ;-)
    1.12.2023 10:33 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    TehotnA kdyz uz! Muz nemuze mit tehotenstvi!
    Necpi mi prosím tyto levicové anti-rodinné feministické názory o 100% samostatnosti žen. Sorry, ale žena bez muže nemůže být těhotná, tj. muž "je těhotný" u manželky/partnerky, jelikož on to spoluzpůsobil.
    1.12.2023 10:33 jozka | skóre: 19 | blog: jozkovo
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ne a Ne. V prvnim pripade jde o tehotenstvi, lec pruserove, v druhem pripade o nej nejde.
    1.12.2023 10:37 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    V obou případech vykazuje tělo některé aspekty těhotenství, ale ne všechny potřebné na reálné/funkční těhotenství.

    Já jsem to linkoval víceméně jen ze srandy / pro zajímavost, ale jestli se v tom chceš zamotat, tak prosim...
    29.11.2023 20:17 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    "Když se zločinu dopustí stát, bude potrestán stát i se svými občany."

    Vít Rakušan
    30.11.2023 07:10 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A co jako, ze toto rekl nejaky levicovy minister? Kolektivni vina je vzdy spatne. Nebo patris k tem, kteri vyhazuji ruske deti z ceskeho vlaku jen kvuli tomu, ze jsi zaslechl neco jako rustinu? Umis to odlisit treba od bulharstiny nebo ukrajinstiny?
    30.11.2023 22:22 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Právě naopak, kolik tanků dodá Česká republika Sýrii na boj proti okupantům? Kolik dobrovolníků odjede bojovat za osvobození syrského území od izraelských skřetů?

    https://www.novinky.cz/clanek/zahranicni-blizky-a-stredni-vychod-valne-shromazdeni-osn-vyzvalo-izrael-aby-prestal-okupovat-syrske-golanske-vysiny-40452441

    Kdy budou zabaveny peníze izraelských občanů? Kdy budou zabaveny majetky izraelských oligarchů? Kdy budou zabaveny izraelské firmy? Kdy bude zakázáno dovážet izraelské zboží?

    Mimochodem, mezitím izraelští zákonodárci rozhodli že Palesinci budou z Gazy vysídleni do Evropy. Je prý povinnost západu se o ně postarat.
    1.12.2023 08:29 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Sorry jako, ale co dela nebo nedela a rika nebo nerika nejaky ministr z levicove vlady, je mi celkem jedno. Kolektivni vina je za mne spatna vzdy a je jedno, zda se jedna o nemce, rusy, araby ci zidy.
    1.12.2023 09:40 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Mimochodem, mezitím izraelští zákonodárci rozhodli že Palesinci budou z Gazy vysídleni do Evropy.
    Odkaz?
    2.12.2023 07:46 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    2.12.2023 13:33 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Aha, takže "izraelští zákonodárci rozhodli" → "dva poslanci navrhli". Rádio Radovan :)
    5.12.2023 06:50 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A to pokračování jsi ani nehledal, že? Tak tomu dáme ještě pár dní a uvidíme jak se situace vyvine...

    https://www.novinky.cz/clanek/zahranicni-blizky-a-stredni-vychod-spolecna-sprava-se-zapadnim-brehem-zadne-vysidlovani-usa-predestrely-predstavu-o-gaze-po-valce-40452892
    S izraelskými představami se ovšem tento plán rozchází.
    5.12.2023 10:59 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak tomu dáme ještě pár dní
    Jo, to jsem taknějak čekal, že budeš potřebovat :-D
    28.11.2023 14:52 Dan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    Jen bych chtěl dodat následujíci: "Po okupaci zbytku okleštěné republiky německou armádou dne 15. března 1939 vydal Adolf Hitler výnos o zřízení Protektorátu Čechy a Morava, ve kterém byla mimo jiné upravena i otázka státního občanství. V článku 2 stojí konkrétně: „(1) Obyvatelé protektorátu, kteří jsou příslušníky německého národa, stávají se německými státními příslušníky a podle předpisu zákona o říšských občanech z 15. září 1935 (Říš. Zák. I., str. 1146) říšskými občany. Pro ně platí tudíž také ustanovení na ochranu německé krve a německé cti. Podléhají německé soudní pravomoci. (2) Ostatní obyvatelé Čech a Moravy stávají se státními příslušníky Protektorátu Čechy a Morava.“[12]" více zde Takže v roce 45 nebyli odsunuti Českoslovenští občané, ale občané říše, kteří žili na území Československa a dobrovolně se přihlásili k Německému občanství. Všichni tady nebyli na pozvání Otakaram ale přišli v několika vlnách později. Pozváni rozhodně byli. Odsunuti rozhodně měli být, mohlo to být ještě horší.

    29.11.2023 10:14 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Schvalujes odsunuti nevinnych lidi za uplatneni principu kolektivni viny??? Schvalujes i nasilny (divoky) odsun? Je mi z tebe zle.
    29.11.2023 12:23 alkoholik | skóre: 40 | blog: Alkoholik
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Kdo se prihlasil k nemeckemu obcanstvi nebyl nevinny, ale vlastizradce.
    Bylo lepsi je odsunout nez popravit, ne?
    29.11.2023 12:45 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    K zadnemu obcanstvi se nikdo nehlasil. Vsichni to byli obcane ceskoslovenske republiky. Pokud se nekdo k necemu hlasil, byla to NARODNOST! Tu zjistovala republika behem scitani lidu. Z cechu se stali obcane protektoratu, z nemcu obcane rise. Nikdo se nikoho na nic moc neptal. Naopak slezane byli prohlaseni za risske nemce, i kdyz to nedavalo smysl.
    Kdo se prihlasil k nemeckemu obcanstvi nebyl nevinny, ale vlastizradce.
    Proc vlastizradce proboha? Ach jo, ten tvuj fanaticky etatismus...
    Bylo lepsi je odsunout nez popravit, ne?
    Ne, nejlepsi by bylo neuplatnovat kolektivni vinu a nechat ceskoslovenske obcany zit a hospodarit na jejich majetcich svobodne... Ale ne, hrdinove konce valky se vyradili na svych sousedech, mnohdy je i okradli... A zbytek dokonal pan president se svymi dekrety...
    29.11.2023 12:59 alkoholik | skóre: 40 | blog: Alkoholik
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ty me neznas a meles tu nesmysly o tom, ze jsem etatista? OK, dalsi blbec do blokovanych.
    29.11.2023 13:27 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Pardon, zda te to urazilo. Clovek, ktery nekoho oznacuje za vlastizradce, je co? Jak lze zradit stat? Pokud to citis, ze to lze, pak jsi kolektivista a etatista upozadujici jedince.
    29.11.2023 15:32 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Toto psal falesny Valgrind.
    30.11.2023 08:14 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Stejne to uz nevidi protoze jsi nas vsechny zablokoval :)
    28.11.2023 21:41 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jihočeši žádné "ti" nepoužívají (no dobře, jako třetí pád ve druhé osobě jednotného čísla, dejme tomu, ale zde se jedná o první pád množného čísla ve třetí osobě).
    Opravdovi jihocesi mluvili Nemecky, ale byli vyhnani novou republikou a dekrety pana presidenta.
    Jihočeské dialekty němčiny sice byly proslulé svou nesrozumitelností i mezi ostatními vyriantami Bayrisch, ale silně pochybuji že se v nich slovo Ti (v německé transkripci asi Tjü) nějak prominentně vyskytovalo, pokud vübec.

    Na rozdíl od jihočeských nářečí češtiny (před sto lety i dnes).
    Glee avatar 29.11.2023 02:39 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jihočeši žádné "ti" nepoužívají
    Jihocesi posrali pivo. :-)

    (no dobře, jako třetí pád ve druhé osobě jednotného čísla, dejme tomu, ale zde se jedná o první pád množného čísla ve třetí osobě)

    Ok. :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    Max avatar 29.11.2023 10:09 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ale no tak :). Samson se třeba vyšvihl. Dřív to byl patok, ale dnešní jedenáctka už je chválena. Budvar jede klasiku a jak je na tom Regent, to teď nevím.
    Tak jaképak kazení? :)
    Dej si místo těch plků raději pikador, nebo cmundu a bude dobře :).
    Zdar Max
    Měl jsem sen ... :(
    29.11.2023 10:16 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Budvar je statni ci narodni podnik, ten nepiji. Regent sel za posledni roky nahoru. #PikadoruCmundeAScheissceZdar
    Glee avatar 30.11.2023 03:24 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Budvar je statni ci narodni podnik, ten nepiji. Regent sel za posledni roky nahoru. #PikadoruCmundeAScheissceZdar

    Dej si Breznevaka a budes jak ta dvousecna koza z Futuramy. To uz radej ten Czechvar, posoudim snad brzy.
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    30.11.2023 09:51 karkar | skóre: 6 | blog: Kartrolling
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Czechvar je Budvar v americe. Ale teda nevim co to je ten Brežněvák...
    30.11.2023 12:07 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Patrne Breznak z Krasneho Brezna. :-D
    Glee avatar 1.12.2023 03:23 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Patrne Breznak z Krasneho Brezna. :-D
    Březňák je pivo a pivovar ve Velkém Březně u Ústí nad Labem s dlouholetou tradicí. Pivovar byl založen v roce 1753 ...

    Je dobre, ze se drzime Sudet. :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    1.12.2023 07:07 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    :-D A dekuji za osvetleni, odkud je Breznak. :-D
    Glee avatar 1.12.2023 03:21 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Czechvar je Budvar v americe.

    No shit, bratan!

    Brežněvák

    Brežněvák. Viz nize. :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    1.12.2023 14:12 karkar | skóre: 6 | blog: Kartrolling
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    No shit, bratan!
    Nerozumět hluku tvého kmene. ...příjde mi to že nesouhlasíš, takže: tutaj kukni
    Glee avatar 2.12.2023 01:49 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Nerozumět hluku tvého kmene. ...příjde mi to že nesouhlasíš
    a) Facepalm emoji may be used in cases, when constructive humor is intended.

    b) Please always carefully read. Especially the paragraphs above.

    c) Always remind your opponents of points a) and b).

    Cerny na bilym, kze jako moje, pokud to uz nekdo nerek drive... ... Ugh...
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    4.12.2023 11:49 karkar | skóre: 6 | blog: Kartrolling
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    tvl kde je tam nějakej fascepalm, to zaprvý...

    Zadruhý napiš prosím česky co si myslel tím: "No shit, bratan" Hlavně to "bratan" je z nějaký tatarštiny, což bych si prosil přeložit do češtiny přednostně.
    Cerny na bilym, kze jako moje, pokud to uz nekdo nerek drive... ... Ugh...
    a zase píšeš jak tatar...

    Co tvl znamená "kze jako moje", a co tvl nikdo "neřek" jakože dřív... pro info to tvl znamená tyvole.

    Glee avatar 5.12.2023 02:18 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    tvl kde je tam nějakej fascepalm, to zaprvý...

    Zadruhý napiš prosím česky co si myslel tím: "No shit, bratan" Hlavně to "bratan" je z nějaký tatarštiny, což bych si prosil přeložit do češtiny přednostně.

    Cerny na bilym, kze jako moje, pokud to uz nekdo nerek drive... ... Ugh...

    a zase píšeš jak tatar...

    Co tvl znamená "kze jako moje", a co tvl nikdo "neřek" jakože dřív... pro info to tvl znamená tyvole.
    Vytecne zahrane! ... Ale pockat, ty jses Heroj co ma neco proti Tatarum!! :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    5.12.2023 06:07 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Bratan ... česky

    Si doplň vzdělání, bro.
    2.12.2023 07:41 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Viz John Cleese:
    9. Ta studená věc bez chuti, u níž trváte na názvu pivo, vlastně pivem vůbec není. ... Americké značky budou označovány jako polozmrazená komáří moč, takže všechny tyto nápoje mohou být nadále prodávány bez rizika záměny.
    4.12.2023 11:52 karkar | skóre: 6 | blog: Kartrolling
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak o tom žádná, ten czechvar byla ale poměrně dobrá volba, zejména když zrovna neměli v likérstóru jakousi plzeň...
    Glee avatar 30.11.2023 03:00 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Samson se třeba vyšvihl. Dřív to byl patok, ale dnešní jedenáctka už je chválena.
    Ale tak... chvalena je dnes i kdejaka zeme, nebo stat, ze? :-)

    Budvar jede klasiku
    Access Denied! Posralo se to prave nejakych 20 let zpet. Nezbyva nez po par letech ty patoky asi znova vyzkouset, no...

    Dej si místo těch plků raději pikador, nebo cmundu a bude dobře :).
    Pikador zamackni zpet, ale cmundu si dam rad vzdy. :)

    A bez nasich plku by se to tu asi zavrelo a prodalo v budoucnosti, rovnou s nami vybudovanejma psychologicke-jma prostorama! Nw. :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    30.11.2023 09:45 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Pikador zamackni zpet,
    Zrovna v neděli jsem v Bazileji viděl klasický český bazmek na párky v rohlíku. Akorát místo párku tam lili roztavený sýr a prodávali to jako Fondue Dog. K vidění online zde (celkem nic moc, ale co by člověk chtěl za 10 franků)
    ale cmundu si dam rad vzdy. :)
    Taky mají :-)
    Glee avatar 1.12.2023 03:25 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Akorát místo párku tam lili roztavený sýr a prodávali to jako Fondue Dog.

    Proste jina varianta Ghetto Pizzy. :-D
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    Gréta avatar 29.11.2023 17:28 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ty farářové maj poslední dobou fakt problémy, asi je posednul ďábel, nebo něco takovýho, hele :-)

    přešli na novej druh bylinek hele :O :D :D ;D

    28.11.2023 01:57 karkar | skóre: 6 | blog: Kartrolling
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tý krávo, to je teda fakt hustý tvl.....
    Gréta avatar 29.11.2023 17:29 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    28.11.2023 06:39 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    víte co to je za skřípot? to jsou něčí zoubečky
    28.11.2023 09:18 prst na leve ruce
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    ze se nestydis, dva roky tu meles hovna o ukrajine ktery se prokazaly jako falesny, a ted mas tu drzost si hrat na experta na jiny konflikt. no kdyz se nestydis, tak ja se teda stydim za tebe a lituju kazdyho koho slepe podporujes, protoze ti to maji predem prohrany

    28.11.2023 10:38 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Asi mas pravdu - třeba jsem podporoval pimpa v jeho boji a už je fuč - škoda ho kluka ušatýho, byl to srdcař :/
    28.11.2023 12:22 prst na leve ruce
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    az tak je to spatny, co. no, smula, mel jsi poslouchat a nedivil by ses.
    28.11.2023 12:43 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Hele - četl jsem, ptal jsem se ho aby měl prostor obhájit si svoje tvrzení, těšil jsem se na neprůstřelné argumenty abych se poučil - a je fuč :/
    28.11.2023 13:58 prst na leve ruce
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    hele to vis, ono mit stale dokola pravdu omrzi. jedna vec ze jsi loupak. duha vec ze jsi loupak co nemel pravdu. bohuzel, realita je realita, taky bych na tvym mistae radeji zacal s cistym stitem na novym konfliktu, tam si muzes par mesicu vymyslet nez te dostihne realita.
    28.11.2023 14:38 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Co myslíš, že je lepší - když tě realita doběhne v případě že jsi neměl pravdu (jak to podle tebe asi čeká mě), nebo když před ní musíš furt zdrhat jako třeba chudák pimp a někteří další tady?
    28.11.2023 15:10 prst na leve ruce
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    to mi rekni ty, protoze oboje plati na tebe. co je lepsi?
    28.11.2023 15:23 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Je škoda, ze zase zdrháš :(
    28.11.2023 16:10 prst na leve ruce
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    jsem myslel že tu nejsem, tak si vyber )))) mas v tom dobrej maglajz ))
    28.11.2023 16:35 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    jako třeba chudák pimp a někteří další tady?
    28.11.2023 17:11 prst na leve ruce
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    ))))) a ja si myslel ze uz letos nic trapnejshio neuvidim, hlavne po ukrajinsky ofenzive
    28.11.2023 17:15 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    máš malý rozhled - asi ti uniklo třeba tohle
    28.11.2023 09:47 luky
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Super, proc to nema tucnaka?
    Max avatar 28.11.2023 11:45 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Pecka, toto bez tučňáku ani nejde, takže máš ho tam ;-).
    Zdar Max
    Měl jsem sen ... :(
    28.11.2023 11:56 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    +1

    Opatrne, aby nekomu z toho cevka nerupla. :-D
    Gréta avatar 29.11.2023 17:31 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    diky 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 🐧 :D :D :D :D

    snad se kuli tomu kolbáč ňák neurazí ale zase jako :O :D :O :D

    28.11.2023 15:29 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    sudo make install
    No jo no, Ubuntu/Debian zas nemá balíček, co? Já fakt nechápu, jak lidi tyhle distra tolerují, zejména to Ubuntu.

    Na pracovním PC, kde jsem pod hrozbou inkvizice nucen Ubuntu používat, to řešim Nixem. V tomhle případě by to ale asi nepomohlo, Nix sice raylib má, ale tahle věc určitě potřebuje (transitivně) grafickej driver a tam ta kooperace Nix → nativní balíčky je IIRC problém...

    S lepším distrem tyhle blbosti člověk nemusí řešit...
    28.11.2023 16:20 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Nic novýho, nix je póza a v praxi nefunguje jak člověk potřebuje víc než zkompilovat hello world.
    28.11.2023 21:18 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Huh? To není problém Nixu, to je obecný problém vzájemné (ne)kompatibility distribucí.

    Nejsem nějak extra fanoušek Nixu, jde to trochu mimo mě, nicméně umí toho celkem dost včetně komplexních věcí a balíčků má velké množství. Flakes je zajímavý koncept.
    29.11.2023 10:17 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Toto psal falesny Valgrind.
    30.11.2023 19:36 Valgrind
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To nemuzes dokazat.
    29.11.2023 13:49 Martin Tůma | skóre: 39 | blog: RTFM | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    No jo no, Ubuntu/Debian zas nemá balíček, co? Já fakt nechápu, jak lidi tyhle distra tolerují, zejména to Ubuntu.

    Vždyť se na tom balíčku "pracuje" teprve rok a půl, to je v Debianu úplné nic...

    Každý má právo na můj názor!
    Gréta avatar 29.11.2023 17:43 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    Já fakt nechápu, jak lidi tyhle distra tolerují, zejména to Ubuntu.

    prostě to funguje :D arch třeba potřebuje víc věčí skill na instalaci páč se prej třeba instaluje bez grafickýho rozhraní takže to asi jako neni žádná lidovka :D ;D

    30.11.2023 11:08 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    V pohodě, pokud ti to vyhovuje, proč ne.

    Jinak zápisek (technicky) pěkný, je chvalitebný, že všechny ty naalokovaný věci zase uvolňuješ, i když před returnem z main() to vlastně už je dost jedno. Ale best practices jsou best practices - zdroje je potřeba zase vrátit do systému - to se mi jako radikálnímu levicovému zelenému socialistovi samozřejmě líbí, to je taky jakoby malinká cirkulární ekonomika :-D :-D

    Jenom možná by bylo lepší v tom zápisku ten main.c a případně další soubory nedávat vždycky znova celej, ale udělat diff -u , aby bylo vidět, co se změnilo, ale jako není to žádnej moc velkej problém, takhle taky dobrý.
    Gréta avatar 1.12.2023 19:35 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    věci zase uvolňuješ, i když před returnem z main() to vlastně už je dost jedno.

    teroreticky by sme nemuseli na konci uvolňovat ani textury tou funkcí unload pokuď je současně nepouživá i ňákej jinej kontext nicmeně to sou asi jakoby ty druhy voptimalizací na kterejch moc neušetříš zato ale jako mužeš něco rozbít :D

    Ale best practices jsou best practices - zdroje je potřeba zase vrátit do systému - to se mi jako radikálnímu levicovému zelenému socialistovi samozřejmě líbí, to je taky jakoby malinká cirkulární ekonomika :-D :-D

    :D :D :D :D

    Jenom možná by bylo lepší v tom zápisku ten main.c a případně další soubory nedávat vždycky znova celej, ale udělat diff -u , aby bylo vidět, co se změnilo, ale jako není to žádnej moc velkej problém, takhle taky dobrý.

    jj něco takovýho přistě bude nutný páč se stala děsně divná věc ato že se ten blog prakticky locknul pro ňáký další editování páč je asi jako moc dlouhej (+-400kb) a háže to při ukladání ňákou java vyjímku :D věčinu blogu tvoří xkrát zkopirovanej +- stejnej zdroják takže by asi jakoby bylo dobrý se tomu podruhý ňák vyvarovat :D

    nvm jestli diff ale bude dost 'inkluzivní' třeba pro lidi který moc neprogramujou nebo nevěděj nic vo vyrábění her a si proto jako našli tendlecten 'tutorial' třeba ale holt to asi jako bude nutný :D

    2.12.2023 13:04 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    a háže to při ukladání ňákou java vyjímku :D
    Tohle mi ábíčko typicky dělá, když text obsahuje non-BMP znaky - jako třeba emojis - takže možná (jen hopytéza) se stalo to že ti to převedlo entity na unicode znaky, na kterejch si pak java vylámala zuby...
    Gréta avatar 4.12.2023 21:43 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    todlecto tam vyloženě vypisovalo ňáký dvě děsně velký čisla a byl mezi nima znak '<' a jedno bylo hezky kulatý se samejma nulama takže to spíš jako vypadá na ňákej limit kterej se nehlídá při vkládání zapisku ale až při editaci asi :D

    emoji a tydlecty tady taky vobčas zloběj to máš pravdu :D :D de je sem nacpat asi jenom jako html kód noa kdyby si třeba ňákej blogisek kde máš použitý emoji votevřel pro editaci tak ti to tady ty html kódy z ňákýho duvodu tajemnýho nahradí unicode znakama noa to pak dělá ty problémy s ukládáním resp. nejde to s nima uložit :D :/ :D :/ řešim to tak že mam blogisek napsanej v *.txt bokem a sem ho pak jako hotovej vkládám a nahrazuju s nim komplet puvodní text blogu tady v html editoru (včetně těch samonahrazenejch unicode znaků pro emoji) :D

    Darth Phantom avatar 13.12.2023 13:37 Darth Phantom | skóre: 18 | blog: Kelvin_Fitnick | Doma
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Já jsem se těšilo na Rande na rypadle II., ale todlencto je taky jako ůplně suuprový :). A HW nároky budou baj vočko jaký? Aby si to kolikomunistáč moh zapařit na Thinkpadu 380 :))). Von teďko humanizuje příspěvky, tak nemá čas xDDDD
    Tahle patička nemá hlavu ani patu
    28.11.2023 17:38 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Moc parádní dílko, jako pokračování bych navrhoval prequel v dobách biblických, je k tomu dost bohatá dokumentace:
    „Když před Izraelem utíkali a byli na bétchorónské stráni, vrhal na ně Hospodin z nebe balvany až do Azeky, tak umírali. Těch, kteří zemřeli po kamenném krupobití, bylo více, než těch, které Izraelci pobili mečem.“ (Joz 10,11);

    „Tak vybil Jozue celou zemi, pohoří i Negeb. Přímořskou nížinu i srázy, a všechny jejich krále. Nikoho nenechal vyváznout, vše, co dýchalo, vyhubil jako klaté, jak přikázal Hospodin, Bůh Izraele.“ (Joz 10,40);

    „Ajského krále dal pověsit na kůl, kde byl až do večera. Když slunce zapadlo, rozkázal Jozue, aby sňali jeho mrtvé tělo z kůlu. Pohodili je u vchodu do městské brány a navršili nad ním velikou hromadu kamení, která tam je až dodnes.“ (Joz 8,29).
    Max avatar 28.11.2023 20:06 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To zní docela ublíženě, na to, že blog je jen velmi povedená satira :)
    Zdar Max
    Měl jsem sen ... :(
    29.11.2023 20:00 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Právě naopak, já jsem se velmi dobře pobavil. A David určitě dobře ví po jakém králi nese jméno ;-)

    Ono je dobré znát historii, protože se pořád opakuje:

    https://www.novinky.cz/clanek/zahranicni-blizky-a-stredni-vychod-drahy-svete-staci-vam-to-jako-dukaz-izraelci-ukazali-vybaveni-tunelu-pod-nemocnici-sifa-40451809

    Jako důkaz čeho? Že vězni v koncentračním táboře dokáží zorganizovat ozbrojený odpor? Někdo, kdo zná historii, by si mohl vzpomenout třeba na Sobibor. A také jak dopadli ti, kteří z něj neutekli.

    A nebo tohle:

    https://www.seznamzpravy.cz/clanek/zahranicni-radikalni-osadnici-uz-nevyhaneji-jen-palestince-na-rade-jsou-armeni-240340

    Jak vidno, izraelští fašisté si se svými tureckými protějšky nijak nezadají, nakonec by si Netanyahu a Erdogan mohli padnout do náruče.

    Našly by se i další podobnosti:

    https://www.seznamzpravy.cz/clanek/zahranicni-propusteni-palestinci-se-vraci-domu-veznili-je-za-hozeni-kamene-lici-240500

    Jeden má Palestince, druhý Kurdy, zdi staví oba a bombardují i vězní je také stejně. Za hození kamene na tank roky vězení bez soudu, a může to být i desetiletý kluk.

    Zrovna tak tohle se pořád opakuje:

    https://www.seznamzpravy.cz/clanek/zahranicni-vidite-valecne-zlociny-jen-jedne-strany-vycita-cesku-sef-hrw-240505

    I já jsem tu už u několika konfliktů opakoval: "Je příliš snadné ignorovat zločiny jedné strany." A také: "Kdo chce válku, posílá zbraně." Jedno které straně. Což platí vždy a všude.
    29.11.2023 23:10 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A také: "Kdo chce válku, posílá zbraně." Jedno které straně. Což platí vždy a všude.
    Jjj, vzpomínám si, jak jsi tady v době po Majdanu ostře kritizoval dodávky zbraní z Ruska na Donbas...
    30.11.2023 04:07 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    V době kdy pravoseci upalovali lidi, armáda bombardovala civilisty a opolčenci obsazovali místní vojenské základny, některé bez jakéhokoliv odporu? Kdy sundavali tanky z pomníků, protože Putin jim nechtěl poslat ani patronu?

    Tenkrát bylo vtipné spíš to ani nemusel, protože jediná ukrajinská munička byla v Lugaňsku, a měla na skladu celkem solidní válečné zásoby ;-)

    Ale spíš si vzpomeň jak někteří pevně věřili na ruskou invazi dírou vystříhanou v drátěném plotě, a dokazovali jí videem ruské tankové kolony, natočeným o několik let dříve na cvičení, odehrávajícím se o pár tisíc kilometrů východněji :-D
    30.11.2023 08:57 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Proč by jim tam Putin posilal patrony když jim tam poslal rouvnou girkina s jeho plnou podporou (včetně buku kterým pak ten idiot sundal mh17)
    Max avatar 30.11.2023 09:17 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Myslíš tu kauzu dovolená? Tj. tu invazi v roce 2014 nebo 2015, kterou sám Putin potvrdil, ale obhajoval jí jako "naši vojáci jsou na dovolené" (včetně techniky samozřejmě)? :D A pak ti "dobráci" sundali civilní letadlo a ještě se tím chlubili?
    Zdar Max
    Měl jsem sen ... :(
    30.11.2023 13:04 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Kdyby jen obhajoval - myslím, ze i nějaká medailička byla
    30.11.2023 22:13 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    S tím letadlem opatrně, nezapomeň že Buk s číslem 312 je stále ve stavu ukrajinské armády. Akorát rakety jim už došly.
    30.11.2023 22:43 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To je naprosto v pořádku - víš snad ze ten buk co mh17 sundal byl nakonec identifikován jako buk 332 - nebo ti to (zase)nějakým omylem uniklo?
    1.12.2023 12:05 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jeden bit špatně - to se stává když chybí samoopravný kód nebo alespoň paritní bit.
    Max avatar 1.12.2023 02:20 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ty už se v těch lžích úplně ztrácíš.
    • Mezi 23. a 25. červnem 2014 přepravila ruská 53. protiletadlová raketová brigáda řadu vozidel na pozice v blízkosti hranice s Ukrajinou. Mezi těmito vozidly byl i Buk 332.
    • Dne 17. července 2014 se tento Buk 332 nacházel již na území Ukrajiny. V Doněcku byl naložen na červený podvalník, na kterém přejel na východ do města Snižne.
    • Po příjezdu byl Buk 332 vyložen a po vlastní ose přejel na jih na pole mimo město.
    • Buk 332 vystřelil raketu, která sestřelila letadlo MH17.
    • Ráno 18. července 2014 byl tento Buk 332 natočen při průjezdu městem Luhansk. Je zřetelně vidět, že mu chybí jedna raketa.
    • Buk 332 se vrátil do Ruska.
    • 21. července 2014 představilo ruské ministerstvo obrany řadu vymyšlených či zavádějících informací o dráze letu MH17, údajích z radarů, místu natočení videa v Luhansku z 18. července 2014, včetně špatně datovaných či značně upravených satelitních snímků.
    • Nebyly předloženy žádné důvěryhodné důkazy podporující tvrzení, že by se v oblasti nacházel 17. července 2014 jakýkoli ukrajinský Buk
    A to ještě do toho nepočítám, jak se Rusové na "dovolené" radovali z toho, že sestřelili "nějaké" letadlo. A shodou okolností jediné letadlo, co v tu dobu bylo sestřeleno, bylo MH17.
    A ty nám tu budeš vyprávět pohádky o 312 :D.
    To jsi takový fanatik, nebo dostáváš za ty plky i výpalné? :).
    Zdar Max
    Měl jsem sen ... :(
    1.12.2023 05:54 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    myslíš, že tu svoji vezri ráďa podpoří nějakým hezkým obrázkem, nebo videjkem? bylo by škoda kdyby zase jen tak zmizel
    1.12.2023 08:07 Tim
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Maxi to neni fer proti kremrolim oponovat faktama :-) Se zase urazi a mesic neukazou. Prilezou az zas nekde rusak dostane fest na prdel (jako dnes v Avdiivce) a budou zase mlzit :-)
    Max avatar 1.12.2023 12:40 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A ještě další důkaz místo slibů: MH17-The-Open-Source-Evidence-EN.pdf.
    Zdar Max
    Měl jsem sen ... :(
    1.12.2023 17:52 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    doufám, že ho to moc nerozhodilo a ještě se ukáže - byla by to škoda
    2.12.2023 08:08 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Samozřejmě Maxi, ale jen pokud odignoruješ další zaručeně pravé fotky Buku prchajícícho na traileru, na kterých má číslo 312, a další, kde má číslo zamalované. Stále bez jedné rakety. A některé z nich, kde se vyskytuje černá dodávka, stejná jako v té době používala SBU ;-)

    Mimochodem, kde to že byly umístěné ty ukrajinské Buky pár dní před sestřelem? Oni sice pak tvrdili že nebyly, ale chlubili se tím tenkrát i na vládním webu. Možná to tam je dodnes, hledat to už nebudu. A jak říkám, Buk s číslem 312 je stále ve stavu ukrajinské armády...

    Jo a hele, prohlédni si pořádně fotky těch trosek, a zamysli se nad tím proč na poskládaném předku při focení novináři nebyla umístěná střecha nad levým pilotem, a ležela jenom s ostatním šrotem na podlaze kdesi vzadu. A proč na pravé straně kabiny nejsou vytlučená okna. Ta raketa totiž přiletěla nikoliv zepředu ale zprava, příliš zprava.

    Ještě bys mohl zmínit ten Buk ukořistěný povstalci, kterým bez radaru lze sestřelit letadlo do výšky cca 5 km za přímé viditelnosti, s ručním řízením. Ale v deseti kilometrech nad mraky?

    Ohledně Rusů na dovolené je spíš zajímavé to prohlášení Kolomojského, že chystá pro Porošenka "překvapení s letadlem". Tenkrát jsme mysleli že koupil ty americké vrtulníky, jak zveřejnili video z poletování nad Ukrajinou (mimochodem falešné stejně jako videa s duchem Kyjeva), ale nekoupil. Potom přišlo jiné překvapení, větší.

    A když už máš ty zdroje tak nastudované, je tam někde proč to letadlo udělalo oblouk vlevo mimo koridor? To by mě totiž dost zajímalo.
    2.12.2023 09:18 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    nějaký zdrojík by nebyl? alespoň malinký... úplně malilinkatý? ani trošššššiiiilllliiiiinnnkkkuuuu úplně malilinkatý?

    ale aby přežil alespoň vteřiny hledání na google, duckduck, nebo alespoň Yandexu prosím
    Max avatar 2.12.2023 11:12 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Já dodal zdroj, co ty? Budeš si dál vymýšlet? A ta argumentace s poškozením? To jako fakt? To jako když raketa letí z nějakého směru, tak to letadlo musí být poškozeno přesně v tom místě? Chceš jako říci, že když vypálím na letadlo zezadu,tak to musí dostat ocaska a když to dostane kabina nebo trup, tak to nemohlo přiletět zezadu? To myslíš vážně? A to, jak se Rusové (separatisti) chlubili sestřelením letadla, to nic? To také budeme ignorovat? Budeme i ignorovat výpověď separatisty "Alexandr Chodakovskij", který potvrdil existenci Buku na straně separatistů? Budeme ignorovat, že nezávislé vyšetřování zjistilo, že raketa byla vystřelena z ruskem/separatisty ovládaného území? Budeme i ignorovat závěr nezávislého vyšetřování? Budeme si tu nalhávat, že všichni lžou, jen Rusko má pravdu?
    Ne, opravdu ne. Tvé konspirační teorie založené na tom, že Rusko má za každou cenu pravdu a všichni ostatní lžou, to si bašti sám.
    Zdar Max
    Měl jsem sen ... :(
    2.12.2023 13:03 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ještě je ve hře varianta, ze rada kope za Ukrajinu - ta hromada proruských pič…n co sem naházel a ze kterých pak nepřežila střet s realitou žádná (pokud jsem něco nepřehlédl) by tomu i nahrávala. Víš kolika lidem to tady mohlo pomoc rozšířit obzory?
    3.12.2023 12:45 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Já nevím nakolik je to typické, ale nejvíc mi tu rozšířila obzory paní učitelka.
    3.12.2023 15:52 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    ta to brala spíš přes emoce, ráďa to zkouší "argumentama"...
    3.12.2023 22:07 Want
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    Těžko dodáš odkaz na zdroj tam, kde se nepohodlné zprávy, které by se mohly za nějaký čas považovat za důkazy likvidují. To je jedna věc. A druhou je dnes tak oblíbená nálepka "dezinformace".

    Pokud jde o sestřelení toho letadla. Nevím kdo ho sundal, ale vím že v té oblasti nemělo co dělat, takže za mne jsou jednoznačnými viníky ukrajinci. A s tou Bučou je to také z mého pohledu sporná záležitost. Ne v tom, že se to stalo, ale v tom kdo, komu a proč to udělal. Je totiž velice snadné popravit tzv. proruské kolaboranty a pak je vydávat za oběti ruské agrese.

    3.12.2023 22:15 Want
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A nemusíme chodit až na Ukrajinu. Stačí vzpomenout případ otrávené Bečvy. Kamarád, který zná místní situaci ještě ten večer, kdy se o tom objevila první zpráva, mi podrobně líčil odkud to podle něj přiteklo. A to, že nebyla vůle odebrat vzorky včas jednoznačně ukazuje prstem na Babišovy pohůnky.
    4.12.2023 06:16 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Kdo v té oblasti něměl a nemá co dělat je rusko - to je úplný základ. Tím pádem je vino rusko. Kor když ten buk 332 je jejich...

    A problém dost často není ani tak absence zdrojů, ale to, že ty zdroje se většinou ukážou jako fake na úrovni mateřské školy a jakýkoli dotaz na jejich relevantnost a obhajobu končí buď pokusem o odvedení diskuse jiným směrem, nebo útěkem jejich předkladatele z diskuse...
    5.12.2023 06:39 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ehm, přečti si to ještě jednou a pořádně. JÁ JSEM POTVRDIL existenci Buku na straně separatistů. Část komplexu ve funkčním stavu měli.

    To vyšetřování bylo nezávislé asi tak stejně jako Warrenova komise, takže si vezmi papír a tužku a nakresli si koridor, ze kterého MH17 vyletěl doleva, opsal oblouk a z levé/severovýchodní strany se do něj vracel. Přesně ti to neřeknu, protože údaje se na Flightradaru tenkrát dost rychle měnily, ale mohl to být úhel tak 30°. Potom si k němu nakresli raketu, nějakých 70-80° zprava zepředu (hlavice vybuchla před levým oknem, prvnímu pilovovi přímo do ksichtu). Porovnej to s nákresem v té tvé zprávě - je potřeba vědět jak ta hlavice funguje, že fragmenty směřují přibližně kolmo ke směru jejího letu, a vidět fotky trosek, nejlépe ještě na místě nálezu.

    No a potom si zkus zpětně promítnout možnou trajektorii letu rakety, přičemž musíš vzít v úvahu fungování řídícího systému, Buk je totiž lstivá mrcha, nesleduje cíl po psí křivce jako staré typy, ale "nadbíhá" mu, jako by se ho snažil předletět. A nezasahuje přímo ale zvrchu, kde je nejměkčí část letadla - pilot. Nemá smysl dělat důlky do pancířů.

    Jo, a zamysli se nad tím jak jsem tu několikrát psal "že lžou Rusové víme všichni". Problém je že ostatní lžou ještě víc. Takže na zdroj se zeptej Winstona Smithe.
    5.12.2023 08:18 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Takže na čísílka 312 a podobně už nechceš hrát?

    Max avatar 5.12.2023 08:53 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jasně, všichni lžou a nikdo se nikdy neprokecne :D. A to ani v době, kdy je whistleblowing zakotven v zákoně.
    Nicméně letecký a raketový inženýr Radovan má jasno :D. On byl totiž na místě a analyzoval trosky :D.
    Hele, vážně si ty pohádky nech třeba na Facebook.
    Zdar Max
    Měl jsem sen ... :(
    5.12.2023 10:22 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    kdy je whistleblowing zakotven v zákoně
    Nestyd se napsat hezky cesky "praskacstvi".
    1.12.2023 09:43 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    V době kdy pravoseci upalovali lidi, armáda bombardovala civilisty a opolčenci obsazovali místní vojenské základny, některé bez jakéhokoliv odporu?
    Jo, protože bombardování civilistů / civilních cílů RF aktuálně vůbec nedělá žejo...

    No ale to je jedno, bylo mi jasné, že to tvoje "Což platí vždy a všude" tak úplně vždy a všude platit nebude a dál asi nemá smysl to řešit :-D
    2.12.2023 08:09 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jak můžeš vidět aktuálně v Gaze, i tom bombardování civilistů jsou Rusové prostě žabaři.
    2.12.2023 11:26 Zelena je trava
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Coze? Od invaze na ukrajinu maji rusaci na rukou krev asi 40000 civilistu zabitych, kolem 80000 ranenych a 20000 odvlecenych a ty tady chces neco porovnavat? Pripocitej si k tomu i mrtve rusy kteri by dal mohli zit kdyby Putin nerozpoutal valku. Vam v tom Kremlu uz nacisto jebe ze si myslite ze vam ty lzi jeste nekdo zere?
    Glee avatar 4.12.2023 02:20 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Od invaze na ukrajinu maji rusaci na rukou krev asi 40000 civilistu zabitych, kolem 80000 ranenych a 20000 odvlecenych
    Prodam gauc s kocickou se zvoneckem. Zn.: Kydsi na tom gauci sedaval vrchni stab SOHRu
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    5.12.2023 05:46 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Vymlácená makovice ti vzkazuje:

    https://www.novinky.cz/clanek/valka-na-ukrajine-musime-prestat-lhat-valka-je-v-patove-situaci-prohlasil-klicko-40452984

    Ale chybí ti tam také 10000 dětí zabitých ukrofašisty na Donbasu od roku 2014, 200000 ruských tanků, které tenkrát projely dírou v plotě a ukrajinské dělostřelectvo je rozstřílelo tak, že po nich nezbyl ani šroubek, dvakrát, a 9999999999999999999 dolarů ze západní "pomoci", které zmizely neznámo kam.
    5.12.2023 08:09 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Opatrně s těma čísílkama - už pimp ti tady kdysi neprozřetelně dokázal, že počet obětí zabitých tak ru, tak ua dohromady byl cca 4000 včetně girkinem sundaným mh17 - tak abys tady nebyl za blbečka
    6.12.2023 07:15 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jistě, na základě Ukrajinci vytvořených údajů, takže GOTO 153:

    Musíme přestat lhát...
    6.12.2023 07:45 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To se domluv s pimpem - ten ti tady do toho hází vidle
    2.12.2023 13:36 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jak můžeš vidět aktuálně v Gaze, i tom bombardování civilistů jsou Rusové prostě žabaři.
    V tom případě sis tady neměl co stěžovat na bombardování Donbasu Ukrajinou, protože to byla ještě podstatně větší žabařina než min(Rusko, Izrael).

    Ale jasný, chápu, výjimečka pro Rusko je vždy potřeba najít.
    5.12.2023 05:57 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jak šel čas:

    "Dejte nám zbraně a za dva týdny dobudeme Moskvu,"

    "Dejte nám zbraně a za měsíc budeme u Azovského moře."

    "Dejte nám zbraně nebo budou muset bojovat vaši občané."

    Protiofenziva nepřinesla očekávané výsledky. Bojujeme proti druhé nejlepší armádě na světě, připustil Zelenskyj

    Aneb od hajlování k fňukání :-P
    5.12.2023 08:10 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ano, je to přesně jak tady píšu už od začátku toho ru svinstva - za případnou prohru Ukrajiny budeme moc my - Ukrajina to bez pomoci nezvládne, s pomocí nemůže prohrát.
    5.12.2023 11:34 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Změna tématu? :-D
    Protiofenziva nepřinesla očekávané výsledky. Bojujeme proti druhé nejlepší armádě na světě, připustil Zelenskyj

    Aneb od hajlování k fňukání :-P
    No tak jelikož západ těch zbraní až tak moc nedodal, tak tohle je celkem očekávatelné, ne? Takže teď bude Ukrajina opět přecházet do obrany a když to půjde dostatečně špatně, bude příležitost otestovat tvoje hypotézy o tom, že RF nemá zájem Ukrajinou postupovat moc daleko na západ, a zjistit, jestli ses ohledně Ruska opět mýlil.
    5.12.2023 16:00 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    západ těch zbraní až tak moc nedodal
    Ukrajina jich az tak moc nezaplatila (ani na dlouhodoby uver).
    5.12.2023 17:24 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To je ovšem hrůza. Předpokládám, že až nás někdo napadne, budeme hbitě a bezproblémově cálovat za veškerou pomoc poskytnutou spojenci. Tedy pokud se rovnou nevzdáme, protože bránit se znamená zbytečně prodlužovat konflikt...
    5.12.2023 19:14 plostenka | blog: plstnk
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Az nas nekdo napadne, tak se seberou vsechny sily NATO a umlatime toho parchanta nasima mundurama pro tehotny tankistky.

    Od toho v tom spolku jsme...
    6.12.2023 07:18 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Zatím spíš západ platí Ukrajině :-D
    Darth Phantom avatar 12.12.2023 14:59 Darth Phantom | skóre: 18 | blog: Kelvin_Fitnick | Doma
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    No tak jelikož západ těch zbraní až tak moc nedodal,

    Tak takhle bych to určitě neřekl. To byly vůbec největší zbrojní dodávky snad od druhý světový (lend-leasu), který přesáhly 100 miliard dolarů. A takovej třeba obyčejnej dělostřeleckej granát stojí okolo 2000 říšských marek 4. říše (€). Měsíčně jich vystřelí Ukrajina cca 200k, teď teda už asi míň. Tohle si nemůže dovolit financovat dlouhodobě nikdo. EUSSSR si právě dal socialistický závazek na dodávku děl. granátů, který ale nesplnil. Nicméně EUSSR prorazí na poli humanismu a porazí Putlera přijmutím doktorů a inženýrů, a až doputuje do Kremlu svěží vzduch z Green dealu bez nadbytečného CO2, tak Vladimíra Adolfoviče z toho klepne.

    A ta válka dospěla dávno do fáze, kdy je to v podstatě poziční mjasorúbka (mlýnek na maso). To prorokoval na začátku baťka Lukašenko s tou mjasorůbkou a měl pravdu. Životnost nějaký techniky na bojišti se počítá v řádech minut (do deseti minut tam přiletí dron s granátem) a to platí vícméně pro obě strany a týká se to dá se říct i pěších jednotek. s. z Horní dolní tady konstruoval vítězné drony a ejakuloval u toho, ale v současnosti je situace taková, že Rusko má v dronech převahu 1:5 a tuhle informaci jsem zaznamenal dokonce někde na ČT.
    Tahle patička nemá hlavu ani patu
    12.12.2023 16:30 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Prázdná kasa, prázdné sklady.

    https://www.seznamzpravy.cz/clanek/zahranicni-zelenskyj-v-usa-odvraci-putinuv-sen-kyjev-nevi-jak-bude-platit-valku-241511

    Ale naštěstí Rusku do tří týdnů dojde munice a do měsíce díky sankcím zkrachuje, věříme tomu už od loňského února...
    28.11.2023 20:40 vtip
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ptá se izraelský generál nejvyššího rabína: "Jak tahle válka skončí?"

    "No, buď to půjde přirozenou cestou, nebo se stane zázrak", odpoví rabín.

    "A co je ta, pro Izrael, přirozená cesta?"

    "Na nepřátele začnou z nebe padat kameny a oheň, přijdou kobylky a ty jim sežerou zásoby, všichni nepřátelští vojáci budou raněni slepotou a zbraně jim během jedné minuty zrezivějí", říká rabín.

    "A co je tedy potom ten zázrak?" ptá se generál.

    "No, že ta hrstka našich vojáků pomocí zbraní a vlastní síly zvítězí proti tak obrovské přesile nepřátel."
    Gréta avatar 29.11.2023 17:45 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    29.11.2023 19:34 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Hitler je tak zoufalý z nezdaru invaze do Anglie, že zajde za berlínským vrchním rabínem, že když mu prozradí, jak to Mojžíš udělal, že se před ním rozestoupily vody Rudého moře, tak zastaví všechny represálie proti Židům.

    Rabín mu tedy prozradí, že to Mojžíš učinil pomocí kouzelné hole.

    "Taková hůl kdyby existovala.." zatouží Hitler.

    "Ale ona existuje" odpoví rabín.

    "A kde je?" zeptá se tedy Hitler.

    "V Britském muzeu."
    Glee avatar 3.12.2023 02:53 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    "V Britském muzeu."

    Indeed, ale to uz je rozlite mleko. Dokonce mene, nez Kodax Gigastis. Pardon, Codex gigas, T9, znas to...

    Prodam byt v Gaza City, Zn.: V SVJ je to samej magor a stat me ruinuje
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    30.11.2023 10:46 HonzRez | skóre: 4
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    V tom výčtu nových zbraní chybí nutella...
    Gréta avatar 1.12.2023 20:04 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    pan profesor nutella mi tam moc neštimmuje s nim dyštak vyrobim něco těsně pár dní před ňákejma volbama by to jako uďálo nejvěčí škody :D

    xkucf03 avatar 30.11.2023 17:34 xkucf03 | skóre: 49 | blog: xkucf03
    Rozbalit Rozbalit vše Re: David a duchové
    Skvělá hra i článek, tučňáka si právem zaslouží. Doufám, že budou další verze – by z toho časem mohlo být něco jako Prince of Persia, akorát košer :-)
    Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
    30.11.2023 19:46 Applejack
    Rozbalit Rozbalit vše Re: David a duchové
    Jenom aby to nekdo nehral jen kvuli poteseni z pohledu jak hlavni hrdina chcipne :-) Treba Greta po nejakem smazanem blogu...
    Gréta avatar 4.12.2023 21:47 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové

    davidoj nic špatnýho nepřeju páč asi jako uplně nemuže zato co dělá :D

    btw kdyby david skutečně běhal v uniformě idf někde po jeruzalému a bojoval se zlejma duchama by sem mu navopak přála ať se mu jako daří :D ;D

    Gréta avatar 4.12.2023 21:51 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové
    by z toho časem mohlo být něco jako Prince of Persia, akorát košer

    to je ale spíš taková jakože logická roguelike hra sem koukala :O :O sem spíš měla přectavu vo ňáký jakože akční hře nicmeně vidim tam věci který by se asi jako možná mohly z toho prince vykrást :D

    =^..^= AmigaPower® avatar 2.12.2023 08:31 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Hele Gréto, nejseš ty SADAM? Ten jel tyhle píšoviny, jako Lorda Hoven a jeho eshop :-D Jinak teda za blogísek dávám +1 :-D

    BTW: Ten Robertův vendelínskej skin to pěkně rozsypává...
    2.12.2023 11:29 BLEK.
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Zkus browser z tohto tisicileti :-)
    =^..^= AmigaPower® avatar 2.12.2023 22:51 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    FF 120.0.1
    3.12.2023 08:38 BLEK.
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Rekl jsem browser ne nejaky abandonware od Netscape kde jen 25 let mazou radky kodu aby to stale jeste slo skompilovat :-)
    =^..^= AmigaPower® avatar 6.12.2023 14:26 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Opera a Chromium, co tam máš dál falešnej BLEKU? ;-) Explorer?
    Glee avatar 3.12.2023 02:55 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    SADAM
    Zimak byl to nejelegantnejsi hovado na tomto portalu, co si pamatuju...
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    3.12.2023 18:15 Zum
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    By me zajimalo co ti to tu prinasi a kdyz te to teda bavi proc se treba neposunout v nejakem hernim tymu?
    =^..^= AmigaPower® avatar 6.12.2023 14:34 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    - Přináší mi to příjemně hřejivý pocit mezi srdíčkem a varlátky

    - poslal jsem si přihlášku do repre, ale ten čůrák Bílek mi ani neodepsal
    Gréta avatar 4.12.2023 21:29 Gréta | skóre: 37 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    nejsem :D :D

    ze sadámů navic znám jenom tamtoho voběšenýho diktátora :D ;D

    =^..^= AmigaPower® avatar 6.12.2023 14:29 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Seš SADAM vole, mně je to úplně jasný...
    Max avatar 6.12.2023 14:32 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Zases chlastal :)? Jasně má ve jméně Gréta a ta fotka také souhlasí. Není tedy pochyb, že to SALÁM být nemůže :).
    Zdar Max
    Měl jsem sen ... :(
    =^..^= AmigaPower® avatar 6.12.2023 14:36 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Je to SADAM, nikdo jinej nevěnoval podobnejm píčovinám tolik času a energie, vzpomeň si jenom na ten eshop s hovnama, celý to napsal a regnul na to doménu :-D
    Max avatar 6.12.2023 15:30 Max | skóre: 72 | blog: Max_Devaine
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    SADAM skončil v roce 2010, z té doby si pamatuji tak kačera, co jsem za sebou tahal :)
    Zdar Max
    Měl jsem sen ... :(
    =^..^= AmigaPower® avatar 6.12.2023 21:56 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    No právě...
    xkucf03 avatar 6.12.2023 20:43 xkucf03 | skóre: 49 | blog: xkucf03
    Rozbalit Rozbalit vše LordHoven
    Příloha:
    Myslíš tohle? To byly časy :-D
    https://web.archive.org/web/20090725082432/http://lordhoven.cz/
    Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
    =^..^= AmigaPower® avatar 6.12.2023 21:55 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: LordHoven
    Joooooó :-D
    Glee avatar 7.12.2023 02:21 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: LordHoven
    Dodelal nekdy ten CAD?
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    7.12.2023 15:15 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: LordHoven
    To byl taky on? Jsem moc neměl přehled ani v té době, natož teď.

    V každém případě zpětně pročítat ty blogy je poměrně depresivní...
    Glee avatar 8.12.2023 02:12 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: LordHoven
    To byl taky on?
    V cem nemel svoje spinave Vladimir Usamin prstiky ze? :-)

    V každém případě zpětně pročítat ty blogy je poměrně depresivní...

    Me ta doba bavila. :-) Ale jestli mas neco uplne konkretniho, tak se rad podivam, muzu to samo vnimat upe jinak dneska. mahTilda 15 let neni malo ani pro zelvu. :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    =^..^= AmigaPower® avatar 9.12.2023 14:54 =^..^= AmigaPower® | skóre: 30 | blog: BLB | Praha
    Rozbalit Rozbalit vše Re: LordHoven
    Jo, dodělal a začal se živit tim hliníkem... Je to fakt frajer!
    Glee avatar 9.12.2023 16:05 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: LordHoven
    Jo, dodělal a začal se živit tim hliníkem... Je to fakt frajer!

    Dikes. Svaty howno tvl stejne, to je kolik! Nenadarmo sa na nas vsechny vysral. :-D
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    4.12.2023 11:17 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Komunismus v praxi…
    Glee avatar 6.12.2023 01:21 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Komunismus v praxi…
    To je fakt! Kibuce roz... coze, tvl???!! #aninahodou!

    Yo, a byl driv utlak silnejsich, nebo prevalence spojenych? Jo a asi novy PsyOps se v mediich rychle rodi...
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    6.12.2023 07:14 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Odhadnete nekdo co chtěl glee sdělit?
    6.12.2023 07:20 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Jeden článek řetězu, který nechápeš:

    https://jaroslavjonas.blog.idnes.cz/blog.aspx?c=311791
    6.12.2023 07:58 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Co to má společného?
    6.12.2023 09:27 Rav
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak na abicku musi byt jakykoli funkcni model komunismu par jedinci veleben :-) Model kibucu byl jedinym uspesnym komunistickym pocinem a mohl fungovat jen proto ze nebyl rizen hamiznymi ateisty ale s pomoci Vsemhouciho vyvolenym narodem! :-)
    Glee avatar 7.12.2023 02:19 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Tak na abicku musi byt jakykoli funkcni model komunismu par jedinci veleben :-)
    Ale neee. Ja jen narazel na to idnesovske podtrzitkovske radoby disidentovani ve forme nepricetnych one-lineru ohledne chapani toho, co ze je a neni komunismus (kdyz uz spojuje ne-vzdy-nutne-spojitelne). Ale uz zabalil spacak a sel domu spat pred skoro asi tejdnem a neco...
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    7.12.2023 06:20 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ohledně té hamižnosti... :-D:-D:-D

    Teda, jak to v tom blogu popisuje, moc úspěšné ty kibucy nebyly.

    Bolševici v Sojuzu teda vydrželi déle.
    7.12.2023 06:23 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ohledně té hamižnosti vyvoleného národa... :-D:-D:-D

    Ale jak to v tom blogu popisuje, zase tak moc úspěšné ty kibucy nebyly.
    7.12.2023 06:25 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ohledně té hamižnosti vyvoleného národa... :-D:-D:-D
    7.12.2023 09:38 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Sorry byl jsem opilej.
    7.12.2023 12:48 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To byly spíš ty lentilky co ti dal glee…
    Glee avatar 8.12.2023 01:52 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To byly spíš ty lentilky co ti dal glee…

    Tojo, hlavne ze na nich bylo napsano od zacatku "_navodar=".
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    4.12.2023 20:11 Heretik 《小魔神》
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Čistě metafyzicky,

    z Jeruzaléma bubáky vyhnat nelze, protože je tam pořád zazděná ta Šalamounova Brána démonů. Démoni šutrem sice neprojdou, zatím, ale duchové ano.

    Takže i každý David je mi tuze podezřelý....
    7.12.2023 11:43 tajný podezřelý
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To je takový problém tu Šalamounovu Bránu démonů přestěhovat někam jinam? Že to neudělali už dávno, nemuseli by se kvůli tomu mlátit hlava nehlava.
    Glee avatar 8.12.2023 01:48 Glee | blog: Gleekoviny
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    A v CSSR od/vystehovali soudruzi skoro vcelku jine duchovni misto. A v prsa se bili. A par dalsich ok veci se taky najde... Trebas kdyz do Zprav blili! :-)
    The History of the World: Every Year / We agreed today that these countries (UA & GE) will become members of NATO. 2008
    8.12.2023 17:14 karel
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Přepsat do Rustu. Díky.
    9.12.2023 18:31 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    1943: evakuace varšavského ghetta - Hitler

    1993: evakuace farmy ve Waco - FBI

    2023: evakuace pásma Gazy - Netanyahu

    https://www.seznamzpravy.cz/clanek/zahranicni-odpor-vuci-netanjahuovi-roste-stranici-se-boji-ze-prijdou-o-moc-na-20-let-241196
    10.12.2023 08:27 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    312 - raduv buk

    332 - girkinuv buk

    100000 a víc - radovy oběti

    4500 - pimpovy oběti

    Krev, pot a slzy - churchilluv citát

    Zabíjejte je vsude (nebo jak ta radova kravina zněla) - raduv citát

    To jen tak co si vybavim radovy zhovadilosti z poslední doby

    A furt sem cpe další :) - je to srdcař :)
    10.12.2023 09:31 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ještě to budeš muset trochu roztřídit, když se tu v diskuzi objeví třeba tři Radovani najednou :-D

    Apropos, je už čas na humanitární bombardování Tel Avivu?

    https://www.novinky.cz/clanek/zahranicni-blizky-a-stredni-vychod-izraelska-armada-zvysuje-tlak-na-jihu-pasma-gazy-humanitarni-situace-je-tam-katastrofalni-40453298
    10.12.2023 09:40 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Aha, takže teď budeš tlačit, ze to teda jsou fakt picoviny (to co sem cpeš), ale ze je sem nekdo dava tvým jménem a ne ty? No jo, jede tady proti tobě kampáááň :-D
    10.12.2023 20:21 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    10.12.2023 23:23 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ale my uz prece davno vime, s jakym zmrdem mame tu cest, nemusis nam k tomu davat jeste potvrzovaci link.
    Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
    11.12.2023 18:22 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    11.12.2023 19:50 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Co ti vadi vic? Ze ty podvody delali Cesi nebo Ukrajinci?
    Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
    11.12.2023 20:09 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Že jim blbci posílají peníze :-D
    11.12.2023 20:20 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    už jsem se lekl, že by zrovna tobě začalo vadit, že někdo lže a podvádí...
    12.12.2023 11:58 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Co ti vadi vic? Ze ty podvody delali Cesi nebo Ukrajinci?
    Jemu to nevadí vůbec. Kdyby vadila korupce, náckové nebo útlak Rusů, musel by vadit i kremelský režim.

    Vadí pomoc Ukrajině, protože zpomaluje postup RF.
    12.12.2023 11:53 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Místo nenávistných keců pošli Ukrajincům další peníze
    No jo furt, tak teda jo no. Ani jsem se nechystal teď nic posílat, ale když na tom trváš, tak něco pošlu. Připíšu do poznámky, že to je na tvé přání.
    Darth Phantom avatar 12.12.2023 14:21 Darth Phantom | skóre: 18 | blog: Kelvin_Fitnick | Doma
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    ale když na tom trváš, tak něco pošlu. Připíšu do poznámky
    A máš nějakou, alespoň rámcovou nebo přibližnou představu, kterému mafiánovi přispěješ na kousek kulometnostného pásu? Teď si třeba dávají důstojníci generálního štábu v Kyjevě granát k narozeninám, to docela frčí teďko, tyhle žertovné narozeninové dárky. Motivační dopis tam můžeš připojit, že tě motivoval Ráďa, to jest desolát prorusský :-D
    Tahle patička nemá hlavu ani patu
    12.12.2023 16:00 _
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    technická - kolik lidí by přispívalo na ukrajinu, kdyby tam ru nedělalo kdo ví od kdy bordel? co myslíš?
    12.12.2023 17:28 podlesh
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Teď si třeba dávají důstojníci generálního štábu v Kyjevě granát k narozeninám, to docela frčí teďko, tyhle žertovné narozeninové dárky.
    To bude celkově východoevropská móda, v Rusku prý taškařice s granáty přímo letí.
    12.12.2023 18:37 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    To tuhle jeden letěl skrz dvě patra na polské policejní stanici - dárek generálovi od spřátelených banderovců :-D
    Darth Phantom avatar 13.12.2023 13:26 Darth Phantom | skóre: 18 | blog: Kelvin_Fitnick | Doma
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    v Rusku prý taškařice s granáty přímo letí.
    Nojo, ale tady trockista králik nechce posílat granát do Kremlu, jestli se nepletu. A navíc nespíš ani netuší, kdy má Gerasimov narozeniny.
    Tahle patička nemá hlavu ani patu
    15.12.2023 19:15 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    No hele, nebyl hlodavec na výletě? Tohle je hodně vydařená taškařice :-D

    https://echo24.cz/a/H9ub2/zpravy-svet-video-ukrajinsky-poslanec-behem-zasedani-zahodil-tri-odjistene-granaty
    16.12.2023 09:39 Radovan
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻
    Ať je to ještě větší sranda, byl to Serhij Batrin ze Zelenského strany Služebník lidu.

    Ukrajinská politika v plné parádě ;-)
    Darth Phantom avatar 16.12.2023 12:38 Darth Phantom | skóre: 18 | blog: Kelvin_Fitnick | Doma
    Rozbalit Rozbalit vše Re: David a duchové 🤴 👻

    No dyť řikám, že to tam teďko dost frčí. A podlý podleš ukazuje prstem schválně někam jinam. To byla asi nějaká větší narozeninová párty.

    Dejme tomu, že jsou trochu výbušnější povahy. Ale profesor Nutella řikal, že to bude ohromný přínos v EU, určitě nejen ekonomický ale i kulturní, to nemůže bejt dezinformace.
    Tahle patička nemá hlavu ani patu
    xkucf03 avatar 16.12.2023 15:04 xkucf03 | skóre: 49 | blog: xkucf03
    Rozbalit Rozbalit vše Podíl na poválečné obnově