13. diel - MonoGame: Herné menu
V minulej lekcii, MonoGame: Správa herných obrazoviek , sme si naprogramovali správu herných
obrazoviek a pripravili komponent pre herné menu. Nič nám nebráni v tom, aby
sme sa do neho dnes pustili 
Menu budeme chcieť samozrejme pekné as nejakými efekty. Najprv si do
našej komponenty KomponentaMenu pridáme pozadia. Tu si ho
stiahnite:

a pridajte do zložky Sprity/ v hre. Pridáme príslušný
atribút:
private Texture2D pozadi;
Načítanie do LoadContent():
pozadi = hra.Content.Load<Texture2D>(@"Sprity\pozadi_menu");
A vykreslenie do Draw():
hra.spriteBatch.Begin(); hra.spriteBatch.Draw(pozadi, new Vector2(0, 0), Color.White); hra.spriteBatch.End();

Menu si rozdelíme do dvoch komponentov, aby sme ho mali znovu použiteľné
a dalo sa použiť bez veľkých zmien aj v inej hre alebo obrazovke.
KomponentaMenu sa bude starať o vykreslenie tých častí menu,
ktoré sú špecifické pre hru Robotris. Pridajme si ešte jednu univerzálnu
komponent, ktorá bude spravovať jednotlivé položky menu. Komponent bude
vykreslitelná a bude sa volať KomponentaPolozkyMenu. Opäť pre
úplnosť uvediem jej prázdny zdrojový kód (nezabudnite, že namespace má
byť opäť len Robotris, aj keď je v priečinku
Komponenty/):
namespace Robotris { public class KomponentaPolozkyMenu : Microsoft.Xna.Framework.DrawableGameComponent { private Hra hra; public KomponentaPolozkyMenu(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); } } }
Zatiaľ ju ponecháme prázdnu a pridáme ďalšiu triedu, ktorej inštancia
bude reprezentovať jednu položku menu. Triedu pridáme medzi ďalšie triedy
priamo v projekte Robotris.
Položka menu
Trieda sa bude volať PolozkaMenu. Bude obsahovať údaje o
svojej pozícii (súradniciach na obrazovke), veľkosti a textu. Veľkosti
preto, že vybranú položku budeme škálovať a to vrátane animácie. Trieda
je veľmi jednoduchá, uveďme si rovno jej zdrojový kód:
public class PolozkaMenu { public string text; public Vector2 pozice; public float velikost; public PolozkaMenu(string text, Vector2 pozice) { this.text = text; this.pozice = pozice; velikost = 0.6f; } }
Kvôli použitie štruktúry Vector2 dodáme using na XNA
framework:
using Microsoft.Xna.Framework;
Presuňme sa do KomponentaPolozkyMenu. Tento komponent bude
správca položiek menu, bude ich uchovávať, prepínať a vykresľovať.
Konkrétne udalosti (čo ktorá položka po stlačení vykoná) vložíme
neskôr do KomponentaMenu, pretože to je závislé na konkrétnej
hre.
Pridáme list položiek ako atribút, ďalej aktuálne vybratú položku a pozíciu menu:
private List<PolozkaMenu> polozky; public PolozkaMenu vybranaPolozka; private Vector2 pozice;
Komponent sa pokúsime urobiť čo najviac prispôsobiteľný, preto pridáme ešte farbu vybrané a nevybrané položky a výšku položky (tam potom uložíme výšku písma):
private Color nevybranaBarva; private Color vybranaBarva; private int vyska;
Presunieme sa do konstruktoru, ktorému pridáme ďalšie parametre a kde inicializujeme atribúty:
public KomponentaPolozkyMenu(Hra hra, Vector2 pozice, Color nevybranaBarva, Color vybranaBarva, int vyska): base(hra) { this.pozice = pozice; this.hra = hra; this.nevybranaBarva = nevybranaBarva; this.vybranaBarva = vybranaBarva; this.vyska = vyska; polozky = new List<PolozkaMenu>(); vybranaPolozka = null; }
Správa položiek menu
Pridajme niekoľko metód pre prácu s kolekciou položiek menu. Začnite pridaním nové položky. Metóda bude brať v parametri text položky. Vnútri vytvorí novú položku, tej nastaví pozíciu pod už existujúce položky v menu, podľa ich výšky. Položku následne pridá do internej kolekcie a pokiaľ nie je žiadna vybraná, vyberie práve ju (vybraná teda bude vždy 1. položka v menu). Metóda by mohla vyzerať takto:
public void PridejPolozku(string text) { // nastavení pozice podle pořadí položky Vector2 p = new Vector2(pozice.X, pozice.Y + polozky.Count * vyska); PolozkaMenu polozka = new PolozkaMenu(text, p); polozky.Add(polozka); // výběr první položky if (vybranaPolozka == null) vybranaPolozka = polozka; }
Po pridaní položiek bude treba vyberať ďalšie a predchádzajúcu položku. V metóde pre vybranie ďalšie položky nebude mimo prechodu z poslednej späť na prvú nič zaujímavé. Pretože si neudržujeme pozíciu aktuálnej položky, ale len jej inštanciu, musíme jej index vždy znovu zistiť, ale to nás v našom prípade nijako netrápi.
public void VyberDalsi() { int index = polozky.IndexOf(vybranaPolozka); if (index < polozky.Count - 1) vybranaPolozka = polozky[index + 1]; else vybranaPolozka = polozky[0]; }
Metóda pre výber predchádzajúcej položky bude podobná:
public void VyberPredchozi() { int index = polozky.IndexOf(vybranaPolozka); if (index > 0) vybranaPolozka = polozky[index - 1]; else vybranaPolozka = polozky[polozky.Count - 1]; }
Obsluha položiek
Obsluhu položiek nastavíme na klávesy nadol a nahor. Budeme tak prepínať
ďalšie a predchádzajúcu položku. Presuňme sa do Update() a
dodajme reakcii na tieto klávesy:
// reakce na klávesy if (hra.NovaKlavesa(Keys.Up)) VyberPredchozi(); if (hra.NovaKlavesa(Keys.Down)) VyberDalsi();
Vykreslenie položiek
Pretože u položiek budeme potrebovať špecifikovať aj veľkosť,
nevystačíme si s našou metódou TextSeStinem(). Preto si triedu
LepsiSpriteBatch obohatíme o ďalšiu metódu, ktorá vykreslí
škálovanie text s tieňom pomocou ďalšieho preťaženie metódy
DrawString():
public void TextSeStinemSkalovany(SpriteFont spriteFont, string text, Vector2 position, Color color, float size) { DrawString(spriteFont, text, new Vector2(position.X + 2, position.Y + 2), Color.Black * 0.8f, 0.0f, new Vector2(0, 0), size, SpriteEffects.None, 0); DrawString(spriteFont, text, position, color, 0.0f, new Vector2(0, 0), size, SpriteEffects.None, 0); }
Teraz už je pre nás hračka vykresliť v Draw() položky
menu:
hra.spriteBatch.Begin(); foreach (PolozkaMenu polozka in polozky) { Color barva = nevybranaBarva; if (polozka == vybranaPolozka) barva = vybranaBarva; hra.spriteBatch.TextSeStinemSkalovany(hra.fontBlox, polozka.text, polozka.pozice, barva, polozka.velikost); } hra.spriteBatch.End();
(Tu je závislosť na font fontBlox z hry. Ideálne by sme
mali umožniť font odovzdať, ale kvôli tomu, že font existuje až po volaní
LoadContent() by sa nám práca skomplikovala a preto toto
zanedbáme).
Vloženie komponentov do seba
Komponent KomponentaPolozkyMenu teraz vložíme do komponenty
KomponentaMenu. Takto sme do seba komponenty ešte nevkladali,
poďme si to vyskúšať. Presuňme sa do KomponentaMenu.cs, kde
pridajme atribút s inštanciou komponentmi
KomponentaPolozkyMenu:
private KomponentaPolozkyMenu polozkyMenu;
Samotnú inštanciu si však vytvoríme v Hra.cs (pretože tu
potrebujeme komponent pridať do obrazovky). Išlo by to samozrejme navrhnúť
aj inak, ale preferujte jednoduchosť. Do KomponentaMenu inštanciu
dostaneme konstruktoru, ktorý modifikujeme:
public KomponentaMenu(Hra hra, KomponentaPolozkyMenu polozkyMenu) : base(hra) { this.hra = hra; this.polozkyMenu = polozkyMenu; }
Presuňme sa do Hra.cs a v Initialize() a pridajme
vytvorenie inštancie komponenty KomponentaPolozkyMenu:
KomponentaPolozkyMenu polozkyMenu = new KomponentaPolozkyMenu(this, new Vector2(700, 250), Color.Red, Color.Yellow, 80);
A za ňou rovno pridanie njěkolika položiek do menu:
polozkyMenu.PridejPolozku("StArT"); polozkyMenu.PridejPolozku("SkOrE"); polozkyMenu.PridejPolozku("AuToRi"); polozkyMenu.PridejPolozku("KoNeC");
Striedam v názve položiek veľké a malé písmená, pretože to s fontom
Blox vyzerá dobre 
Do volanie konstruktoru KomponentaMenu doplníme inštanciu
polozkyMenu.
KomponentaMenu menu = new KomponentaMenu(this, polozkyMenu);
A rovnako tak ju dodáme aj do vytvárania obrazovky
obrazovkaMenu:
obrazovkaMenu = new HerniObrazovka(this, mraky, menu, polozkyMenu);
Otvorte si font_blox.spritefont v priečinku Fonty/
a zmeňte Style z Regular na Bold. Projekt spustíme, mali by ste dospieť
takéhoto výsledku:

Vidíme, že aj prepínanie položiek funguje dobre. Nabudúce, v lekcii MonoGame: Skrolující text (autori hry) , sprevádzkujeme klikanie na položky a vytvoríme si obrazovku autori sa skrolujícím textom.
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é 332x (13.21 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

David sa informačné technológie naučil na