12. díl - XNA: Správa herních obrazovek

C# .NET XNA game studio Robotris XNA: Správa herních obrazovek

V minulém dílu seriálu XNA tutoriálů jsme do levelu s Tetrisem přidali vylepšenou rotaci a zaměřovač. Tím pro nás Tetrisování končí a budeme hru považovat za hotovou. Vy si tam samozřejmě můžete dodat další power-upy, herní módy a podobně. Dnes se zaměříme na herní obrazovky, díky kterým budeme poté schopni vytvořit např. herní menu.

Herní obrazovka

Víme, že XNA není engine, ale framework. Proto XNA samotné kromě komponent neposkytuje žádný způsob, jak se vypořádat s přepínáním herních obrazovek. Herní obrazovkou myslím nějakou samostatnou část hry, třeba level, menu, skóre tabulku, obrazovku autoři a podobně. Hlavní menu bude mít určitě jinou logiku, než level s Tetrisem. Navíc je třeba docílit toho, abychom herní obrazovky mohli přepínat a ukládat jejich stav.

Možností je samozřejmě mnoho. Úplně ta nejhloupější je napsat celou hru do jednoho souboru a udělat mnoho stavů (stav pro menu, stav pro hru a tak). Výsledný soubor by ale asi nevypadal úplně hezky a když umíme používat herní komponenty, určitě je využijeme. Občas jsem viděl způsob, kdy je co obrazovka, to komponenta. Komponenty se poté mezi sebou přepínají (např. z komponenty Menu do komponenty Level). Pro malé hry to může být dostačující, ale pro větší projekty již nikoli. Problém je v tom, že jsme omezeni na 1 komponentu pro každou obrazovku, nemohli bychom mít např. v tetrisu oddělené Mraky a Level, případně ještě nějaké další součásti, které by se ve složitější hře našly.

Řešení, které si zde ukážeme, definuje herní obrazovku jako soubor komponent. Do hry jsou vloženy všechny komponenty a při přepnutí obrazovky se zakáží a povolí se jen ty, které používá konkrétní obrazovka.

Přidejme si k projektu třídu HerniObrazovka.cs. Její instance budou reprezentovat jednotlivé herní obrazovky. Třídu si nastavte jako public. Bude mít 2 privátní atributy, jeden bude kolekce komponent, které obrazovka obsahuje. Druhý instance Hry:

private List<GameComponent> komponenty;
private Hra hra;

Kvůli použití typu GameComponent dodáme nad třídu using:

using Microsoft.Xna.Framework;

Přidáme veřejnou metodu PridejKomponentu(), která komponentu předanou v parametru vloží do interní kolekce obrazovky a zároveň i do kolekce Components hry. Do Components se musí komponenta vložit pouze tehdy, když tam již není. Některé obrazovky totiž využívají stejné komponenty. Metoda vypadá takto:

public void PridejKomponentu(GameComponent komponenta)
{
        komponenty.Add(komponenta);
        if (!hra.Components.Contains(komponenta))
                hra.Components.Add(komponenta);
}

Díky tomu, že je list privátní, všechna přidání proběhnou přes tuto metodu a můžeme si být jistí, že budou dané komponenty i v Components hry.

V konstruktoru třídy si předáme v parametru instanci hry tak, jak jsme zvyklí z komponent a herních objektů. Dále pomocí klíčového slova params umožníme vložit několik parametrů typu GameComponent. Ty proiterujeme a přidáme pomocí naší metody.

public HerniObrazovka(Hra hra, params GameComponent[] komponenty)
{
        this.hra = hra;
        this.komponenty = new List<GameComponent>();
        foreach (GameComponent komponenta in komponenty)
        {
                PridejKomponentu(komponenta);
        }
}

Jako poslední přidáme metodu VratKomponenty(), která vrátí komponenty v obrazovce jako pole:

public GameComponent[] VratKomponenty()
{
        return komponenty.ToArray();
}

Pro úplnost si můžete napsat metodu pro vymazání komponenty, v nějaké složitější hře by se mohly za běhu přidávat a odebírat, ale pro naše účely to není nutné.

Menu

Abychom měli na čem testovat, přidáme si ke hře komponentu KomponentaMenu (do složky Komponenty, ale namespace ponechte pouze na Robotris). Bude se opět jednat o DrawableComponent, jak ji přidat jsme si ukázali v tutoriálu Rozdělení XNA hry do komponent. Pro jistotu si ukážeme i kód třídy:

public class KomponentaMenu : Microsoft.Xna.Framework.DrawableGameComponent
{

        private Hra hra;

        public KomponentaMenu(Hra hra)
                : base(hra)
        {
                this.hra = hra;
        }

        public override void Initialize()
        {
                base.Initialize();
        }

        protected override void LoadContent()
        {
                base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
                base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
                base.Draw(gameTime);
        }
}

Komponentu zatím ponecháme prázdnou.

Obsluha herních obrazovek

Samotnou obsluhu herních obrazovek vložíme do třídy Hra.cs. Docela mi to dává smysl a je jednoduše viditelná ze všech komponent. Další možnost by byla vytvořit nějaký manažer obrazovek.

