Aproape fiecare joc poate fi considerat ca avand o singura functie principala care contine toata logica jocului si care se executa fie atunci cand utilizatorul face ceva, fie dupa un anumit interval de timp. Acest ciclu de funcționare a aceleiași funcții principale este numit joc bucla, și este crucial să înțelegeți pentru orice fel de dezvoltare a jocului.
Ați jucat, probabil, jocul de joc Chutes and Ladders (sau șerpi și scări așa cum o numim în Marea Britanie).
(Photo credit incurable_hippie pe Flickr)
Fiecare jucător rotește matrița (sau rotește spinnerul) și înaintează numărul de pătrate indicate. Pătratul în care se aterizează îi poate face să alunece în spate sau să urce în spate câteva spații. Jucătorul câștigă jocul când ajunge în piața finală.
Deci, în imaginea de mai sus, aterizarea în Piața 6 te face să urci patru patrate în Piața 10; aterizarea în Piața 19 vă face să alunecați 15 piețe în Piața 4; și aterizarea pe Piața 64 înseamnă că câștigi jocul.
Acum, să presupunem că jucați un singur jucător, pentru a practica. Faceți același lucru ca mai sus, de mai multe ori, până când ajungeți la Piața 64. Cum ați prezenta acest lucru în cod?
Probabil că veți începe prin crearea unei matrice pentru stocarea valorilor pătratelor. Cele mai multe elemente ar conține zero, dar câteva ar conține fie un număr pozitiv (indicând o scară), fie un număr negativ:
Notă: Acesta este pseudocod, nu AS3
var specialSquares: Array = []; caractere speciale [0] = 0; // pătratul pe care încep jucătorii, înainte de 1 specialSquares [1] = 0 ;? specialeSquares [6] = +4 ;? rubrici speciale [19] = -15;
? si asa mai departe. Apoi, ați avea o funcție pentru a muta jucătorul în funcție de numărul de pe mat:
funcția movePlayer (pătrate: număr) newSquare = currentSquare + pătrate; newSquare + = specialSquares [newSquare]; curentSquare = newSquare;
Ați putea pune această funcție într-o funcție mai mare, reprezentând o întoarcere întreagă:
funcția takeATurn () diceNumber = aleatoare (1, 6); // număr aleator între 1 și 6 movePlayer (diceNumber); dacă (currentSquare == 64) // jucătorul a câștigat! joc încheiat
Această funcție, takeATurn ()
, încapsulează logica jocului de bază pentru jetoane și scări pentru un singur jucător. Dar cum de fapt avem această funcție să funcționeze? Există mai multe opțiuni:
Am putea pune un buton pe ecran și să-l sunăm takeATurn ()
de fiecare dată când este făcut clic. Dacă ați jucat vreodată Facebook Scrabble sau Cuvintele cu prietenii, ați văzut această opțiune în acțiune.
Am putea face takeATurn ()
alerga la fiecare șaizeci de secunde.
De fapt, această opțiune este puțin mai complicată decât pare. În practică nu vedem niciodată jocuri fără niste player input; fără interacțiune, nu poate fi considerat un joc. Dar totuși, unele jocuri au un element de "timp calendaristic" implicat. Luați în considerare FarmVille: tu, jucătorul, plantați culturile și apoi la fiecare câteva minute (sau ore) se dezvoltă puțin mai departe, de la semințe până la fructe. Și în anumite moduri de civilizație, vi se dă un anumit timp (de exemplu, cinci minute) pentru a vă face toate mișcările pentru o "întoarcere"; odată ce aceste cinci minute sunt în sus, funcția de bază a jocului este declanșată.
Unele jocuri utilizează un amestec din aceste două opțiuni: de exemplu, Mafia Wars are o resursă numită "energie" care umple unitatea la fiecare cinci minute; luați acțiuni în joc utilizând această resursă, astfel încât funcția de bază a logicii jocului este încă declanșată de o acțiune a utilizatorului, este doar limitată de timp.
Acesta este un model comun pentru majoritatea jocurilor: o singură bucată de cod care conține logica jocului principal este declanșată în mod repetat. Noi numim asta joc bucla.
Există un termen pentru acțiunea sau perioada de timp care declanșează și codul logic al jocului de bază: a căpușă (cum ar fi sunetul ceasului).
Deci, în Civilizare, bifarea este la fiecare cinci minute. În Cuvintele Cu Prietenii, joci rândul tău cauze o căpușă. Cu alte cuvinte, bucla de joc rulează o singură dată pe bifați.
Super Mario Bros nu pare să se încadreze în niciuna dintre aceste categorii. Mario răspunde la intrarea jucătorului? și totuși tot felul de lucruri se întâmplă fără a mai fi nevoie să faceți nimic (Goombasul se plimba pe jos, cronometrul contorizează, obiectele cad). Sunt acolo Două bucle de joc?
Nu. Există doar unul, și este declanșat numai de timp - dar cu o bifă de doar o fracțiune de secundă.
În civilizație, aveți o perioadă de cinci minute pentru a introduce tot ceea ce doriți să faceți la rândul său, înainte ca jocul "să bată" și să execute bucla de joc din nou pe baza tuturor datelor introduse. Deci, dacă spui, în Turnul 23, că vrei ca războinicii tăi să atace un cerb, atunci în Turnul 24 toată lumea primește vânatul pentru cină.
E același lucru cu Mario. Dacă apăsați butonul Jump în timpul unei bifați, atunci în următoarea iterație a jocului, Mario va începe să sară.
Rețineți că voi nu face trebuie să faceți timp ca presa Jump să apară la fel cum este declanșată funcția de bază a jocului logic - toate acțiunile dvs. în timpul unei perioade de bifare sunt înregistrate și utilizate în timpul următoarei iterații a buclei de joc.
Toată logica jocului este tratată în bucla de joc. Dar există mai mult pentru un joc decât pentru logica sa, grafica fiind exemplul major.
Desenarea grafică pe ecran este o muncă grea pentru computer. Să presupunem că aveți un joc de acțiune cu o bifă de 1 / 60th din secundă; care ar trebui să facă jocul să se simtă ca și cum ar reacționa în mod fluid la controalele jucătorului. Dar ce se întâmplă dacă computerul jucătorului este prea lent pentru a rula tot codul pentru logica jocului (răspuns la intrare, simularea gravitației, rularea rutinelor AI) și trageți totul pe ecran în 1/60 secunde?
În acest scenariu, putem folosi două bucle separate: o buclă de jocuri și o trageți buclă. Am putea apoi rula buclă de tragere la o frecvență mult mai mică decât bucla de joc; să spunem că reîmprospătăm ecranul jumătate de câte ori, adică la fiecare 1/30 de secundă.
Cantitatea de putere de procesare cerută de joc poate varia de la nivel la nivel. Luați în considerare un "shoot-up": primele câteva nivele vor avea foarte puține nave pe ecran, pentru a ușura jucătorul ușor, în timp ce ultimele niveluri ar putea avea zeci de nave inamice și sute de gloanțe care zboară în jurul aceleiași scene o singura data. Buclele de joc trebuie să-și dea seama cum ar trebui să se miște toate aceste obiecte, iar bucla de tragere trebuie să facă fiecare, astfel încât în timp ce s-ar fi putut executa atât buclă de joc, cât și buclă de tragere la fiecare 1/60 secunde la începutul jocului, până la sfârșit ceva trebuie să dea.
În general, este mai simplu să încetiniți bucla de tragere decât bucla de joc, dacă trebuie să alegeți. Ajustarea lungimii căpușei de joc a jocului înseamnă ajustarea tuturor lucrurilor din joc care se bazează pe timp; dacă Mario rulează la o viteză de 20 de pixeli / secundă și proiectați jocul cu o lungime de 1/60 de secundă, atunci trebuie să-l mutați cu 1/3 de pixel pe bifă. Dacă ajustați bucla de joc pentru a avea o lungime de cec de 1/30 din secundă, atunci trebuie să ajustați această valoare la 2 / 3rds dintr-un pixel per căpușă - și chiar aceasta este o simplă schimbare în comparație cu păstrarea calculelor de fizică și a rutinelor AI consistent.
Din acest motiv, jocurile deseori urmăresc să mențină coaja jocului consecventă și să încetinească ciclul de tragere dacă este nevoie de mai multă putere. Dacă ați activat vreodată contorul FPS (scurt pentru Cadre pe secundă, câte ori se execută bucla de tragere pe secundă) într-un shooter de prima persoană, veți fi văzut modificarea în funcție de cât de mult este pe ecran ; ritmul de reîmprospătare a buclă de tragere se ajustează automat. Jocul ar putea să arate jalnic - ca un film live streaming pe o conexiune lentă la internet - dar dacă nu se rulează pe un calculator cu mult mai puțină putere decât dezvoltatorii de jocuri au avut în minte, toate obiectele din lumea jocurilor vor continua să mutați și interacționați la viteze corecte.
Pentru un articol extraordinar care explică modul în care Flash se ocupă de acest lucru, consultați postul lui Sean Christmann pe "Elastic Racetrack".