NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.

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

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

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 586x (13.22 MB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
MonoGame: Herní menu
Všechny články v sekci
Od nuly k tetrisu v MonoGame
Přeskočit článek
(nedoporučujeme)
Hra tetris v MonoGame: Skóre
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
7 hlasů
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 se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity