Vývoj her: Laborování se závodní AI

Stát se PATRONEM
high-voltage.cz

21 patronů = 2120 Kč měsíčně

Je to malé pade pro čtenáře, ale velká vzpruha pro HV! ;)

Tak jsem se zase jednou pustil do programování věcí, co "jsem vždycky chtěl zkusit", a taky jsem si trochu modernisticky "zavajbkódoval". Nikdy mě totiž moc nebavily ty začátky projektu, kdy "to ještě nic nedělá", a tak dost často praktikuji metodu, že nechám LLM napsat nějaký tragický, ale částečně funkční kód, na kterém se už něco rozhýbe, a pak ho tak dvacetkrát přepíšu tak, aby fungoval tak jak bych si představoval. A ano, uznávám, je to několikanásobně víc práce, otravy, opravování atd. Ale já mám po prvních dvaceti minutách od začátku práce pohybující se cosi, a to mi vlévá do žil chuť to opravit a dodělat tak jak chci. Nesuďte mně.

Vývoj her: Laborování se závodní AI

Tentokráte jsem se rozhodl, že oživím svou snahu o vytvoření 2D závodní hry z pohledu shora. Jak jsem již nastínil, tak prvotní pokus, kdy jsem ovládal své autíčko, které jezdilo po vytyčené trase, a při najetí do trávy zpomalilo, byl na světě celkem rychle. Postupně jsem ještě doladil zdi které nejdou projet a generují kolize, a byl jsem se základním konceptem celkem spokojen. Pak jsem ale došel k tomu, že potřebuji někoho, proti komu závodit. Nechal jsem tedy LLM vysmahnout první jednoduchý nástřel AI pro moje vozidla. Kupodivu to celé na první pohled vypadalo celkem dobře, a po prvotním "vajbkódování" a ladění s LLM jsem dosáhl celkem slušných výsledků a pokračoval v ladění sám. Došel jsem k tomu, že stačí celkem jednoduchý "radar", který vyšle paprsky v několika úhlech před auto, detekuje co je před ním, a vybere cestu s nejméně překážkami, a k té se poté snaží vydat.

A paradoxně toto velmi jednoduché řešení fungovalo celkem obstojně. Samozřejmě trvalo nějakou dobu vyladit všechny mouchy, ale nakonec autíčko celkem obstojně drandilo po dráze, a kvůli zatím absentujícímu sofistikovanému modelu zatáčení a akcelerace / decelerace se plnou rychlostí prohánělo zatáčkami. Problém nastal, když se přidalo více AI, s různými stupni "agresivity", a vozidla se dojížděla navzájem. Bylo tedy potřeba implementovat ještě režim předjíždění.

AI si tedy pomocí "radaru" začala skenovat i vozidla, ke kterým se blížila. Pokud už bylo vozidlo vpředu dostatečně blízko, aktivoval se režim předjíždění, a radar se začal zaměřovat i na strany auta, vyhodnocovat šířku silnice, a snažit se předjíždět. Toto už bylo trochu náročnější, ale nakonec se to celé podařilo implementovat a vše začalo fungovat.

Když už jsem měl celkem obstojnou AI, tak jsem se rozhodl do hry vložit sofistikovanější okruh, který je realističtější a širší. Najednou se ale opět začaly projevovat problémy s AI, která na úzké dráze fungovala. Problém byl, že se autům často dařilo "zabloudit" v zatáčkách. Tedy docházelo k tomu, že auto mělo před sebou pořád dost silnice, až do doby, kdy dorazilo do vnějšího vrcholu zatáčky. Tam se ale zaseknulo, protože už nezbývala žádná další možná cesta vpřed, protože už nebylo dost prostoru zatáčku "vytočit".

Přidal jsem tedy další vrstvu radaru, která se snažila predikovat zatáčky a směrovat vozidlo tím či oným směrem tak, aby zatáčku začalo vybírat včas. To se nakonec po delším laborování opět povedlo, a protože jsem líný, nechal jsem opět trochu zapracovat LLM, aby implementovala i recovery logiku, pokud se už auto opravdu zaseklo, aby se dostalo do módu záchrany, a začalo couvat. Nechtělo se mi přepisovat celou sekvenci rozhodování ručně, takže tohle za mně LLM udělala, a já pak začal implementovat kroky záchrany. Nakonec se mi podařilo celkem úspěšně detekovat to, že se auto nachází ve slepé uličce, a zahájit záchranu couváním. Bohužel se ale moc nedařilo dobře detekovat "odzaseknutí" a tak auta pak často končila v nekonečném módu pocukávání na zpátečce.

Vývoj her: Laborování se závodní AI

Zkusil jsem tedy ještě s LLM trochu podiskutovat o tom, že by zkusila implementovat pathfinding, který by predikoval trasu dostatečně dopředu, proložila křivku, a vozidlo se pak snažilo jí držet. Po několika pokusech, které často vedly k tomu, že se auto buď často vydalo v nekonečných kruzích, protože šířka trati to na plný rejd dovolovala, nebo se vydalo do protisměru či zvláštní slepé cesty, kdy to pathfinding spočítal hned po startu "plnou parou" proti zdi, to vypadalo tak beznadějně a otravně, že výsledky byly ve všech případech horší než jízda podle "radaru". Nakonec jsem tedy pokračoval v radarové metodě, a podařilo se ji dotáhnout dostatečně daleko na to, aby auta celkem pěkně jezdila po okruhu, a s rozšířenou predikcí zatáček opravdu odkroužila i 10 kol bez záseku.

Začala mně ale trápit jiná věc. Fyzikální model byl naprosto nedostačující pro to, aby jízda vypadala plynule, a ani požitek z hraní nebyl nic moc. Všechny zatáčky se daly projet plnou rychlostí, protože rejd byl pevně daný a nezávisel na rychlosti. Musel jsem tedy vylepšit fyzikální engine, a když už jsem byl u toho, rovnou implementovat i vliv pneumatik a jejich opotřebení.

Zase jsem tedy zapojil LLM, aby navrhla rychlou kostru a základní implementaci, což ušetřilo dost času, a pak se vydal do ladění vlivu přilnavosti, opotřebení, teploty pneumatik a podobně. Sepsání základní kostry tedy nebylo příliš dlouhé a základ by rychle hotový a funkční, ale nakonec vyžadoval hodně času na ladění detailů a různých konstant. Zpětně vzato by asi bylo lepší implementovat jednotlivé části postupně, a nenechat LLM tam nasekat všechno najednou (upotřebení, teploty, typy pneu, vliv rychlosti na radius..), protože pak ladit jednotlivé vlivy, jejich poměry, a celkový efekt jednotlivých věcí na jízdní model se ukázalo jako příliš chaotické a zdlouhavé.

Nakonec jsem ale měl jízdní model který je pocitově velmi přirozený a zdá se velmi podobný realitě. Co se ale ukázalo jako problém, byla má dokonale kroužící AI. Pomocí relativně jednoduchého, byť dvouvrstvého radaru už se v této situaci nedalo dostatečně dobře rozhodovat. Auta najížděla do kombinovaných zatáček v takových úhlech, že další zatáčky již nebylo možné projet, případně vůbec nebyla schopna včas zabrzdit. A i po důkladném ladění, optimalizacích a dalších pokusech byly ve finále jen neuspokojivé možnosti. Buď AI jezdila nesnesitelně pomalu všude, aby vybrala zatáčky, nebo prostě všude narážela a zasekávala se každou chvíli v nějaké zatáčce, nebo potřebovala nějakou formu "cheatu", což často navrhoval LLM. Ten dospíval k závěru, že je třeba do implementace vozidla doplnit funkci na hard braking, což znamenalo prakticky to, že by AI popřela fyzikální model a prostě to "zapíchla na fleku".

Vývoj her: Laborování se závodní AI

Byl jsem tedy opět v situaci, kde prakticky vždy AI končila hned v první zatáčce. A bohužel jsem došel k závěru, že tady už prostě radar stačit nebude, a že bez sofistikovaného pathfindingu se to prostě vyřešit nepodaří. Opět jsem tedy zapojil LLM, aby mi vystřelil základ pathfindingu. Toto byla asi nejdelší seance "vibecodingu", protože LLM to prostě odmítal správně uchopit. Opět generoval trasy v neustálém kruhu, případně si podezřele často myslel, že jde o klasickou starou "jeď vzhůru" hru, a tak na pokyn, aby preferoval více cestu vpřed, generoval trasy směrem k horní hraně canvasu. Nakonec jsem tedy použil kostru a začal to dělat "po svém".

Po řadě protrpěných hodin jsem se dostal alespoň do stavu, kdy se AI trochu snaží jet po trati. Problémů se ale vynořuje víc, než kolik se dostavuje řešení.

Vývoj her: Laborování se závodní AI

Při hledání optimalizací trati často auta inklinují k tomu, aby se snažila limitně blížit ke zdem, snaží se příliš agresivně trefovat apex, takže nakonec bokem narazí do zdi, nebo pak zase naopak jedou i ostrou zatáčku téměř rovně. Jakékoliv snahy o korekci mezi tyto dva stavy vždy končily naprosto bláznivým chováním které bylo zcela nevyzpytatelné.

Nakonec, když už se mi podařilo nakorigovat pathfinding plus mínus na trať, došel jsem k dalšímu problému. Často se začalo stávat, že algoritmus pathfindingu našel cestu přímo skrze pevnou zeď. To mi ale vůbec nedávalo smysl vzhledem k počtu různých ochran, optimalizací a kontrol. Až po nepřiměřeně dlouhé době mi došlo, že se prostě stane, že body na nalezené trase jsou příliš daleko od sebe, takže se může stát, že dva sousedící body jsou sice oba na trati, ale přímka mezi nimi protíná zábranu (je vidět i na screenu výše). Řešení tedy byla dvě. První, které kontrolovalo jestli úsečka neprotíná zeď, se ukázalo jako příliš výpočetně náročné a docházelo k lagování. Druhé řešení, které ale na první pohled vypadalo více náročné než první, bylo prostě zhustit intenzitu bodů tak, aby se mezi ně zeď nevešla. To se nakonec ukázalo paradoxně celkem milosrdné na výpočetní čas, a problém to vyřešilo.

Nicméně tento problém mi pomohl s laděním a konečnou opravou "recovery" systému, protože jsem měl více než dostatek testovacích situací. AI tedy nyní umí zahájit recovery plán, zacouvat, a opět se vrátit k pathfindingu!

Vývoj her: Laborování se závodní AI

Dostal jsem se do fáze, kdy se již poměrně příjemně a bezkolizně vytvářely křivky, které měla vozidla následovat. Bohužel se ale poměrně často stávalo, že trasa nakonec vedla do zdi. Bylo tedy třeba implementovat jistou úroveň rekurze, kdy pokud vygenerovaná cesta je kratší než X bodů, je třeba si poznamenat, že "tudy cesta nevede", vrátit se zpět na její začátek a zkusit to jinudy. Jak jsem ale zjistil později, je třeba rekurzi limitovat dostatečně dobře tak, aby hledala "sjízdnou" trasu, a ne nejlepší možnou, protože to opět vede k drastickému nárůstu výpočetního času, a vlastně to není vůbec třeba.

Celá tato optimalizace vedla k zásadnímu zlepšení, a auta již celkem pěkně sledují závodní linie. Bohužel to ale přineslo vedlejší efekt v tom, že se vrátil problém, který jsem řešil na začátku práce s komplexním pathfindingem - vozidla prostě často dojdou rekurzí k tomu, že když to nejde do zdi, je lepší se otočit a jet zpátky, nebo se prostě točit v kruhu. Na druhé straně pokud o nápravu tohoto chování tím, že se preferuje "přímější" cesta, zase často vede k tomu, že AI nedokáže vybrat ostřejší zatáčku, a tak v ní musí bourat a couvat i několikrát.

Závěrem zatím je tento stav, který se ale zdá jako nejspolehlivější cesta k tomu, projet alespoň dva okruhy bez bourání. Pokud mi tedy neprasknou nervy, možná se časem dočkáte i pokračování. Pokud jste ovšem očekávali happyend v podobě alespoň jednoho projetého kola, tak vás bohužel zklamu.

Držte mi palce s laděním.

Autor: Jenkings

Sbírám staré notebooky, mobily a hraju jen to co vzniklo před více než 15 lety. Ve volném čase vyvíjím a provozuji web HryProDva.cz

