Acest tutorial este ultima parte a procesului de codificare a unui joc de hochei folosind comportamente de direcție și mașini de stat finite. Aici vom îmbunătăți inteligența artificială a sportivilor noștri pentru a le permite să-și apere obiectivul împotriva adversarilor lor. De asemenea, sportivii noștri vor efectua tactici de atac în timp ce se apără, astfel încât să poată recupera pucul și să înceteze ofensiva adversarului.
Într-un joc competitiv precum hocheiul, procesul de apărare este mult mai mult decât să se grăbească spre zona de poartă a echipei, pentru a împiedica adversarul să marcheze. Prevenirea adversarului de scorul este doar una din multele sarcini implicate.
Dacă o echipă se concentrează doar pe tactici de prevenire a scorurilor, toți sportivii vor deveni doar obstacole pe parcurs. Adversarul va continua să împingă, încercând să găsească un loc în formarea de apărare. Va dura ceva timp, dar în cele din urmă adversarul va înscrie.
Procesul de apărare este un amestec de acțiuni defensive și ofensive. Cea mai bună modalitate de a pune capăt atacului adversarului, care este obiectivul de apărare, este să atac în timp ce apăra. S-ar putea suna cam confuz, dar are sens.
Un atlet care apără echipa trebuie să se îndrepte spre obiectivul său, împiedicând adversarul să marcheze. Pe parcurs, el trebuie să încerce să fure pucul de la adversar care îl poartă sau să intercepteze pucul atunci când este schimbat între adversari. Exact acest tutorial va încerca să pună în aplicare: o tactică defensivă cu acțiuni de atac.
Pentru a realiza un comportament defensiv care are câteva aspecte de atac în el, vom adăuga două noi stări la mașina AI finit-state:
O mașină de stat finită bazată pe stack, reprezentând procesele de atac și de apărare ... apăra
statul va fi piatra fundamentala in procesul de aparare. În timp ce se află în acea stare, sportivii se vor deplasa spre partea lor, încercând întotdeauna să recupereze pucul pentru a termina ofensiva adversarului.
patrulare
statul va completa procesul de apărare. Acesta va împiedica sportivii să stea în picioare când își ating poziția de apărare în patinoar. Această stare va ține sportivii în mișcare și patrulare în zonă, ceea ce va produce un rezultat mai convingător.
apăra
stat se bazează pe o idee foarte simplă. Când este activ, fiecare sportiv se va muta în poziția inițială din patinoar. Am folosit deja această poziție, descrisă de mInitialPosition
proprietate în Atlet
clasa, să pună în aplicare prepareForMatch
stat în primul tutorial din această serie.
În timp ce se deplasează spre poziția sa inițială, un atlet va încerca să efectueze unele acțiuni de atac împotriva adversarului dacă este destul de aproape și poartă pucul. De exemplu, în cazul în care atletul se mișcă și liderul adversarului (cel cu puc) devine vecin, apăra
statul va fi înlocuit cu ceva mai adecvat, cum ar fi stealPuck
stat.
Deoarece sportivii tind să se răspândească prin întregul patinoar în timp ce atacă, când trec apăra
și încep să se întoarcă la poziția lor inițială, vor acoperi o zonă semnificativă, asigurând un model de apărare convingător:
Unii sportivi nu vor întâlni adversari de-a lungul drumului, așa că se vor deplasa doar spre poziția lor inițială. Alți sportivi, cu toate acestea, s-ar putea apropia de niște adversari interesanți, cum ar fi liderul (cel care poartă pucul).
apăra
statul va avea patru tranziții:
Trei dintre ele, echipa are pucul
, aproape de liderul adversarului
, și pucul nu are proprietar
, sunt legate de acțiunile de atac. Ei vor fi responsabili pentru a face ca sportivii să pară că atacă adversarii în timp ce se mută pentru a apăra obiectivul echipei. pe poziție
tranziția va fi declanșată atunci când atletul ajunge în sfârșit la poziția sa inițială în patinoar.
Primul pas în implementarea apăra
statul este de a face sportivul să se îndrepte spre poziția sa inițială. Din moment ce el trebuie să încetinească în timp ce se apropie de destinație, comportamentul de direcție sosire este perfect potrivit:
clasa Atlet // (...) funcția privată defend (): void var aPuckOwner: Athlete = getPuckOwner (); // Deplasați-vă spre poziția inițială, ajungând acolo ușor. mBoid.steering = mBoid.steering + mBoid.arrive (mInitialPoziție); // Are pucul un proprietar? dacă (aPuckOwner! = null) / Da, da. Cine o are? dacă (doesMyTeamHasThePuck ()) // Echipa mea are pucul, timpul pentru a opri apărarea și a începe ataca! mBrain.popState (); mBrain.pushState (atac); altfel dacă (Utils.distance (aPuckOwner, acest lucru) < 150) // An opponent has the puck and he is close to us! // Let's try to steal the puck from him. mBrain.popState(); mBrain.pushState(stealPuck); else // No, the puck has no owner, it is running in the rink. // There is no point to keep defending the goal, because nobody has the puck. // Let's switch to 'pursuePuck' and try to get the puck to our team. mBrain.popState(); mBrain.pushState(pursuePuck); // (… )
Comportamentul de sosire va crea o forță care va împinge atletul spre poziția sa inițială (mInitialPosition
) in timp ce apăra
statul este activ. După calculul forței de sosire, în acest cod, executăm o serie de teste care vor verifica proprietatea puțului și apropierea adversarilor, apăra
stat de la creier și împingând unul nou în funcție de situație.
Dacă pucul nu are proprietar, probabil că se mișcă liber în patinoar. În acest caz, pursuePuck
statul va fi împins în creier (linia 29). În cazul în care pucul are un proprietar de echipă, înseamnă că procesul de apărare sa terminat și este timpul să atacăm (linia 16). În cele din urmă, dacă proprietarul pucului aparține echipei de adversari și este destul de aproape, stealPuck
va fi împins în creier (linia 22).
Rezultatul este o echipă care își poate apăra scopul, urmărind și încercând să fure pucul de la adversar care îl poartă. Mai jos este o demonstrație a implementării actuale de apărare:
Comportamentul actual de apărare este acceptabil, dar poate fi modificat puțin pentru a fi mai convingător. Dacă analizați demo-ul anterior, este posibil să observați în cele din urmă că sportivii se vor opri și vor sta în continuare după ce ajung în poziția inițială în timp ce apără.
Dacă un sportiv se întoarce în poziția sa inițială fără a întâlni adversari de-a lungul drumului, el va rămâne în continuare până când un adversar cu pucul trece sau echipa va recupera pucul.
Putem îmbunătăți acest comportament prin adăugarea unui a patrulare
stat, care este împins în creier de către apăra
atunci când atletul atinge poziția sa inițială:
patrulare
stat este extrem de simplu. Când este activ, va face sportivii să se deplaseze la întâmplare pentru o perioadă scurtă de timp, ceea ce mimează vizibil comportamentul așteptat de la un atlet care încearcă să apere un loc în patinoar.
Când distanța dintre atlet și poziția sa inițială este mai mare decât 10
, de exemplu, patrulare
se scoate din creier și împinge apăra
. Dacă atletul ajunge din nou în poziția inițială în timp ce apără, patrulare
este împins încă o dată în creier și procesul se repetă:
Modelul de mișcare aleatorie cerut de patrulare
starea poate fi realizată cu ușurință cu comportamentul de direcție rătăcit. Punerea în aplicare a directivei patrulare
stat este:
clasa Atlet // (...) privat funcția patrol (): void mBoid.steering = mBoid.steering + mBoid.wander (); // Sunt prea departe de poziția mea inițială? dacă (Utils.distance (mInitialPosition, this)> 10) // Da, sunt. Este timpul să opriți patrularea și să vă întoarceți la // poziția mea inițială. mBrain.popState (); mBrain.pushState (apăra); // (...)
Verificarea distanței (linia 8) asigură că atletul va patrula o zonă mică în jurul poziției sale inițiale, în loc să lase complet poziția de apărare inițială nesupravegheată.
Rezultatele utilizării patrulare
stat este un comportament mai convingător:
În timpul punerii în aplicare a directivei stealPuck
stat în tutorialul anterior, a existat o situație în care sportivii ar trebui să treacă la apăra
stat. Totuși, acel stat nu a fost implementat atunci.
În timp ce încerca să fure pucul ( stealPuck
stat), dacă adversarul este prea departe de atlet, este inutil să continuăm să încercăm să furăm pucul. Cea mai bună opțiune în această situație este de a afișa stealPuck
stat și împinge apăra
, sperând că un coechipier va fi mai aproape de liderul adversarului pentru a fura pucul.
stealPuck
starea trebuie schimbată (linii 28 și 29) pentru a permite sportivilor să împingă apăra
stat în această situație:
clasa Atlet // (...) funcția privată stealPuck (): void // Pucul are proprietar? if (getPuckOwner ()! = null) / Da, da, dar cine o are? dacă (doesMyTeamHasThePuck ()) // Echipa mea are pucul, deci e timpul să nu mai încerci să furi // pucul și să începi să ataci. mBrain.popState (); mBrain.pushState (atac); altfel // Un adversar are pucul. var aOpponentLeader: atlet = getPuckOwner (); // Este adversarul cu pucul aproape de mine? dacă (Utils.distance (aOpponentLeader, acest lucru) < 150) // Yeah, he is close! Let's pursue him while mantaining a certain // separation from the others to avoid that everybody will ocuppy the same // position in the pursuit. mBoid.steering = mBoid.steering + mBoid.pursuit(aOpponentLeader.boid); mBoid.steering = mBoid.steering + mBoid.separation(50); else // No, he is too far away. Let's switch to 'defend' and hope // someone closer to the puck can steal it for us. mBrain.popState(); mBrain.pushState(defend); else // The puck has no owner, it is probably running freely in the rink. // There is no point to keep trying to steal it, so let's finish the 'stealPuck' state // and switch to 'pursuePuck'. mBrain.popState(); mBrain.pushState(pursuePuck); // (… )
După actualizarea stealPuck
stat, sportivii sunt acum capabili să organizeze tactici de atac și de apărare, ceea ce face ca două echipe controlate de AI să poată juca unul împotriva celuilalt.
Rezultatul este demonstrat mai jos:
În acest tutorial am implementat o tactică de apărare folosită de atleți pentru a-și apăra obiectivul de la adversari. Am îmbunătățit apoi apăra
prin adăugarea unor acțiuni de atac, cum ar fi încercarea de a fura pucul adversarului, ceea ce a făcut ca tactica de apărare să se simtă mai naturală și mai convingătoare.
Am îmbunătățit, de asemenea, simțul comportamentului apărării prin adăugarea unei stări extrem de simple, dar puternice patrulare
. Ideea este de a împiedica sportivii să stea în picioare în timp ce apăra obiectivul echipei.
Și cu asta, am creat un sistem complet de AI pentru jocul nostru de hochei!