[CZĘŚĆ 1] STM32Butterfly2: Tetris na STM32 – wprowadzenie do mechanizmu gry
W przypadku, kiedy równanie w warunku jest prawdziwe (wystąpiła kolizja) ustawiana jest zmienna kolizja zwracana później w wyniku działania funkcji.
W tej samej funkcji umieścimy także warunki sprawdzające czy klocek nie wystaje poza boczne ścianki planszy:
if(x > 9) kolizja=1;
…i czy nie przeszedł poniżej jej „dna”:
if(y > 19) kolizja=1;
Gotowa funkcja będzie wyglądała następująco:
unsigned char Kolizja(unsigned char kx, unsigned char ky, unsigned char r)
{
unsigned char x,y,i,kolizja;
kolizja=0;
for(i=0;i<4;i++) //pętla odlicza kolejne cztery segmenty klocka
{ //(każdy klocek składa się z czterech segmentów)
x=klocki[kloceknr][r][i][0]+kx-2; //obliczanie współrzędnych na planszy
y=klocki[kloceknr][r][i][1]+ky-2; danego segmentu klocka
if(x > 9) kolizja=1; //sprawdzenie czy segment jest
poza ściankami bocznymi planszy
if(y > 19) kolizja=1; //sprawdzenie czy segment jest
poniżej dna planszy
if(plansza[x][y]) kolizja=1; //sprawdzenie czy segment
//nie nakłada się na istniejący punkt na planszy
}
return kolizja; //jeżeli wykryto kolizję
//to funkcja zwraca 1 w innym razie 0
}
Teraz wystarczy, że przed każdym kolejnym ruchem klocka będziemy sprawdzać czy nie wywoła od kolizji. Przykładowo przed opuszczeniem klocka w dół sprawdzimy następujący warunek:
if(Kolizja(klocekx,kloceky+1,klocekr) == 0) kloceky++;
Konstrukcja taka zwiększy zmienną kloceky o jeden, tylko w przypadku, kiedy funkcja sprawdzająca zwróci wartość 0. Podstawiając do funkcji współrzędna y klocka zwiększona o jeden sprawdzamy czy opuszczenie klocka spowoduje kolizję, zanim opuścimy klocek. Analogicznie będziemy sprawdzać wystąpienie kolizji podczas wykonywania klockiem ruchów na boki. Przygotujmy zatem komplet funkcji odpowiedzialnych za poszczególne ruchy klocka. Pierwsza funkcja przemieszcza klocek o jedno pole w lewo:
void KlocekLewo(void)
{
if(Kolizja(klocekx-1,kloceky,klocekr) == 0) //sprawdzenie czy przesunięty klocek
nie wywoła kolizji
{ //jeżeli nie to:
klocekx--; //zmniejsz zmienną x położenia klocka
}
}
Proste, prawda? Myślę, że już każdy wie jak będzie wyglądała funkcja przemieszczająca klocek w prawo. Równie proste będzie obracanie klocka. Wystarczy tylko zmienić wartość jednej zmiennej, na kolejną z 4 wartości, jakie może przyjąć:
void KlocekObroc(void)
{
if(Kolizja(klocekx,kloceky,klocekr+1) == 0) //sprawdzenie czy obrócony klocek
//nie wywoła kolizji
{ //jeżeli nie to:
klocekr++; //zwiększ zmienną obrotu klocka
if(klocekr > 3) klocekr = 0;
}
}
Mam nadzieję, że już widzicie zalety proponowanego rozwiązania. Pozostała nam jeszcze do napisania funkcja przemieszczająca klocek o jedno pole w dół. Tutaj sytuacja będzie nieco bardziej skomplikowana. Zastanówmy się jak nasz program powinien zareagować, jeżeli podczas opuszczania klocka kolejny ruch nie będzie możliwy. Klocek, który do tej pory był w ruchu powinien zostać odwzorowany na planszy w postaci stałych jej segmentów. Napiszmy wiec funkcję, która będzie tego dokonywała. Podobnie jak w przypadku sprawdzania kolizji zbudujemy pętlę odliczającą kolejne segmenty klocka, wewnątrz której będziemy obliczać ich współrzędne na planszy. Z tą jednak różnicą, że ustawimy odpowiednie komórki w tablicy odwzorowującej planszę.
void KlocekWklej(void)
{
unsigned char x,y,i;
for(i=0;i<4;i++) //pętla odlicza kolejne 4 segmenty klocka
{
x=klocki[kloceknr][klocekr][i][0] + klocekx-2; //oblicz położenie
segmentu na planszy
y=klocki[kloceknr][klocekr][i][1] + kloceky-2;
plansza[x][y]=1; //zapal punk na planszy w miejscu segmentu klocka
}
}
Kolejnym działaniem po odwzorowaniu klocka na planszę będzie wygenerowanie kolejnego klocka. Będzie to polegało na ustawieniu współrzędnych klocka na położenie początkowe. Wyzerowaniu zmiennej obrotu klocka, oraz zmiany rodzaju klocka na inny, najlepiej w sposób losowy. Tworzymy kolejna funkcję, która będzie za to odpowiedzialna:
void KlocekNowy(void)
{
kloceknr=nkloceknr; //kopiuj rodzaj klocka jaki był następny jako bierzący
nkloceknr=rkloceknr; //kopiuj rodzaj następnego klocka z zmiennej losującej
if(kloceknr==nkloceknr) //jeżeli następny klocek jest taki sam jak bierzący
{
rkloceknr++; //zwiększ zmienną losującą
if(rkloceknr>6) rkloceknr=0;
nkloceknr++; //zwiększ zmienną z rodzajem kolejnego klocka
if(nkloceknr>6) nkloceknr=0;
}
klocekr=0; //zerowanie położenia nowego klocka na planszy
klocekx=5;
kloceky=2;
}

Tester baterii GBM-3300 marki GW Instek
NCS-PX133P-J2-J
Bezpieczne kleje anaerobowe, dwuskładnikowe kleje strukturalne oraz innowacyjne systemy dozowania w ofercie Semicon 