Komentáře k:
"Vývoj her: Laborování se závodní AI"

  • aargh napsal:

    Jaký LLM přesně používáš? A v jakém enginu?

    • Jenkings napsal:

      Vzhledem k tomu, že si žádnou neplatím, tak to obvykle točím mezi všemi těmi většími, profláklejšími. Některé jsou lepší na iterace a optimalizace, některé zase trochu líp zpracovávají sémantiku a kostru.

      Engine nepoužívám žádný, já většinou když něco píšu, tak to chci mít od nuly, abych si to trochu víc navnímal a odnesl si z toho nějaké nové zkušenosti a znalosti.

      • Milsa napsal:

        Mohol by si popísať aj akým spôsobom s nimi komunikuješ a ktoré sú tie všemi těmi?

        O čo mi ide? Neviem si predstaviť ako by som s umelou inteligenciou komunikoval ohľadne mnou písaného programu. To tam hodíš celý projekt a AI si ho prejde a upraví? Alebo tam dávaš časť kódu a musíš mu vysvetľovať nejaké „globálne“ parametre k tomu?

        • Jenkings napsal:

          Konkrétně většinou cykluju mezi DeepSeek, ChatGPT, Grok a Claude.

          Konkrétně u toho Ai co ladím teď, stačí předhodit jen ten soubor s AI, protože v něm je prakticky vše co potřebuje vědět. To rozpoznání mapy jsem tam implementoval, takže to do začátku mají, a pak už jen hážu kód co je, a jedním odstavcem popíšu, co to dělá, co to je za hru, v jakém „prostoru“ se to vozidlo pohybuje a co potřebuju udělat.

  • Doomtrooper napsal:

    Za mě super počin. Chápu frustraci s LLM a musím říct že jediný který si s takovými věcmi může poradit by byl Claude code.

    • Jenkings napsal:

      Tak do Klóda jsem taky vkládal největší naděje, ale reálně se ukázal jako největší dřevo a každá jeho iterace na existujícím kódu vede jen k horším výsledkům, než byl vstup..

  • WIFT napsal:

    Ještě že jsem na to už moc starý a můžu v tomhle jen fandit těm mladým :). Já bych na to neměl nervy, po prvním nezdaru bych plasťáka poslal hrát si s igelitovými pytlíky a hodil na to bobana :).

    • Crazy Mage napsal:

      Mohu mluvit jenom za sebe, ale mladý jsem byl před pár (mnoha) dekádami, ale stále se tím zabývám. Také bych kolikrát toho plasťáka (teď myslím notebook :D) poslal do křemíkového nebe hodem o zeď, ale po chvilce uklidnění mi dojde, že chyby byla ve mě a v kódu, který jsem napsal. Přeci jenom počítač je tupý stroj a dělá přesně to co se mu řekne a v pořadí v jakém se mu to řekne. Vždy si uvědomím, že je chyby mezi klávesnicí a židlí. :D A hlavně po mnoha hodinách je oko unavené a kolikrát přehlédne znaménko < a > nebo + a – . Druhý den na tu malou chybu přijdu a nadávám sám sobě jaký jsem blbec, ale tak o druhé hodině ranní mi to už moc po celém dni programování nemyslí a jak se říká, tak pro samé stromy nevidím les. :D
      Jinak je to zábava tvořit něco z ničeho a potom mít radost, že to funguje. :) Tedy až po mnoha desítkách hodin frustrace a nadávání. :D Ale to prostě k tomu patří.

      • WIFT napsal:

        Imho jedna věc je ovládat počítač skrze kód, který je nějak daný a nepřipouští vícero variant provedení (není-li např. v interpreteru chyba) a druhá něco řešit se softwarovým produktem, jehož chování se řídí blíže neznámou olbřímí sadou dat způsobující, že ten produkt může mít plus mínus na výsledné řešení svůj názor.

  • Crazy Mage napsal:

    Moc krásné napsané a přesně vím čím si procházíš. :) Tedy závodní hru jsem nikdy nedělal, protože mě tyhle hry nebaví, ale pathfinding je stejný jak pro auta nebo pro nepřítele, který tě pronásleduje. A kolikrát je to utrpení to vyladit k dokonalosti, aby to fungovalo jak si člověk představuje a vlastně chce dosáhnout.
    Jaký programovací jazyk a systém používáš – Pascal, C++, Visual Basic, Python – Dos nebo Windows?
    BTW doufám, že bude další článek jak pokračuješ dál. Držím ti palce. ;)

    • Jenkings napsal:

      Nesuď mně, ale vyvíjím to v Javascriptu :) bez knihoven, jen na „zelené louce“.

      Každopádně když se dostanu někam dál, tak klidně sepíšu nějaké další útrpné pokračování, ale zatím se, zdá se, pořád točím v kruhu stejně neuspokojivých výsledků. Tedy jsem stále ve fázi „už to vypadá skoro dobře, a zdá se že jednoduchou úpravou to bude funkční“. Konkrétně jsem v této fázi už několik hodin čistého vývojového času.

      • Crazy Mage napsal:

        Proč bych tě měl soudit? :D Každý programovací jazyk je tak dobrý jako je programátor/vývojář… ale sakra práce… Javascript? :D :D Ne dělám si srandu, každý má to své oblíbené a přestože všichni víme, že bychom měli dělat v něčem jiném, tak stejně nepřejdeme. :D Moje zkušenost. Když jsem měnil prostředí v čem dělat dále, tak to kupodivu bylo vždy hodně podobné tomu, které jsem znal, přestože jsem věděl, že to není dokonalé. Ale co vlastně je dokonalé, že? :D Assembler se do úplného detailu učit nehodlám. :( Budu rádu rád pokud budeš pokračovat v tomto „deníčku“ vývojáře a doufám, že to dotáhneš do zdárného konce. Moc ti fandím. :) Vím jaké to je.

  • Xspy napsal:

    Když to nejde do zdi, je lepší se otočit a jet zpátky, nebo se prostě točit v kruhu ;D …Skvělé životní moudro

    • Jenkings napsal:

      Jo, dalo by se říct, že je to celkem zajímavé fylozofické řešení, a praktická aplikace softwarové lenosti..

      Prostě budu kroužit.. na silnici jsem, a aspoň se nenadřu s pathfindingem…

      • Milsa napsal:

        To má jednoduché riešenie, ale ťažšiu implementáciu. Na trase nech si pri štarte AI vygeneruje checkpointy a pohyb dostane skóre podľa toho, ako sa priblížil k CP. Ak je blízko, začne sa zameriavať na ďalší. Nesmie to byť ale presne na ňom, lebo by to skončilo povinným prejazdom.

        • Jenkings napsal:

          Tohle je věc nad kterou přemýšlím čistě z praktického hlediska nejen kvůli AI, ale i kvůli hráči, aby se nesnažil to občůrávat a případně hledat zkratky nebo glitche. Takže bych ty checkpointy namaloval tři nebo čtyři přímo do mapy. Zároveň by mohly sloužit i pro timing.

          • VasilijP napsal:

            Toto je zaujimavy projekt, chvilu som to mal otvorene v tabe kym som si nasiel cas podrobne precitat.
            Ten napad s checkpointmi je dobry sposob ako postavit fitness funkciu. Celkovo rozumny pristup je ten „radar“ – analogia toho ked sofer ide po neznamej ceste. Pridal by som nejaku lokalnu „znalost“ napr. grid (ked mapa je napr. 100×100, grid by mal bunky 1×1) nasledne „ucil“ ai parametre ktore viedli k zlepseniu casu na checkpointoch. kazde AI auticko by malo za sebou virtualny trail (ako v hre snake) tak aby dosiahol priblizne dlzku medzi checkpointmi a pri zlepseni casu by sa do kazdej z pozicii spriemerovali parametre akymi tadial prechadzalo (ako rychlost, natocenie volantu atd.).

  • Crazy Mage napsal:

    Vím, že tohle je trochu něco jiného, ale nepomohlo by ti to?

    https://www.youtube.com/watch?v=MDD2VbM3FLM

    Ano, chápu ten pokus zapojit AI do procesu tvorby, ale přeci jenom AI ještě není tak daleko, aby vše vyřešilo, takže do toho musí vstoupit lidský element.

    Jenom mě tak napadlo jestli by tohle nebylo nápomocné. Mě to pomohlo, přestože je to v jiném jazyce než v kterém pracuji, ale co si budeme povídat. Každý jazyk si je podobný a záleží jenom na detailech v syntaxi.

Přidej komentář k příspěvku uživatele WIFT (přihlášení / registrace)

(Komentáře s více jak 2 odkazy musí počkat na schválení.)

Podpořit finančním příspěvkem » The Ultimate Retro Gaming PC in a Compact Package Shadow bazar, retro herní džungle