Care a fost motivul pentru scrierea acestui articol?
1 Întrebări adresate utilizatorilor acestui site despre cum să scrieți tetris.
2 Recent scrise de mine nu este clar pentru ce motive și în ce scop Tetris. În copilăria mea nu am încercat să scriu tetris. Un pic maturit a decis sa realizeze un vis din copilarie :)
3 O dorință banală de a-mi arăta eu și întreaga lume ce programator minunat sunt și știu cum să scriu tetris :)
Totul este bine de vorbit. Să mergem la afaceri.
În primul rând, trebuie să ne imaginăm care sunt părțile jocului nostru. În tetris există cifre (clasă Figura) și câmp (câmp de clasă). Avem de asemenea nevoie de o lume (clasa Mondială), va conține un câmp, două cifre (care se încadrează și următorul), puncte, nivel și alte informații.
Să ne gândim la ce va cuprinde cifra noastră. Există mai multe opțiuni. Noi alegem mai simplu. Să luăm ca bază faptul că figura noastră este un fel de matrice cu dimensiunea N pe M conținând celule goale și umplut. Acum trebuie să decidem ce este celula. De fapt, trebuie să știm dacă este plină sau nu. Deci, pentru reprezentarea celulei, este suficient pentru noi să fim de tipul "BOOL". De asemenea, figura conține informații despre culoarea și poziția pe câmpul de joc. Din tot ceea ce sa spus, aceasta este structura pe care o obținem:
Ce nu ne place aici? Mai întâi, matricea însăși. Deoarece această abordare trebuie să fie atât de mare încât să se potrivească cu cea mai mare figură. Cea mai mare cifră vom fi în lungime de 4 celule și lățimea de 1 Tetris este posibil cifre basculează aici obținem o matrice pătrată de dimensiune 4 de 4. Dezavantajul unei astfel de matrice este „complexitatea“ verifica pentru mișcările verticale și orizontale. Acest lucru se datorează faptului că o parte din cifra va depăși domeniul nostru. Continuând de aici, ne schimbăm matricea de la statică la dinamică.
În această versiune, am înlocuit tipul BOOL cu UNSIGNED INT, acest lucru sa făcut deoarece STL implementează în mod specific STD :: VECTOR
Asta e tot. Putem lucra din nou cu matricea noastră ca o matrice bidimensională.
În clasa Figura, s-au înregistrat și alte modificări. Culoarea figurii noastre a dispărut. Vom vorbi despre asta într-o altă secțiune.
Și așa! Câmpul nostru are dimensiunea N pe M în exact același fel ca și figura. Ca și cifra ar trebui să conțină informații despre dacă celula este goală sau nu. Și, de asemenea, culoarea acestei celule. Vom codifica culoarea celulei în int unsigned (0xAARRGGBB). Acum, o cușcă de nișă pentru a stoca în sine atât culoare cât și informații despre dacă acestea sunt goale sau nu. Dacă celula nu este zero, înseamnă că este plină dacă zero este gol. Acesta este modul în care arată domeniul nostru:
Veți spune că nu diferă mult de figură. Și veți avea absolută dreptate. Propun să combinăm totul din cele două clase într-o singură entitate:
Acum vedem că domeniul nostru și cifra sunt moștenite de la GameObj. Și în clasele Figura și Câmpul erau doar acele lucruri pe care le deosebesc radical unul de celălalt. Din ultima listă a clasei Figura, Field, putem vedea că au adăugat mai multe detalii în ele într-un mod "magic". Hai să vorbim despre ei acum.
Analiza detaliată
Cred că nu este nimic de explicat aici și totul este clar. Vreau doar să observ că clasa conține un indicator pentru clasa de câmp. Acest pointer este primit în constructor. Prin această abordare, putem numi ușor funcțiile câmpului de care avem nevoie, ceea ce facem cu succes.
Funcția RotateLeft ne rotește figura în stânga.
Cum funcționează. Creați o nouă figură. Figura newFigure (câmp_, înălțime_, lățime_). Intrăm în figura nouă datele din matricea noastră cu privire la rotație. Setați poziția și verificați o coliziune cu câmpul. Dacă există o coliziune, atunci nu este posibilă întoarcerea figurii. Dacă nu, atunci cu o conștiință clară schimbăm datele figurinei noastre pe datele rotite.
Actualizați aici ne mutăm cifra pe orizontală și pe verticală și, de asemenea, verificăm posibilitatea căderii sale ulterioare. Dacă nu există altceva unde să cadă, datele din figură sunt transferate pe câmp și cifra este marcată ca fiind "fly_ = false";
Câmp de analiză detaliat
În această clasă nu este nimic de discutat. Doar listați cele mai interesante caracteristici și spuneți-le ce fac.
Hit - verifică dacă trebuie să renunți la figura sau sub spațiul deja ocupat
Coliziune - verificați intersecția cu celulele ocupate deja de câmp și cifrele.
SetFigure - transferă datele câmpului în câmp.
KillLine - verifică posibilitatea eliminării liniei. Dacă unitatea curentă elimină linia, ea stropeste celulele superioare în jos, adaugă puncte și mărește contorul liniilor luate.
De fapt, încă nu am atins clasa mondială. Aici este:
Nu este nimic interesant în această clasă. Excepția este GenerateNext.
După ce ați studiat această funcție, puteți observa că 5 clase sunt create și inițializate accidental, la amintirea cărora nu există loc. Să ne uităm la ce sunt aceste clase. Iată unul dintre ei:
Vedem că moșteneste din clasa Figura cu care suntem deja familiarizați și constă dintr-un constructor. Iată ce se întâmplă în constructor:
În acest designer, figura noastră este creată. Acele celule care sunt umplute cu zero vor fi goale, restul va fi afișat pe ecran. Creând astfel de clase, noi creăm diferite forme. Toți sunt băieții!
Tetrisul scris aici nu este un produs complet. Acesta conține bug-uri și unele defecte. Eu cu siguranță ar putea remedia problema, dar m-am gândit că nu ar fi atât de plictisitor cititor și el ar putea distra însuși încredințat sarcina să-i decât dacă este necesar :) Deci, du-te pentru ea!
Este greu de spus dacă procesul de creare a unui joc din acest articol este de înțeles, dar dacă nu este clar pentru acest caz, codul sursă este atașat.
Vă mulțumesc tuturor pentru a citi până aici și noroc pe un domeniu dificil;)