5. díl - 3D bludiště v XNA - Dokončení editoru map

C# .NET XNA game studio 3D bludiště 3D bludiště v XNA - Dokončení editoru map

V tutoriálu 3D bludiště v XNA - Editor map jsme načali tvorbu editoru 3D bludiště. Dnes editor dokončíme a zprovozníme. Jako první dokončeme naši třídu Mapa, ve které nám chybí implementovat její vykreslení.

Vykreslení mapy

Metoda k vykreslení mapy bude tedy také ve třídě Mapa.cs. V parametru metody si předáme Graphics, na který se má kreslit. Stejně tak si předáme i velikost hrany políčka. Různé hodnoty nám umožní vykreslovat zvětšenou či zmenšenou mapu. Jelikož nejsme žádní začátečníci, ukažme si opět kód metody a záhy si jej popiš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;
                        }
                }
        }
}

První 2 cykly vykreslí na daný Graphics čtvercovou síť, aby se nám mapa lépe designovala. První kreslí vodorovné čáry, druhý svislé. Zde asi není co vysvětlovat.

Obdobně vykreslujeme v dalších 2 cyklech i políčka. Typ políčka rozlišíme switchem, zeď je vykreslena jako čtverec, políčka start a cíl jako barevná kolečka s nápisy S a C. Souřadnice nápisu na políčkách i velikost nápisu jsou pronásobeny velikostí hrany, aby při zoomování mapy zůstal text přibližně stejně velký a na stejné pozici.

Třídu Mapa můžeme prohlásit za hotovou.

Vizuální část

Logika je hotová, zprovozněme vizuální část editoru, tedy tu formulářovou.

Jako první si do třídy FormEditor přidejme proměnnou mapa, kde budeme mít uloženou instanci mapy, se kterou v editoru aktuálně pracujeme:

Mapa mapa;

Do konstruktoru formuláře přidejme vytvoření nové instance mapy velikosti 16x16. Pokud editor spustíme, bude v něm tedy připravena tato prázdná mapa:

mapa = new Mapa(16, 16);

Vybereme v designu mapaPictureBox a naklikneme mu událost Paint(). V té jednoduše zavoláme vykreslení mapy, kde v parametrech předáme Graphics PictureBoxu a šířku hrany z hranaNumericUpDown.

mapa.Vykresli(e.Graphics, Convert.ToInt32(hranaNumericUpDown.Value));

Můžeme spustit:

Editor levelů bludiště v C# .NET

Vidíme vykreslenou prázdnou mapu, tedy mřížku 16x16. PictureBox však není roztáhnutý na velikost, kterou by měl mít. Tu můžeme jednoduše spočítat, pojďme přidat do formu metodu, kterou budeme mapu obnovovat. Ta kromě překreslení mapy ještě změní velikost PictureBoxu. Přidejme do FormEditor.cs metodu metodu PrekresliMapu():

private void prekresliMapu()
{
        mapaPictureBox.Size = new Size(mapa.Sirka * Convert.ToInt32(hranaNumericUpDown.Value) + 1, mapa.Vyska * Convert.ToInt32(hranaNumericUpDown.Value) + 1);
        mapaPictureBox.Refresh();
}

Velikost mapy jednoduše spočítáme podle rozměrů mapy a velikosti hrany vykreslovaného políčka. Formuláři přidáme událost Load a v ní překreslíme mapu:

prekresliMapu();
Editor levelů bludiště v C# .NET

PictureBox se nám krásně roztáhl a pokud je form menší, zobrazí se u panelu posuvníky a můžeme mapou skrolovat. To jsme přesně chtěli. Do události Load připišme výběr výchozího políčka v typPolickaComboBox:

typPolickaComboBox.SelectedIndex = 0;

hraNumericUpDown naklikneme událost ValueChanged a v ní překreslíme mapu:

prekresliMapu();

Nyní naklikneme na mapaPictureBox událost MouseClick. Do ní umístíme následující 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();
}

