Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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#

 

Predchádzajúci článok
Hra tetris v MonoGame: Generátor kociek
Všetky články v sekcii
Od nuly k tetrisu v MonoGame
Preskočiť článok
(neodporúčame)
Hra Tetris v MonoGame: Sprevádzkovanie hry
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity