Astăzi vom studia elementele din interiorul jocului Tetris, scris sub platformă Arduino și matrice LED.
Autorul acestui produs de casă este AlexGyver, autorul canalului YouTube cu același nume. Bine ați venit în minunata lume a pixelilor pătrați.
Să începem cu povestea. Tetrisul este un joc în care cifrele formate din 4 pătrate cad de sus în jos. În diferite combinații, aceste forme pot fi rotite și deplasate la stânga și la dreapta. Scopul jocului este de a colecta niveluri orizontale care sunt șterse și puncte care vă sunt acordate. Pierderea este considerată momentul în care noua cifră nu are unde să cadă. Tetrisul a fost inventat de programatorul sovietic Alexei Leonidovici Pazhitnov.
Versiunea originală a lui Pascal a apărut pe 6 iunie 1984. De atunci, Tetris a parcurs un drum lung și a fost portat la toate platformele pe care este posibil, în general, să joci jocuri, precum și la dispozitive care nu sunt destinate deloc jocurilor, cum ar fi un calculator de inginerie, un osciloscop și, nu vei crede, o fieră de lipit.
Prin numărul de versiuni comerciale vândute, Tetris este superior oricărui alt joc din istoria omenirii. Pentru doar un Game Boy, s-au vândut 35 de milioane de exemplare, ca să nu mai vorbim de jocul portabil Brick, pe care aproape toate îl aveau la un moment dat.
Vom începe implementarea tetrisului pe arduino și o matrice de culori cu analiza „cârligelor”. Matricea este formată din LED-uri cu trei culori de adresă. Problema cu acest tip de matrice este că este prea mișto. Culoarea fiecărui pixel este codificată cu 24 de biți, adică 8 biți pentru fiecare componentă: roșu, verde și albastru. Nu există un astfel de tip de date despre arduino, există următoarele - 32 de biți.
Culorile tuturor LED-urilor trebuie stocate în RAM, deoarece le vom schimba. Și în plus, pentru o matrice 16 cu 16, avem exact 1 KB de memorie dinamică ocupată, iar arduo nano are doar 2 dintre ele.
Adăugați încă câteva biblioteci și începeți să scrieți codul, memoria se va încheia. Autorul practic nu folosește, de exemplu, arduino mega, unde există mai multă memorie. Scopul este de a face jocul în mod special pe arduino nano, folosind instrumente simple, standard și binecunoscute, dar, în același timp, abordări și „cârje” non-standard și cu ajutorul lor să obțină cel mai optim cod.
Prima „cârjă” va fi refuzul de a stoca separat în memorie pozițiile figurilor și, în general, tot ceea ce se întâmplă pe ecran.Trebuie să păstrăm coordonatele punctelor cifrei de alimentare și coordonatele punctelor cifrelor deja scăzute, adică maxim, avem nevoie de un alt tablou, bidimensional 16 cu 16, iar acesta este de până la 256 octeți.
Tu și cu mine avem deja o serie de culori pentru toți pixelii, haideți să o folosim. Într-adevăr, pe lângă faptul că putem pune un punct colorat pe matrice, putem măsura lumina unui punct existent, astfel încât să lucrăm cu culori.
Tetrisul începe cu un bloc în cădere, care este controlat de butoane și are 2 coordonate în sistemul de coordonate matrice. Este foarte simplu, construim un cronometru, conform căruia blocul va cădea. Aceasta este biblioteca autorului, pe care o puteți citi pe site.
Pentru a procesa butoanele, autorul folosește și biblioteca sa. Schema de conectare a butoanelor este ridicol de simplă: 4 butoane, 8 fire.
La fiecare pas al cronometrului, desenăm un punct un pixel sub cel vechi și desenăm punctul vechi în negru, adică stingem LED-ul. Făcând clic pe buton, procedăm la fel, dar cu o coordonată orizontală. Ei bine, pentru decență, vom limita dimensiunea matricei, astfel încât punctul să nu depășească câmpul.
Vezi, nimic complicat. Dar acest lucru nu este de mult pentru că a venit momentul să tragem cifre. Vom acționa astfel: vom păstra referința la punctul de aprovizionare, pe care l-am scris deja, îl vom numi punctul principal sau blocul principal. Blocul principal se mișcă în sistemul de coordonate matrice, am făcut deja acest lucru. Toate figurile Tetrisului constau din 4 blocuri, motiv pentru care, apropo, se numește Tetris.
În consecință, rămâne în continuare să adăugăm încă 3 blocuri la blocul principal. Să scriem coordonatele lor în sistemul de coordonate al blocului principal, astfel încât blocul principal să fie întotdeauna mai jos. Este foarte simplu, luați figura literei inversate T. Blocul principal de jos în centru are coordonate 0.0 în sistemul său de coordonate.
Blocul superior este 0,1, dreapta este 1,1 iar stânga -1,1.
Luați litera G. Blocul inferior este 0.0, următorul 0.1, următorul 0.2 și marginea literei 1.2.
Scriem aceste coordonate în tablou în următoarea formă: {0.1, 0.2, 1.2} și aruncăm tabloul în memoria flash, pentru a nu pierde memoria dinamică. În ceea ce privește rotația cifrelor. Este imposibil să rotiți cifrele. Este corny, este foarte dificil să explici microcontrolerului cum să faci acest lucru. Pentru a face acest lucru, trebuie să setați centrul de rotație, să descompuneți cumva figura în părți și să căutați noi coordonate pentru fiecare parte, ținând cont de pixelarea puternică, ceea ce va duce, evident, la erori și va rezulta o prostie. Problema se rezolvă foarte simplu, vom păstra în memorie toate cele 4 poziții pentru toate cifrele și toate.
De fapt, acum rămâne să selectați la întâmplare numărul cifrei și să o atrageți în jurul blocului care se încadrează. Aici, pentru toate cele 3 blocuri rămase, luăm coordonatele din memoria flash, le transpunem în coordonatele globale ale matricei și pornim ledurile. Apropo, culoarea este aleasă, de asemenea, la întâmplare, dintre cele 6 cele mai simple și luminoase culori ale spațiului rgb. Unghiul de rotație al figurii la începutul rundei este, de asemenea, setat la întâmplare, iar când apăsați butonul în sus, trebuie doar să luați următorul set de coordonate pentru a desena și rotiți-l în sensul acelor de ceasornic. Mutarea unei forme funcționează la fel. Mai întâi, ștergem figura în poziția anterioară, adică o desenăm în negru, apoi în noua poziție desenăm culoarea curentă a figurii. La întoarcere, din nou, ștergem vechea poziție și doar desenăm una nouă.
Firmware-ul poate fi descărcat la. Vom analiza doar esența. Să începem verificând pereții din stânga și din dreapta și partea de jos. Totul este foarte simplu cu partea de jos, ne uităm la fiecare pas al căderii, unitatea de bază a atins o înălțime de 0, acest lucru nu este dificil, dar de fiecare dată când apăsăm butonul de control, trebuie să vedem dacă punctul extrem al formei pereților laterali ai matricei a fost atins.
Dacă este atins, nu mișcați figura. Același lucru este valabil și pentru rotația cifrelor. De exemplu, dacă noua poziție a figurii se extinde dincolo de pereți, atunci rotația este interzisă și, deoarece toate formele pe care le avem sunt de diferite forme, atunci blocurile extreme pentru acestea sunt diferite. Ar fi posibil să picteze blocuri extreme individuale pentru fiecare figură, pentru a simplifica activitatea microcontrolerului, dar să se considere că au inventat-o pentru asta.
Totul este foarte simplu. Dar următoarea sarcină este mult mai interesantă. Trebuie să verificăm coliziunile cu blocurile deja situate mai jos.Dacă am avea un tablou care conținea starea tuturor celulelor din câmp, ar fi mai ușor, dar vom folosi o serie de culori pentru pixelii casetei, deci vom avea cea mai tare "cârpă". Care este problema reală. Totul pare a fi simplu, o figură verde va cădea, iar la fiecare pas al toamnei, fiecare schimbare în lateral și fiecare încercare de întoarcere ar trebui să verifice dacă figura din noua poziție se bazează pe figurile deja culcate. Dacă pentru toate blocurile, culoarea înconjurătoare este egală cu negrul sau egală cu culoarea figurii, atunci permitem deplasarea în direcția dorită. Acest lucru va funcționa până când forma de sub noi va fi aceeași culoare ca și forma care se încadrează. Aceasta este de fapt „cârja”: vom picta forma căzută într-o altă culoare. Repetă imperceptibil pentru ochi, dar este vizibil pentru program. Tot ce trebuie să faceți este să creșteți ușor luminozitatea culorii curente a formei și asta este totul.
Figura a căzut pe partea inferioară sau pe o altă figură, luminozitatea sa nu a crescut vizibil, iar în noua rundă, figurile care scad nu își vor mai confunda culoarea cu a lor, vor cădea pe ea și la fel de fix, adăugând ușor luminozitatea.
Apropo, când apăsați butonul în jos, cifra se grăbește cu viteză mare și își ia locul.
Tetrisul nostru este lăsat cu atingerea finală, și anume verificarea și ștergerea nivelurilor umplute pe orizontală. Totul este simplu aici. După fixarea cifrei din runda curentă, ne deplasăm de-a lungul liniilor și comparăm culorile pixelilor cu negrul. Dacă nu există un singur pixel negru în întreaga linie, atunci vom șterge întreaga linie.
Liniile detectate sunt umplute cu alb, apoi luminozitatea scade treptat la zero și se obține animația. În plus, toți pixelii, începând de la prima linie completată în partea de sus, sunt mutați în jos și numărul de linii care au fost șterse. Acest proces se repetă până când nu există niveluri finalizate. Verificăm și dacă am ajuns în vârf, ceea ce înseamnă să pierdem. În acest caz, este afișat un cont egal cu numărul de niveluri șterse.
Contul este afișat în numere, care sunt stocate în memorie ca un set de unități și zerouri, prin care ledurile sunt apoi activate sau dezactivate. Așa arată Tetris scris în matricea de adrese. Vă mulțumim pentru atenție. Ne vedem curând!
video: