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í.

16. diel - Hra tetris v MonoGame: Dokončenie

V minulej lekcii, Hra tetris v MonoGame: Skóre , sme si vytvorili komponent skóre a ukázali si ako uviesť komponent do východiskového stavu pri zobrazení. V dnešnom MonoGame tutoriálu naprogramujeme ukladanie a načítanie výsledkov a všetko pekne prepojíme. Tým uzavrieme náš on-line kurz a budete mať hru hotovú so všetkým. On-line skóre si necháme do bonusovej lekcie, pretože budeme potrebovať použiť ďalšie technológie a bolo by fajn najprv dokonči hru v C# za použitia ukladania skóre do XML.

Komponent skóre využíva triedu SkoreKlient, v ktorej máme pripravené metódy pre ukladanie a načítanie.

Ukladanie

Budeme ukladať do súboru XML s názvom skore.xml. Ale vôbec nič vám nebráni, aby ste ukladali skóre podľa ľubovôle kamkoľvek inam, aj na server, ako si ukážeme ďalej.

Štruktúra XML súboru bude vyzerať nasledovne

<?xml version="1.0" encoding="utf-8"?>
<hraci>
  <hrac>
    <prezdivka><!-- Sem přijde přezdívka --></prezdivka>
    <body><!-- Sem přijdou dosažené body --></body>
  </hrac>
</hraci>

V tomto formáte teda jednotlivé inštancie triedy Hrac uložíme. Zdrojový kód metódy Uloz() bude teraz vyzerať takto:

public void Uloz(Hrac hrac)
{
    if (!File.Exists(soubor))
    {
        XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
        xmlWriterSettings.Indent = true;
        xmlWriterSettings.NewLineOnAttributes = true;
        using (XmlWriter xmlWriter = XmlWriter.Create(soubor, xmlWriterSettings))
        {
            xmlWriter.WriteStartDocument();
            xmlWriter.WriteStartElement("hraci");
            xmlWriter.WriteStartElement("hrac");
            xmlWriter.WriteElementString("prezdivka", hrac.prezdivka);
            xmlWriter.WriteElementString("body", hrac.body.ToString());
            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndDocument();
            xmlWriter.Flush();
            xmlWriter.Close();
        }
    }
    else
    {
        XDocument xDocument = XDocument.Load(soubor);
        XElement koren = xDocument.Element("hraci");
        IEnumerable<XElement> polozky = koren.Descendants("hrac");
        XElement polozka = polozky.First();
        polozka.AddBeforeSelf(
           new XElement("hrac",
               new XElement("prezdivka", hrac.prezdivka),
               new XElement("body", hrac.body)));
        xDocument.Save(soubor);
    }
}

Ak súbor neexistuje, tak ho vytvoríme a uložíme do neho prvý výsledok. Ak už existuje, vyhľadáme element s hráčmi a pred posledného (prvého zapísaného) pridáme novo pridávaného. Tým budeme mať výsledky zoradené podľa posledného pridaného. Ak budeme chcieť radiť inak, vyriešime to v komponente KomponentaSkoreTabulka. Premenná soubor je reťazec obsahujúci názov súboru s príponou .xml, ako sme si ju minule nachystali.

Načítanie

Načítanie hráčov môže vyzerať napr. Nasledovne:

public List<Hrac> Nacti()
{
    string element = "";
    var hrac = new Hrac();
    var hraci = new List<Hrac>();
    using (var xr = XmlReader.Create(soubor))
    {
        while (xr.Read())
        {
            if (xr.NodeType == XmlNodeType.Element)
                element = xr.Name;
            else
            if (xr.NodeType == XmlNodeType.Text)
            {
                switch (element)
                {
                    case "prezdivka":
                        hrac.prezdivka = xr.Value;
                        break;
                    case "body":
                        hrac.body = long.Parse(xr.Value);
                        break;
                }
            }
            else if ((xr.NodeType == XmlNodeType.EndElement) && (xr.Name == "hrac"))
            {
                hraci.Add(hrac);
                hrac = new Hrac();
            }
        }
    }
    return hraci;
}

Postupne načítame zo súboru a ukladáme do zoznamu, ktorý potom vraciame. Do toho ako pracuje XmlReader, XmlWriter a XDocument zabiehať nebudem, pretože sú detailne popísané v Práca so súbormi v C# .NET.

Pridanie hernej obrazovky

Zostáva upraviť triedu Hra a pridať jej herné obrazovku obrazovkaSkore. V komponente menu navyše upravíme čo sa má stať ak užívateľ bude na položke Skore a stlačí Enter. Kód bude vyzerať nasledovne:

Hra.cs

public HerniObrazovka obrazovkaMenu, obrazovkaLevel, obrazovkaAutori, obrazovkaSkore; // přidáno

/* Ostatní kód */

protected override void Initialize()
{
    KomponentaMraky mraky = new KomponentaMraky(this);
    KomponentaLevel level = new KomponentaLevel(this);
    KomponentaAutori autori = new KomponentaAutori(this);
    KomponentaSkoreTabulka skoreTabulka = new KomponentaSkoreTabulka(this); // přidáno
    KomponentaPolozkyMenu polozkyMenu = new KomponentaPolozkyMenu(this, new Vector2(700, 250), Color.Red, Color.Yellow, 80);
    polozkyMenu.PridejPolozku("StArT");
    polozkyMenu.PridejPolozku("SkOrE");
    polozkyMenu.PridejPolozku("AuToRi");
    polozkyMenu.PridejPolozku("KoNeC");
    KomponentaMenu menu = new KomponentaMenu(this, polozkyMenu);

    obrazovkaMenu = new HerniObrazovka(this, mraky, menu);
    obrazovkaLevel = new HerniObrazovka(this, mraky, level);
    obrazovkaMenu = new HerniObrazovka(this, mraky, menu, polozkyMenu);
    obrazovkaAutori = new HerniObrazovka(this, mraky, autori);
    obrazovkaSkore = new HerniObrazovka(this, mraky, skoreTabulka); // přidáno

    foreach (GameComponent komponenta in Components)
    {
        PrepniKomponentu(komponenta, false);
    }
    graphics.PreferredBackBufferWidth = sirkaOkna;
    graphics.PreferredBackBufferHeight = vyskaOkna;
    graphics.IsFullScreen = false;
    graphics.ApplyChanges();
    base.Initialize();
}

KomponentaMenu.cs

public override void Update(GameTime gameTime)
{
    // enter - akce podle vybrané položky
    if (hra.NovaKlavesa(Keys.Enter))
    {
        switch (polozkyMenu.vybranaPolozka.text)
        {
            case "StArT":
                hra.PrepniObrazovku(hra.obrazovkaLevel);
                hra.PrepniHudbu(hra.hudba_zardax);
                break;
            case "SkOrE":
                hra.PrepniObrazovku(hra.obrazovkaSkore);
                break;
            case "AuToRi":
                hra.PrepniObrazovku(hra.obrazovkaAutori);
                break;
            case "KoNeC":
                hra.Exit();
                break;
        }
    }
    base.Update(gameTime);
}

KomponentaLevel.cs

/* Update skce pro vytvoření nové kostky */
if (hraciPlocha.Kolize(kostka, kostka.pozice))
    hra.PrepniObrazovku(hra.obrazovkaSkore);

Po týchto úpravách už bude možné uloženie skóre po skončení hry. Určite si ale všimnete malé nedokonalosti a to že ak chceme z menu zobraziť tabuľku skóre, tak sa nám zobrazí otázka, či chceme uložiť skóre. To je samozrejme zle, pretože sme hru doteraz nehrali a súčasne by sa nám uložil zakaždým hráč, ktorý nemá žiadne body. Oprava nezaberie veľa času ani úsilia. Upravíme komponent skóre, aby keď hráč nebude mať body, tak rovno nastavíme stav na výpis a nie na otázku. To všetko obstará jedna podmienka v try bloku v metóde OnEnabledChanged(). Bude vyzerať takto:

if (hra.hrac != null && hra.hrac.body > 0)
    stav = eStav.Otazka;
else
    stav = eStav.Vypis;

Toto bola malá úprava, aby sme odchytili posledný nedostatok, ktorý rušil inak pekný zážitok z hry.

Kompletné kódy sú priložené ako vždy. Hru máme kompletný so všetkými funkcionalitami, ktoré sme chceli :) Nabudúce, v lekcii Hra tetris v MonoGame: Webový server , na vás čaká on-line skóre tabuľka.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 495x (13.23 MB)

 

Predchádzajúci článok
Hra tetris v MonoGame: Skóre
Všetky články v sekcii
Od nuly k tetrisu v MonoGame
Preskočiť článok
(neodporúčame)
Hra tetris v MonoGame: Webový server
Článok pre vás napísal Matouš Kratochvíl
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje C#
Aktivity