Prvně si zjistíme ze souřadnic myši políčko na mapě, na které se kliklo. To je jednoduché, stačí je jen vydělit velikostí políčka. Dále si připravíme pole hodnot, které bude představovat hodnoty pro jednotlivá políčka v typPolickaComboBox. Je důležité, aby hodnoty měly to samé pořadí, jako mají itemy v ComboBoxu. Vidíme, že zeď má hodnotu 1, start 99, cíl 100 a prázdno 0. Vypočítané souřadnice je nutno otestovat, jelikož uživatel mohl kliknout mimo mapu a sahali bychom tak za hranice pole. Nyní pouze otestujeme, které tlačítko bylo stisknuté. Pokud levé, vložíme na příslušené políčko na mapě hodnotu dle vybraného itemu v ComboBoxu. Pokud bylo stisknuto pravé tlačítko, vložíme prázdné políčko (pravým tlačítkem tedy mažeme). Nakonec mapu překreslíme a máme hotovo. MouseClick jsme použili z důvodu možnosti odlišení tlačítek narozdíl od události Click.

Můžete vyzkoušet. Bylo by skvělé, kdybychom mohli na mapu pokládat políčka i tažením myši, nejen klikáním. Stačí pouze, když metodu mapaPictureBox_Mou­seClick() vybereme i u události MouseMove. Nyní se mapa vytváří opravdu jednoduše:

Editor levelů bludiště v C# .NET

Vytvoření nové mapy

Přejděme k formuláři pro vytvoření nové mapy. Do jeho třídy si přidáme veřejný atribut s instancí mapy.

public Mapa mapa;

Při kliknutí na tlačítko "Vytvořit" do atributu vytvoříme novou instanci mapy požadované velikosti a formulář zavřeme:

mapa = new Mapa(Convert.ToInt32(sirkaUpDown.Value), Convert.ToInt32(vyskaUpDown.Value));
Close();

Formu naklikneme událost Shown, kde vždy nastavíme tuto instanci na null:

mapa = null;

Při každém zobrazení dialogu se nám tedy mapa vymaže. Díky tomu poznáme, zda jsme formulář opustili kliknutím na tlačítko "Vytvořit" (v mapě je instance mapy) nebo jen zavřeli křížkem (v mapě je null).

Vytvoření formu a následné vytvoření mapy nakonec naklikneme do položky Nová v MenuStrip:

FormNovaMapa formNovaMapa = new FormNovaMapa();
formNovaMapa.ShowDialog();
if (formNovaMapa.mapa != null)
{
        mapa = formNovaMapa.mapa;
        prekresliMapu();
}

Můžete si zkusit založit novou mapu.

Ukládání a načítání

Dokončení editoru vrcholí. Přidejme si z Toolboxu dialogy pro otevření a uložení souboru. Nejprve přidejme SaveFileDialog pojmenovaný mapaSaveFileDialog. Nastavíme mu DefaultExt (výchozí příponu) na map. To bude přípona našich souborů s mapou. Dále nastavíme Filter na:

Mapy (*.map)|*.map

Stejně přidáme i nastavíme mapaOpenFileDialog. U něj ještě vymažeme vlastnost FileName (necháme prázdnou hodnotu).

V MenuStrip rozklikneme položku Otevřít a vložíme logiku pro zobrazení dialogu a načtení mapy:

if (mapaOpenFileDialog.ShowDialog() == DialogResult.OK)
{
        mapa.Nacti(mapaOpenFileDialog.FileName);
        prekresliMapu();
}

Obdebně to uděláme i u položky Uložit:

if (mapaSaveFileDialog.ShowDialog() == DialogResult.OK)
{
        mapa.Uloz(mapaSaveFileDialog.FileName);
        prekresliMapu();
}

Jako symbolickou třešinku na dortu přidáme vyvolání MessageBoxu při kliknutí na položku "O programu":

MessageBox.Show("Editor k tutoriálu na 3D bludiště v C# XNA z programátorské sociální sítě www.devbook.cz");

Editor levelů pro bludiště je hotový :) Za domácí úkol si můžete omezit, aby šlo vložit pouze jedno startovní a cílové pole, i když tato ochrana není nutně potřeba. Příště si s oslíkem načtete vaší krásnou mapu do enginu a můžete se v ní projít.


 

Stáhnout

Staženo 185x (70.49 kB)
Aplikace je včetně zdrojových kódů v jazyce C# XNA

 

  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 (1 hlasů) :
55555


 


Miniatura
Všechny články v sekci
3D bludiště v XNA

 

 

Komentáře

Avatar
Pleto
Redaktor
Avatar
Pleto:

Super tutoriál, len mi trochu kole oči konštrukcia

// 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)); // |
               }
       }

nebolo by lepšie to spraviť cez dva jednoduché cykly ako cez jeden vnorený? Už pri rozmeroch 10x10 je to rozdiel 20 : 100 iterácií, ...

 
Odpovědět 25.1.2013 23:50
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 1 zpráv z 1.