Python týden Geek tričko zdarma
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde
Pouze tento sleva až 80% na kurzy Python

Lekce 16 - Hra tetris v MonoGame: Dokončení

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Hra tetris v MonoGame: Skóre, jsme si vytvořili komponentu skóre a ukázali si jak uvést komponentu do výchozího stavu při zobrazení. V dnešním MonoGame tutoriálu naprogramujeme ukládání a načítání výsledků a všechno hezky propojíme. Tím uzavřeme náš on-line kurz a budete mít hru hotovou se vším všudy. On-line skóre si necháme do bonusové lekce, jelikož budeme potřebovat použít další technologie a bylo by fajn nejprve dokonči hru v C# za použití ukládání skóre do XML.

Komponenta skóre využívá třídu SkoreKlient, ve které máme připravené metody pro ukládání a načítání.

Ukládání

Budeme ukládat do souboru XML s názvem skore.xml. Ale vůbec nic vám nebrání, abyste ukládali skóre dle libosti kamkoli jinam, i na server, jak si ukážeme dále.

Struktura XML souboru bude vypadat následovně

<?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átu tedy jednotlivé instance třídy Hrac uložíme. Zdrojový kód metody Uloz() bude nyní vypadat 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);
    }
}

Pokud soubor neexistuje, tak jej vytvoříme a uložíme do něj první výsledek. Pokud již existuje, vyhledáme element s hráči a před posledního (prvního zapsaného) přidáme nově přidávaného. Tím budeme mít výsledky řazené podle posledního přidaného. Pokud budeme chtít řadit jinak, vyřešíme to v komponentě KomponentaSkoreTabulka. Proměnná soubor je řetězec obsahující název souboru s příponou .xml, jak jsme si ji minule nachystali.

Načítání

Načítání hráčů může vypadat např. takto:

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;
}

Postupně načítáme ze souboru a ukládáme do seznamu, který poté vracíme. Do toho jak pracuje XmlReader, XmlWriter a XDocument zabíhat nebudu, protože jsou detailně popsané v Práce se soubory v C# .NET.

Přidání herní obrazovky

Zbývá upravit třídu Hra a přidat jí herní obrazovku obrazovkaSkore. V komponentě menu navíc upravíme co se má stát pokud uživatel bude na položce Skore a zmáčkne Enter. Kód bude vypadat následovně:

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 již bude možné uložení skóre po skončení hry. Určitě si ale povšimnete malé nedokonalosti a to že pokud chceme z menu zobrazit tabulku skóre, tak se nám zobrazí otázka, zda chceme uložit skóre. To je samozřejmě špatně, protože jsme hru dosud nehráli a současně by se nám uložil pokaždé hráč, který nemá žádné body. Oprava nezabere moc času ani úsilí. Upravíme komponentu skóre, aby když hráč nebude mít body, tak rovnou nastavíme stav na výpis a nikoli na otázku. To vše obstará jedna podmínka v try bloku v metodě OnEnabledChanged(). Bude vypadat takto:

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

Toto byla malá úprava, abychom odchytili poslední nedostatek, který rušil jinak pěkný zážitek ze hry.

Kompletní kódy jsou přiloženy jako vždy. Hru máme kompletní se všemi funkcionalitami, které jsme chtěli :) Příště, v lekci Hra tetris v MonoGame: Webový server, na vás čeká on-line skóre tabulka.


 

Stáhnout

Staženo 67x (13.23 MB)

 

 

Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!