Lekce 14 - MonoGame: Skrolující text (autoři hry)
V minulé lekci, MonoGame: Herní menu, jsme naprogramovali herní menu.
Dnes do něj přidáme výběr položek a naprogramujeme obrazovku Autoři se skrolujícím textem.
Výběr položky
Při stisknutí Enter se z menu nyní přesuneme vždy do levelu. Teď ale budeme při Enter reagovat na to, jaká položka byla vybrána a podle toho změníme obrazovku. Výběr obrazovky uděláme podle textu položky. Možností je samozřejmě více, ale tato je nejjednodušší, protože nemusíme nikde uchovávat instance položek. Nevýhoda je, že při změně textu položky musíme změnit i tento kód.
Přesuňme se do Update()
v KomponentaMenu
. Do
reakce na Enter vložíme switch
, který bude zatím
reagovat na položky Nová hra a Konec:
// 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": break; case "AuToRi": break; case "KoNeC": hra.Exit(); break; } }
Můžete vyzkoušet.
Obrazovka autoři
Pojďme na obrazovku autoři. Vytvoříme skrolující text, který se načte
ze souboru a bude jezdit po obrazovce. Přidejme si novou vykreslitelnou
komponentu KomponentaAutori
, již to jistě všichni zvládnete a
podrobně jsme si to popisovali již několikrát Komponentu vytvořte ve složce
Komponenty/
a namespace
ponechte na
Robotris
.
Jako proměnné budeme kromě instance hry potřebovat pozadí, samotný text, startovní pozici textu, aktuální pozici textu, výšku celého bloku textu a font. Výšku bloku potřebujeme proto, abychom mohli poznat, kdy celý text již vyjel z obrazovky a vrátit ho na startovní pozici. Bude tak jezdit stále dokola. Atributy třídy budou vypadat takto:
private Hra hra; private Texture2D pozadi; private string text; private Vector2 startovniPozice; private Vector2 pozice; private float vyskaTextu; private SpriteFont font;
Načtení textu ze souboru
K projektu si připojíme nový textový soubor, jako jsme to dělali se
souborem pro kostky (Pravým na projekt Robotris
v Solution
Exploreru -> Add -> New Item -> Text File). Soubor pojmenujeme
autori.txt
a opět mu nastavíme v Properties Copy to Output
Directory na Copy always. Do souboru si vložíme nějaký
text:
. __ /\ \ _ __ ___\ \ \____ ___ /\`'__\/ __`\ \ '__`\ / __`\ ____ \ \ \//\ \L\ \ \ \L\ \/\ \L\ \/\___\ \ \_\\ \____/\ \_,__/\ \____/\/___/ \/_/ \/___/ \/___/ \/___/ __ /\ \__ __ \ \ ,_\ _ __ /\_\ ____ \ \ \/ /\`'__\/\ \ /',__\ \ \ \_\ \ \/ \ \ \/\__, `\ \ \__\\ \_\ \ \_\/\____/ \/__/ \/_/ \/_/\/___/ Ukázková hra z programátorské sociální sítě ITnetwork.CZ Co je RoboTris? =============== Ukázková hra v MonoGame se zdrojovým kódem. Obsahuje mód z originálního tetrisu, tzn. bodování podle oficiálních pravidel, rozměry pole, tvary kostiček atd. Pokud nahraješ vysoké skóre, můžeš ho sdílet na webu s ostatními a vyzývat je, aby se tě pokusili překonat. Ovládání ======== Šipka doleva - posun kostičky doleva Šipka doprava- posun kostičky doprava Šipka nahoru a enter - rotace kostičky Šipka dolu - uzemnění kostičky Pravý CTRL - zrychlení pádu kostičky Poděkování ========== StainlessSteel - hudba na pozadí HVSC - ZeroX - píseň od neznámého autora Vzor pro obrázky kostek - hra Supaplex Licence ======= RoboTris můžete volně šířit i modifikovat, podmínkou je uvést viditelně ve hře link na www.itnetwork.cz
(Tu tečku na začátku jsem tam dal, aby místní formátovač kódů
pochopil ten ASCII ART, vy si ji vymažte ). V komponentě přidejme na
začátek
using System.IO
:
using System.IO;
A pojďme text ze souboru načíst do připravené proměnné. Udělejme si
na to metodu NactiText()
:
public void NactiText() { text = ""; using (StreamReader sr = new StreamReader("autori.txt")) { text = sr.ReadToEnd(); } }
Tu zavolejme v Initialize()
a ještě nastavme startovní pozici
kousek pod rámeček v menu, ve kterém bude text běhat. Tak bude ze začátku
celý schovaný. Aktuální pozici nastavíme také na startovní:
NactiText(); startovniPozice = new Vector2(510, 550); pozice = startovniPozice;
Načtení obsahu
S fontem máme opět problém, potřebujeme se zeptat na jeho výšku, ale
ještě není načtený. Vyřešíme to jednoduše, prostě ho v této
komponentě načteme znovu. Nebojte, MonoGame v Hra.cs
pozná, že
byl již načtený zde a pouze ho předá jako instanci. Můžeme si to tedy
dovolit bez zpomalení aplikace, to samé platí i u dalších součástí
obsahu. Zde mimo font načteme podobně i pozadí, které by teoreticky mohlo
být jiné, než u menu, i když v tomto případě není. Přesuňme se do
LoadContent a dodejme následující řádky:
pozadi = hra.Content.Load<Texture2D>(@"Sprity\pozadi_menu"); font = hra.Content.Load<SpriteFont>(@"Fonty\font_courier_new"); vyskaTextu = font.MeasureString(text).Y;
Výšku textu jsme nastavili pomocí metody MeasureString()
na
fontu, která nám vrátí přímo výšku a šířku textu v pixelech, pokud je
napsaný tímto fontem. Další možností by bylo použít vlastnost
LineSpacing
a tu vynásobit počtem řádků.
Logika
Logika v Update()
bude triviální. Návrat do menu je pouze
reakce na klávesu Escape:
if (hra.NovaKlavesa(Keys.Escape))
hra.PrepniObrazovku(hra.obrazovkaMenu);
Pohybu textu směrem nahoru dosáhneme jednoduše posunem jeho pozice. Zde se ukáže jedna z výhod vektorových souřadnic, můžeme posouvat o desetinná čísla:
pozice.Y -= 0.3F;
Zbývá snad jen zjistit, zda text vyjel z obrazovky a tehdy resetovat jeho pozici. Podiváme se, zda je jeho pozice menší, než startovní pozice snížená o výšku textu a ještě výšku oblasti, ve které text běží.
if (pozice.Y < startovniPozice.Y - (vyskaTextu + 320)) pozice = startovniPozice;
Vykreslení
V Draw()
vykreslíme pozadí a zatím celý text bez
oříznutí:
hra.spriteBatch.Begin(); hra.spriteBatch.Draw(pozadi, new Vector2(0, 0), Color.White); hra.spriteBatch.TextSeStinem(font, text, pozice, Color.Red); hra.spriteBatch.End();
To by prozatím stačilo, přesuňme se do Hra.cs
a do atributů
třídy přidejme obrazovku s autory:
public HerniObrazovka obrazovkaAutori;
V Initialize()
vytvořme komponentu:
KomponentaAutori autori = new KomponentaAutori(this);
A níže i obrazovku, zas v ní budou mraky a naše komponenta
autori
:
obrazovkaAutori = new HerniObrazovka(this, mraky, autori);
V KomponetaMenu
doplníme v Update()
do
switch
přepnutí obrazovky:
case "AuToRi": hra.PrepniObrazovku(hra.obrazovkaAutori); break;
Spustíme.
![Ukázkový Tetris v XNA Game Studio - Od nuly k tetrisu v MonoGame](images/5/xna/robotris_17.jpg)
Až na to, že by se text měl oříznout, je výsledek dobrý.
Oříznutí vykreslování v MonoGame (clipping)
Oříznutí dosáhneme pomocí tzv. "nůžek". V Draw()
metodě
komponenty KomponentaAutori
vyjmeme vykreslení textu a vložíme
ho do dalšího vykreslovacího bloku, tentokrát s jiným přetížením metody
Begin()
. Nejprve uvedu kód, který vysvětlím. Metodu
Draw()
si pozměňte takto:
public override void Draw(GameTime gameTime) { // vykreslení pozadí hra.spriteBatch.Begin(); hra.spriteBatch.Draw(pozadi, new Vector2(0, 0), Color.White); hra.spriteBatch.End(); // vyklreslení skrolujícího textu pomocí clippingu (nůžek): // zapnutí clippingu RasterizerState rs = new RasterizerState(); rs.ScissorTestEnable = true; hra.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, rs); // uložení současných nůžek Rectangle currentRect = hra.spriteBatch.GraphicsDevice.ScissorRectangle; // nastavení nůžek hra.spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(488, 240, 570, 335); // vykreslení textu hra.spriteBatch.TextSeStinem(font, text, pozice, Color.Red); // reset původních nůžek hra.spriteBatch.GraphicsDevice.ScissorRectangle = currentRect; hra.spriteBatch.End(); base.Draw(gameTime); }
Pomocí RasterizerState
zapneme nůžky. Toto nastavení poté
předáme metodě Begin()
. Uložíme si současné nůžky
(nastavené na celou obrazovku) a poté nastavíme nůžky vlastní, nastavené
na obdélník, kde má text skrolovat. Vykreslíme text a nůžky vrátíme
zpět. Výsledný efekt:
![Ukázkový Tetris v XNA Game Studio - Od nuly k tetrisu v MonoGame](images/5/xna/robotris_18.jpg)
K dokonalosti bychom mohli výtvor dovést tak, že bychom si uložili obdélníky horního a spodního okraje pole, ve kterém text jede. Ty v grafickém editoru postupně zprůhlednili a vykreslili přes text. Text by se poté takto neusekával, ale postupně mizel. Můžete si doplnit. Některé věci v menu ještě necháme rozdělané.
Příště, v lekci Hra tetris v MonoGame: Skóre, půjdeme na on-line skóre tabulku.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 583x (13.22 MB)
Aplikace je včetně zdrojových kódů v jazyce C#