18. diel - Hra tetris v MonoGame: Webový klient
V minulej lekcii, Hra tetris v MonoGame: Webový server , sme si pripravili jednoduchý PHP server s MySQL databázou. V dnešnej bonusovej lekcii si ukážeme ako na tento server skóre odoslať a tiež ako internetové skóre v našej hre zobraziť. Tak smelo do toho.
WebKlient
Po vzore triedy SkoreKlient
si teraz vytvoríme novú triedu
WebKlient
. Tá nebude sa skóre pracovať lokálne, ale cez
internet. Inak bude fungovať úplne rovnako. Rovnako bude potrebné upraviť
komponent KomponentaSkoreTabulka
. A to je celé.
Trieda WebKlient
bude mať metódy Uloz()
,
Nacti()
a novo i Stahni()
. Pridáme
ešte konštanty pre držanie URL potrebných pre uloženie a načítanie.
Trieda bude vyzerať takto:
public class WebKlient { public string ChybaNacitani => $"Chyba při načítání skóre z internetu."; // přidáno private WebClient webKlient; private const string urlPridat = "http://localhost:8000/uloz"; private const string urlVypsat = "http://localhost:8000/stahnout"; private string soubor; public WebKlient() { webKlient = new WebClient(); soubor = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"robotris\skore.xml"); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(soubor)); } public void Uloz(Hrac hrac) { // Doplníme později } public void Stahni() { // Doplníme později } public List<Hrac> Nacti() { // Doplníme později } }
Nezabudnite si upraviť 2 URL adresy na vaše skripty. Mohli by vyzerať napr. Nasledovne:
private const string urlPridat = "https://www.mujweb.cz/robotris_skore_uloz.php"; private const string urlVypsat = "https://www.mujweb.cz/robotris_skore_nacti.php";
Všimli ste si určite nového atribútu typu WebClient
. Táto
.NET trieda obsahuje všetko potrebné pre vykonanie HTTP dotazu a zábalom ich
do jednoduchých metód, ktoré vzápätí použijeme. Sú to
OpenRead()
a DownloadFile()
. WebClient
treba naimportovať pomocou pridanie using System.Net;
medzi
using
y na začiatku súboru.
Konštruktor
V triede WebKlient
neinicializujú premennú soubor
hneď pri jej deklarácii, ale až v konstruktoru, pretože chceme opísať
cestu k súboru a vytvoriť priečinok.
K vytvoreniu cesty je veľmi užitočné používanie metódy
Path.Combine()
, ktorá berie jednotlivé časti cesty ako parametre
a vytvorí z nich jednu validný cestu k súboru či zložke. Nemusíme sa tak
zaoberať chýbajúcimi alebo Zotrvávajúcim lomítkami a podobne.
Ďalšia užitočná metóda je Environment.GetFolderPath()
,
ktorá nám vráti cestu k nejakej systémovej zložke. Výraz
Environment.SpecialFolder.ApplicationData
získa zo špeciálnych
zložiek zložku dát aplikácií. Microsoft má niekoľko špeciálnych
zložiek, ktoré môže naše aplikácie využiť na ukladanie dát potrebných
pre svoj beh, napr. Uloženej pozície v hre, a každý užívateľ počítača
má potom svoje vlastné.
A ako posledný v aplikačnej zložke vytvoríme novú zložku
robotris/
so súborom skore.xml
.
Ukladanie
Pre uloženie skóre musíme vytvoriť URL s QueryString (to je tá časť za
otáznikom), v ktorom bude prezývka a dosiahnuté body. Využijeme triedu
Hrac
az nej vytiahneme všetko potrebné. Pre formátovanie stringu
použijeme notáciu $""
. Potom použijeme už spomínanú metódu
OpenUrl()
triedy WebClient
. Celá metóda
Uloz()
bude vyzerať takto:
public void Uloz(Hrac hrac) { string url = $"{urlPridat}?prezdivka={hrac.prezdivka}&body={hrac.body}&rady={hrac.rady}&level={hrac.level}"; webKlient.OpenRead(url); }
Stiahnutie
Aby sme zo servera dostali triedu Hrac
, lepšie povedané zoznam
hráčov List<Hrac>
, je nutné najskôr získať súbor XML.
Využijeme teda metódu DownloadFile()
na WebClient. Tá požaduje
URL, kde nájde súbor a ďalej cestu, kam má súbor uložiť. Metóda
Stahni()
bude vyzerať takto:
public void Stahni() { webKlient.DownloadFile(urlVypsat, soubor); }
Načítanie
Súbor máme stiahnutý a teraz ho ešte potrebujeme deserializovat na zoznam hráčov a použiť v našej tabuľke.
Zostáva doplniť metódu Nacti()
. Metóda bude identická s
rovnomennou metódou v triede SkoreKlient
. Pre lepšiu
udržateľnosť a správu kódu by sme sa ideálne mali vyhnúť duplicite v
logike aplikácie, ale dúfam že mi to pre tentokrát prepáčite
public List<Hrac> Nacti() { string element = ""; Hrac hrac = new Hrac(); List<Hrac> hraci = new List<Hrac>(); // parsování XML using (XmlReader xr = XmlReader.Create(soubor)) { // postupné načítání uzlů while (xr.Read()) { // uzel typu element if (xr.NodeType == XmlNodeType.Element) element = xr.Name; // uložení jména elementu else if (xr.NodeType == XmlNodeType.Text) // uzel typu text { switch (element) { case "prezdivka": hrac.prezdivka = xr.Value; break; case "body": hrac.body = long.Parse(xr.Value); break; } } // konec elementu hráč else if ((xr.NodeType == XmlNodeType.EndElement) && (xr.Name == "hrac")) { hraci.Add(hrac); hrac = new Hrac(); } } } return hraci; }
To je všetko k internetovému klientovi. Teraz zostáva len vykonať zmeny k komponente pre vykreslenie skóre a máme hotovo
KomponentaSkoreTabulka
Tu pridáme nový atribút menom webKlient
, ktorý bude držať
inštanciu našej novej triedy:
private WebKlient webKlient;
Atribút nezabudneme inicializovať v metóde Initialize()
:
webKlient = new WebKlient();
Ešte pridáme nový stav do zoznamu eStav
a tým bude
ChybaWebu
. Túto chybu nebudeme považovať za fatálne a teda ak
sa vyskytne, dáme užívateľovi vedieť a spýtame sa, či bude chcieť pokus
o stiahnutie opakovať alebo nie. Ak zvolí nie, skóre zobrazíme iba formou
lokálne uložených dát. Enum eStav
teraz vyzerá takto:
private enum eStav { ChybaNacteni, ChybaUlozeni, ChybaWebu, Zapis, Vypis, Otazka, }
Nacitaj ()
Zmeníme metódu Nacti()
, v ktorej pridáme stiahnutie a
načítanie skóre zo servera a pridáme týchto hráčov medzi hráčov už
lokálne načítané:
public void Nacti() { stav = eStav.Vypis; hraci = new List<Hrac>(); try { var xmlHraci = klient.Nacti(); hraci.AddRange(xmlHraci); } catch { stav = eStav.ChybaNacteni; return; } try { webKlient.Stahni(); var webHraci = webKlient.Nacti(); hraci.AddRange(webHraci); } catch { stav = eStav.ChybaWebu; } hraci = hraci.OrderByDescending(x => x.body).ToList(); }
Najprv načítame lokálne uložené hráčov a ak sa vyskytne chyba, ukončíme vykonávanú metódu. Potom stiahneme dáta zo servera, kde opäť chytáme chybu a nakoniec hráča zoradíme podľa dosiahnutých bodov.
K využitie metódy radenia na zozname OrderByDescending()
je
nutný using using System.Linq;
.
Uloz ()
Ukladanie vykonáme pokusom o uložení na server a ak bude pokus neúspešný, tak dáta uložíme lokálne. Nechceme predsa, aby užívateľ prišiel o ťažko vydreté body
public void Uloz() { try { webKlient.Uloz(hra.hrac); Nacti(); stav = eStav.Vypis; } catch { try { klient.Uloz(hra.hrac); hraci = klient.Nacti(); stav = eStav.Vypis; } catch { stav = eStav.ChybaUlozeni; } } }
OnEnabledChanged ()
Nasleduje upravenie metódy OnEnabledChanged()
:
protected override void OnEnabledChanged(object sender, EventArgs args) { if (Enabled) { Nacti(); // Pokud budeme ve stavu chyba přeskočíme if (!(stav == eStav.ChybaNacteni || stav == eStav.ChybaUlozeni)) { // Rovnou na vypis pokud nejsou body if (hra.hrac != null && hra.hrac.body > 0) stav = eStav.Otazka; else if (stav != eStav.ChybaWebu) stav = eStav.Vypis; } } base.OnEnabledChanged(sender, args); }
Tu načítame skóre a pri chybe webu najprv zistíme, či má hráč niečo na uloženie. Pokiaľ nemá, tak ešte len nastavíme stav na výpis, pokiaľ nie je chyba webu. Týmto umožníme hráči uložiť skóre, ak nastala chyba v komunikácii so serverom.
Draw () a Update ()
A dostali sme sa k záveru, kde upravíme metódy Draw()
a
Update()
, v ktorých budeme reagovať na nami pridaný nový stav
ChybaWebu
:
V metóde Draw()
pridáme do switch
:
// vykreslení chyby webu case eStav.ChybaWebu: hra.spriteBatch.TextSeStinem(hra.fontCourierNew, $"{webKlient.ChybaNacitani} \n Zkusit znovu? [A/N]", new Vector2(510, 240), Color.Red); break;
A do metódy Update()
rovnako do switch
pridáme
ďalší prípad:
// dotaz při chybě skore na web case eStav.ChybaWebu: if (hra.NovaKlavesa(Keys.A)) Nacti(); if (hra.NovaKlavesa(Keys.N)) stav = eStav.Vypis; break;
Ak sa vyskytla chyba webu, tak ju zobrazíme. A ak užívateľ nebude chcieť akciu opakovať, vypíšeme skóre.
Php server
PHP server sme si vytvorili minule a aplikáciu s ním môžete teraz vyskúšať.
C # server
Ak ste mali problémy s PHP serverom alebo ho chcete v C #, tak sľúbený C#
server je súčasťou kódov k tejto lekcii. Po rozbalení je v priečinku
RobotrisServer/
. Aplikácia má názov
robotris_web_server/
a vytvorí server, ktorý počúva na adrese a
porte http://localhost:8000
. Obsahuje iba dve URL, ktoré sú
uloz
a stahnout
. Aplikácia vytvorí vo svojej zložke
XML súbor s uloženým skóre, ktorý funguje ako "webové" úložisko. Tento
XML je neplatne formátovaný.
- Po dotazu
uloz
server vytiahne z QueryStringu parametreprezdivka
,body
,rady
alevel
. Parameterprezdivka
je text. Zvyšné hodnoty musí byť číslo. Uloží sa do vopred spomínaného súboru. - Po otázke na
stahnout
sa obsah vopred spomínaného súboru sformátuje na platný XML a odošle. A tento súbor už v Robotrisu získavame, ukladáme a deserializujeme.
Serverové hlášky sú v angličtine. A vypisujú sa do konzoly aplikácie.
Toto je koniec bonusové lekcie o tom, ako ukladať skóre na web. Ak ste došli až som tak ďakujem za pozornosť a v nejakom ďalšom tutoriálu alebo článku dovidenia
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é 23x (13.93 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#