Přesuneme se do Hra.cs, kde do atributů třídy přidáme 2 veřejné herní obrazovky, budou to obrazovky pro menu a pro level:

public HerniObrazovka obrazovkaMenu, obrazovkaLevel;

Do Initialize() přidáme k vytvoření komponent i vytvoření komponenty menu:

KomponentaMenu menu = new KomponentaMenu(this);

Připojení komponent ke hře do kolekce Components úplně odstraníme, protože to za nás dělá herní obrazovka. Namísto toho si vytvoříme herní obrazovky:

obrazovkaMenu = new HerniObrazovka(this, mraky, menu);
obrazovkaLevel = new HerniObrazovka(this, mraky, level);

Vidíme, že můžeme použít tu samou komponentu Mraky ve více obrazovkách.

Přidáme privátní metodu k přepnutí stavu obrazovky. Jako parametr bude brát komponentu a stav (zapnuto/vypnuto). GameComponent v XNA má vlastnost Enabled, která umožňuje zapínat/vypínat vykonávání metody Update(). Pokud ho vypneme, komponenta se zastaví. Pokud je komponenta ještě typu DrawableGameCom­ponent (což téměř vždy bude), nastavíme i vlastnost Visible. Ta udává, jestli se má vykonávat metoda Draw() a tedy jestli se má komponta vykreslovat.

private void PrepniKomponentu(GameComponent komponenta, bool zapnout)
{
        komponenta.Enabled = zapnout;
        if (komponenta is DrawableGameComponent)
                ((DrawableGameComponent)komponenta).Visible = zapnout;
}

Když takto komponentu vypneme, nebude se vykreslovat ani obsluhovat. Stále však existuje a když ji poté zapneme, bude přesně ve stavu, v jakém jsme ji nechali. To se nám někdy může hodit (např. přechod mezi různými lokacemi, minihrami, z menu do hry atd.).

Vrátíme se do Initialize(), po vytvoření obrazovek proiterujeme všechny komponenty hry a vypneme je:

foreach (GameComponent komponenta in Components)
{
        PrepniKomponentu(komponenta, false);
}

Nakonec přidáme samotnou metodu k přepnutí obrazovky. Bude veřejná a jako parametr bude brát obrazovku, do které se chceme přepnout.

public void PrepniObrazovku(HerniObrazovka obrazovka)
{
}

Nejprve si z obrazovky vyžádáme komponenty, které obsahuje:

GameComponent[] povolene = obrazovka.VratKomponenty();

Proiterujeme komponenty hry a zjistíme, jestli je daná komponenta povolená. To uděláme tak, že se ji pokusíme vyhledat v poli povolených komponent. Nakonec komponentu nastavíme na požadovaný stav.

foreach (GameComponent komponenta in Components)
{
        bool povolena = povolene.Contains(komponenta);
        PrepniKomponentu(komponenta, povolena);
}

V metodě ještě updatujeme minulý stav kláves, protože přepnutí komponent má za následek jeho vynechání:

klavesyMinule = klavesy;

Na konec metody LoadContent() přidáme přepnutí obrazovky (nastane až ve chvíli, kdy bude vše načteno):

PrepniObrazovku(obrazovkaMenu);

Když hru nyní spustíme, měli bychom vidět menu, které je představováno zatím jen mraky.

Ukázkový Tetris v XNA Game Studio

Přesuneme se do KomponentaMenu a přidáme do Update() reakci na enter, která nás přesune do hry:

if (hra.NovaKlavesa(Keys.Enter))
                hra.PrepniObrazovku(hra.obrazovkaLevel);

Vyzkoušíme a vidíme, že jsme naprogramovali přepínání obrazovek. Příště se zaměříme na menu :)


 

Stáhnout

Staženo 253x (5.93 MB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (2 hlasů) :
55555


 


Miniatura
Všechny články v sekci
Od nuly k tetrisu v XNA game studio
Miniatura
Následující článek
XNA: Herní menu

 

 

Komentáře

Avatar
lukas
Neregistrovaný
Avatar
lukas:

Ahoj, můžeš prosím opravit download (Stáhnout XNA: Správa herních obrazovek v 1.0), momentálně je tam nalinkovaný pouze obrázek té plochy nikoliv archiv s programem. Díky

 
Odpovědět 13.10.2012 20:14
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na lukas
David Čápka:

Díky, opraveno, jsem se uklikl :) Zrovna píšu 14. díl 8-)

Odpovědět 13.10.2012 20:16
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
lukas
Neregistrovaný
Avatar
Odpovídá na David Čápka
lukas:

Super, 14. bude věnovaná menu?

 
Odpovědět 14.10.2012 14:53
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na lukas
David Čápka:

Jo, dělat se bude menu. Na něčem jsem se tam zasekl, snad to dnes publikuji, každopádně to bude již brzo :)

Odpovědět 14.10.2012 14:55
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
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.

Zobrazeno 4 zpráv z 4.