5. diel - 3D bludisko v XNA - Dokončenie editoru máp
V tutoriále 3D bludisko v XNA - Editor máp sme načal tvorbu editora 3D bludisko. Dnes editor dokončíme a sprevádzkujeme. Ako prvý dokončí našu triedu Mapa, v ktorej nám chýba implementovať jej vykreslenie.
Vykreslenie mapy
Metóda k vykreslenie mapy bude teda tiež v triede Mapa.cs. V parametri metódy si odovzdáme Graphics, na ktorý sa má kresliť. Rovnako tak si odovzdáme aj veľkosť hrany políčka. Rôzne hodnoty nám umožní vykresľovať zväčšenou či zmenšenú mapu. Keďže nie sme žiadni začiatočníci, ukážme si opäť kód metódy a vzápätí si ho popíšme.
public void Vykresli(Graphics g, int hrana) { // mřížka for (int j = 0; j <= Vyska; j++) { for (int i = 0; i <= Sirka; i++) { g.DrawLine(Pens.Gray, new Point(0, j * hrana), new Point(Sirka * hrana - 1, j * hrana)); // - g.DrawLine(Pens.Gray, new Point(i * hrana, 0), new Point(i * hrana, Vyska * hrana - 1)); // | } } // Políčka for (int j = 0; j < Vyska; j++) { for (int i = 0; i < Sirka; i++) { switch (policka[i, j]) { // Zeď case 1: g.FillRectangle(Brushes.CornflowerBlue, i * hrana, j * hrana, hrana, hrana); break; // Start case 99: g.FillEllipse(Brushes.GreenYellow, i * hrana, j * hrana, hrana, hrana); g.DrawString("S", new Font("Arial", hrana / 2), Brushes.Green, i * hrana + (hrana / 6), j * hrana + (hrana / 6)); break; // Cíl case 100: g.FillEllipse(Brushes.Purple, i * hrana, j * hrana, hrana, hrana); g.DrawString("C", new Font("Arial", hrana / 2), Brushes.Red, i * hrana + (hrana / 6), j * hrana + (hrana / 6)); break; } } } }
Prvé 2 cykly vykreslí na daný Graphics štvorcovú sieť, aby sa nám mapa lepšie designovala. Prvý kreslí vodorovné čiary, druhý zvislé. Tu asi nie je čo vysvetľovať.
Obdobne vykresľuje v ďalších 2 cykloch aj políčka. Typ políčka rozlíšime switchom, múr je vykreslená ako štvorec, políčka štart a cieľ ako farebná kolieska s nápismi S a C. Súradnice nápisu na políčkach i veľkosť nápisu sú pronásobeny veľkostí hrany, aby pri zoomovaní mapy zostal text približne rovnako veľký a na rovnakej pozícii.
Triedu Mapa môžeme vyhlásiť za hotovú.
Vizuálnu časť
Logika je hotová, sprevádzkuje vizuálnu časť editora, teda tú formulárové.
Ako prvý si do triedy FormEditor pridajme premennú mapa, kde budeme mať uloženú inštanciu mapy, s ktorou v editore aktuálne pracujeme:
Mapa mapa;
Do konstruktoru formulára pridajme vytvorenie novej inštancie mapy veľkosti 16x16. Ak editor spustíme, bude v ňom teda pripravená táto prázdna mapa:
mapa = new Mapa(16, 16);
Vyberieme v dizajne mapaPictureBox a naklikne mu udalosť Paint (). V tej jednoducho zavoláme vykreslenie mapy, kde v parametroch odovzdáme Graphics PictureBox a šírku hrany z hranaNumericUpDown.
mapa.Vykresli(e.Graphics, Convert.ToInt32(hranaNumericUpDown.Value));
Môžeme spustiť:
Vidíme vykreslenú prázdnu mapu, teda mriežku 16x16. PictureBox však nie je natiahnutý na veľkosť, ktorú by mal mať. Tú môžeme jednoducho spočítať, poďme pridať do formu metódu, ktorú budeme mapu obnovovať. Tá okrem prekreslenie mapy ešte zmení veľkosť PictureBox. Pridajme do FormEditor.cs metódu metódu PrekresliMapu ():
private void prekresliMapu() { mapaPictureBox.Size = new Size(mapa.Sirka * Convert.ToInt32(hranaNumericUpDown.Value) + 1, mapa.Vyska * Convert.ToInt32(hranaNumericUpDown.Value) + 1); mapaPictureBox.Refresh(); }
Veľkosť mapy jednoducho spočítame podľa rozmerov mapy a veľkosti hrany vykreslovaného políčka. Formulári pridáme udalosť Load a v nej prekreslíme mapu:
prekresliMapu();
PictureBox sa nám krásne roztiahol a ak je form menšia, zobrazí sa pri paneli posuvníky a môžeme mapou skrolovať. To sme presne chceli. Do udalosti Load pripíšte výber predvoleného políčka v typPolickaComboBox:
typPolickaComboBox.SelectedIndex = 0;
hraNumericUpDown naklikne udalosť ValueChanged a v nej prekreslíme mapu:
prekresliMapu();
Teraz naklikne na mapaPictureBox udalosť mouseclick. Do nej umiestnime nasledujúci kód:
int hrana = Convert.ToInt32(hranaNumericUpDown.Value); int x = e.X / hrana; int y = e.Y / hrana; // Hodnoty v pořadí, jako jsou popisky políček v ComboBoxu int[] hodnoty = {1, 99, 100, 0}; // Kontrola správnosti souřadnic if ((x >= 0) && (y >= 0) && (x < mapa.Sirka) && (y < mapa.Vyska)) { // Levé myšítko přidá zeď if (e.Button == MouseButtons.Left) mapa.policka[x, y] = hodnoty[typPolickaComboBox.SelectedIndex]; // Pravé myšítko vymaže zeď if (e.Button == MouseButtons.Right) mapa.policka[x, y] = 0; prekresliMapu(); }
Najprv si zistíme zo súradníc myši políčko na mape, na ktoré sa kliklo. To je jednoduché, stačí ich len vydeliť veľkosťou políčka. Ďalej si pripravíme pole hodnôt, ktoré bude predstavovať hodnoty pre jednotlivé políčka v typPolickaComboBox. Je dôležité, aby hodnoty mali to isté poradí, ako majú itemy v ComboBox. Vidíme, že múr má hodnotu 1, štart 99, cieľ 100 a prázdno 0. Vypočítané súradnice treba otestovať, pretože užívateľ mohol kliknúť mimo mapu a siahali by sme tak za hranice poľa. Teraz len otestujeme, ktoré tlačidlo bolo stlačené. Ak ľavej, vložíme na vhodnej políčko na mape hodnotu podľa vybraného item v ComboBox. Ak bolo stlačené pravé tlačidlo, vložíme prázdne políčko (pravým tlačidlom teda natierame). Nakoniec mapu prekreslíme a máme hotovo. Mouseclick sme použili z dôvodu možnosti odlíšenie tlačidiel narozdiel od udalosti Click.
Môžete vyskúšať. Bolo by skvelé, keby sme mohli na mapu pokladať políčka aj ťahaním myši, nielen klikaním. Stačí len, keď metódu mapaPictureBox_MouseClick () vyberieme aj u udalosti MouseMove. Teraz sa mapa vytvára naozaj jednoducho:
Vytvorenie novej mapy
Prejdime k formuláru pre vytvorenie novej mapy. Do jeho triedy si pridáme verejný atribút s inštanciou mapy.
public Mapa mapa;
Pri kliknutí na tlačidlo "Vytvoriť" do atribútu vytvoríme novú inštanciu mapy požadovanej veľkosti a formulár zatvoríme:
mapa = new Mapa(Convert.ToInt32(sirkaUpDown.Value), Convert.ToInt32(vyskaUpDown.Value));
Close();
Formu naklikne udalosť Shown, kde vždy nastavíme túto inštanciu na null:
mapa = null;
Pri každom zobrazení dialógu sa nám teda mapa vymaže. Vďaka tomu spoznáme, či sme formulár opustili kliknutím na tlačidlo "Vytvoriť" (v mape je inštancia mapy) alebo len zavreli krížikom (v mape je null).
Vytvorenie formu a následné vytvorenie mapy nakoniec naklikne do položky Nová v MenuStrip:
FormNovaMapa formNovaMapa = new FormNovaMapa(); formNovaMapa.ShowDialog(); if (formNovaMapa.mapa != null) { mapa = formNovaMapa.mapa; prekresliMapu(); }
Môžete si skúsiť založiť novú mapu.
Ukladanie a načítanie
Dokončenie editora vrcholí. Pridajme si z Toolbox dialógy pre otvorenie a uloženie súboru. Najprv pridajme SaveFileDialog pomenovaný mapaSaveFileDialog. Nastavíme mu DefaultExt (predvolené príponu) na máp. To bude prípona našich súborov s mapou. Ďalej nastavíme Filter na:
Mapy (*.map)|*.map
Rovnako pridáme aj nastavíme mapaOpenFileDialog. U neho ešte vymažeme vlastnosť FileName (necháme prázdnu hodnotu).
V MenuStrip rozkliknite položku Otvoriť a vložíme logiku pre zobrazenie dialógu a načítanie mapy:
if (mapaOpenFileDialog.ShowDialog() == DialogResult.OK)
{
mapa.Nacti(mapaOpenFileDialog.FileName);
prekresliMapu();
}
Obdebně to urobíme aj u položky Uložiť:
if (mapaSaveFileDialog.ShowDialog() == DialogResult.OK)
{
mapa.Uloz(mapaSaveFileDialog.FileName);
prekresliMapu();
}
Ako symbolickú čerešničku na torte pridáme vyvolanie MessageBox pri kliknutí na položku "O programe":
MessageBox.Show("Editor k tutoriálu na 3D bludiště v C# XNA z programátorské sociální sítě www.itnetwork.cz");
Editor levelov pre bludisko je hotový Za domácu úlohu si môžete obmedziť, aby šlo vložiť iba jedno štartové a cieľové pole, aj keď táto ochrana nie je nevyhnutne potrebné. Nabudúce si s somárikom načítate vašou krásnu mapu do enginu a môžete sa v nej prejsť.
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é 193x (70.49 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#