8. diel - Hra tetris v MonoGame: Hracia plocha
V minulej lekcii, {previos}, sme si naprogramovali generátor kociek do hry Tetris. Dnes si vytvoríme ďalšie herné objekt, ktorým bude hracia plocha.
Hracia plocha
Už máme komponentu level, v ktorej sa bude hra odohrávať. Máme generátor náhodných kociek a objekt padajúce kocky. Chýba nám hracia plocha.
Ide o objekt, ktorý bude obsahovať dvojrozmerné pole už opadaných kociek. Ďalej metódu na zistenie, či padajúce kocka s hracou plochou koliduje, metódu na pripojenie kocky k napadaným kockám plochy, metódu na vymazanie plných radov a samozrejme metódu k vykreslenie políčok plochy.
Pripojme si k projektu triedu HraciPlocha
, opäť ju nastavíme
ako public
a pridáme potrebné using
:
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics;
Atribúty
Podobne ako u kocky pridáme atribút s políčkami:
private int[,] policka;
Ďalej šírku a výšku hracej plochy v políčkach:
private int sirka; private int vyska;
Posledným atribútom bude vykresľovací pozície hracej plochy na pozadí levelu:
private Vector2 pozice;
Vyprázdnenie políčok
Pridáme si jednoduchú metódu, ktorá hraciu plochu vyprázdni, presnejšie inicializuje políčka:
public void Vyprazdni() { policka = new int[sirka, vyska]; }
Konštruktor
Teraz vytvoríme konštruktor, ten bude brať v parametroch rozmery a pozíciu hracej plochy. Ďalej inštanciu inicializuje:
public HraciPlocha(int sirka, int vyska, Vector2 pozice) { this.sirka = sirka; this.vyska = vyska; this.pozice = pozice; Vyprazdni(); }
Posadenie nové kocky
Ďalšou metódou bude PosadKostku()
, ktoré odovzdáme v
parametri novú kocku a ona nám vráti súradnice, na ktorých sa kocka objaví
hore, v strede hracej plochy.
public Vector2 PosadKostku(Kostka kostka) { return new Vector2(((int)sirka / 2) - 1, 0); }
Nič zložitého na premýšľanie, šírku hracej plochy jednoducho
vydelíme celočíselne dvoma a máme stred. Metóda by sa mala správať podľa
toho, akú kocku ju odovzdávame, aby bola správne vycentrovaná au niektorých
kociek by sme mali nastaviť zložku Y
na -1
, pretože
je prvý rad políčok kocky prázdna. To ale zatiaľ pre jednoduchust
zanedbáme.
Pripojenie kocky k hracej ploche
Poďme ďalej, implementujte metódu Pripoj()
, ktorá bude
opäť brať v parametri kocku a jej políčka pripojí k políčkam hracej
plochy, teda medzi ostatné, už spadnuté kocky. Prejdeme cykly všetky
políčka kocky a ak je políčko kocky zaplnené a zároveň nevyčnieva hore z
hracej plochy (to sa môže na konci hry stáť a musíme s tým počítať),
pripojíme ho na príslušnú pozíciu do políčok hracej plochy.
public void Pripoj(Kostka kostka) { // projetí všech políček kostky for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++) { // získání souřadnic políčka v hrací ploše int x = Convert.ToInt32(i + kostka.pozice.X); int y = Convert.ToInt32((j + kostka.pozice.Y)); // políčko je zaplněné a nevyčnívá zhora z hrací plochy if ((kostka.Policka[i, j] > 0) && (y >= 0)) policka[x, y] = kostka.Policka[i, j]; } }
Trochu nešikovné tu je, že musíme skonvertovať reálne zložky vektora na celočíselné. Niekedy sa nám vektory ale zas hodí.
Kolízie kocky
Ďalšou dôležitou metódou k implementácii je metóda
Kolize()
, ktorá vráti true
, ak kocka koliduje s
nejakými políčkami v hracej ploche. Metóda bude brať ako parametre kocku a
jej pozíciu. Kocka samotná síce svoju pozíciu obsahuje, ale nám sa bude
hodiť pýtať sa: "kolidoval by kocka, keby bola na pozíciu ...", preto budeme
odovzdávať aj pozíciu.
Z počiatku budeme predpokladať, že ku kolízii nedošlo. Vytvoríme si
teda premennú kolize
a nastavíme ju na false
. Potom
ako vždy prejdeme všetky políčka kocky:
public bool Kolize(Kostka kostka, Vector2 pozice) { bool kolize = false; for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++)
Teraz nás čaká pomerne zložitá podmienka, ktorú si však pekne rozpíšeme. Ak je políčko v kocke plnej:
if ((kostka.Policka[i, j] > 0) &&
a vyšlo z hracej plochy:
((j + pozice.Y >= vyska) || (i + pozice.X < 0) || (i + pozice.X >= sirka) ||
alebo sa prekrýva s iným políčkom hracej plochy:
(policka[Convert.ToInt32(i + pozice.X), Convert.ToInt32(j + pozice.Y)] > 0)))
potom ku kolízii došlo:
kolize = true;
Nakoniec výsledok vrátime. Kompletný kód metódy je nasledujúci:
public bool Kolize(Kostka kostka, Vector2 pozice) { // budeme předpokládat, že nedošlo ke kolizi bool kolize = false; // projetí všech políček kostky for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++) // Pokud je políčko v kostce plné a if ((kostka.Policka[i, j] > 0) && // vyjelo z hrací plochy nebo ((j + pozice.Y >= vyska) || (i + pozice.X < 0) || (i + pozice.X >= sirka) || // překrývá se s jiným políčkem hrací plochy (policka[Convert.ToInt32(i + pozice.X), Convert.ToInt32(j + pozice.Y)] > 0))) // došlo ke kolizi kolize = true; return kolize; }
Zostáva nám už len vymazanie radov a vykreslenie.
Vymazanie radov
Metóda VymazRady()
vymaže plné radu v políčkach hracej
plochy a samozrejme políčka nad radom zosunie dolu. Návratová hodnota bude
typu int
a bude udávať, koľko radov bolo vymazané. To bude
neskôr dôležité pre výpočet skóre.
Najprv si vytvoríme počítadlo vymazaných radov a to nastavíme na
0
. Ďalej for
cyklom prejdeme všetky rady hracej
plochy. Nakoniec počítadlo vrátime:
public int VymazRady() { // kontrola plných řad int pocet = 0; for (int rada = 0; rada < vyska; rada++) { } return pocet;
V každej iterácii cyklu musíme zistiť, či je daná séria plná. Spočiatku budeme predpokladať že áno, potom prejdeme rad políčko po políčku a ak nájdeme nejaké prázdne, usúdime, že mnoho plná nie je:
// předpokládáme, že je řada plná bool plna = true; // pokud je někde prázdné políčko, plná není for (int i = 0; i <= (sirka - 1); i++) if (policka[i, rada] == 0) plna = false;
V prípade plnej radu zostáva posunúť všetky políčka nad radom o 1 nadol a zvýšiť počítadlo plných radov. Pôjdeme pospiatky:
// smazání plné řady if (plna) { // posun políček nad řadou dolů for (int j = (rada - 1); j > 0; j--) for (int i = 0; i < sirka; i++) policka[i, j + 1] = policka[i, j]; pocet++; }
Opäť pre istotu prikladám kód celej metódy:
public int VymazRady() { // kontrola plných řad int pocet = 0; for (int rada = 0; rada < vyska; rada++) { // předpokládáme, že je řada plná bool plna = true; // pokud je někde prázdné políčko, plná není for (int i = 0; i <= (sirka - 1); i++) if (policka[i, rada] == 0) plna = false; // smazání plné řady if (plna) { // posun políček nad řadou dolů for (int j = (rada - 1); j > 0; j--) for (int i = 0; i < sirka; i++) policka[i, j + 1] = policka[i, j]; pocet++; } } return pocet; }
Vykreslenie hracej plochy
Doplňme vykresľovací metódu, na tej nie je nič zložité, vykreslenie hracej plochy prebieha úplne rovnako, ako to bolo pri vykreslenie kocky:
public void Vykresli(SpriteBatch spriteBatch, Texture2D[] sprity) { for (int j = 0; j <= (vyska - 1); j++) for (int i = 0; i <= (sirka - 1); i++) if (policka[i, j] != 0) spriteBatch.Draw(sprity[policka[i, j] - 1], new Vector2(pozice.X + i * sprity[0].Width, pozice.Y + j * sprity[0].Height), Color.White); }
Trieda HraciPlocha
je zatiaľ hotová. Nabudúce, v lekcii
Hra Tetris v MonoGame: Sprevádzkovanie hry , si ju vyskúšame a hru sprevádzkujeme
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 206x (11.9 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#