4. diel - 3D bludisko v XNA - Mapy, múry a podlaha
Vitajte po pätnástej. Iste ste si všimli predchádzajúceho článku od zmijozeláka. Editor pre naše bludisko bude veľmi potrebné, zrýchli tvorbu nových levelov. My sa ale nebudeme zaoberať v tomto článku pokračovaním v editore, ale pohneme sa hrou. Vytvoríme si komponentu s mapou a tiež komponenty pre múry a podlahy. Pokúsime sa tiež načítať súbor s mapou. Je to veľa práce, tak sa do toho hneď pustíme.
Múr
Prvý bude potreba komponent pre múry. Nebude to nič zázračného, celý
kód je veľmi veľmi krátky. Vytvoríme si teda zložku pre komponenty v
našej hre. Tu si vytvoríme novú triedu, pomenujte si ju treba
Zed
. Urobíme ju verejnú, upravíme menný priestor. Budeme dediť
od triedy Model3D, ktorá sa nám modelmi reprezentuje. Do obsahu hry pridáme
model podlaha, ktorý budeme používať. Vytvoríme si konštruktor:
public Zed(int x, int z): base(new Vector3(x*20+10,0,z*20+10),Matrix.Identity,new Vector3(1.34f),"zed"){ }
Ako parameter odovzdávame súradnice xayv poli s bludiskom, ktoré potom prepočítame na skutočné vo svete. Rotácia nechceme žiadne, mierka som pokusne stanovil na 1.34x, aj keď som v Číne 4D nastavil veľkosť na presne 100, tak sú tu veľkosti iné. Múr je zatiaľ hotová. Veci pre kolízie pridáme nabudúce.
Podlaha
Ďalšie komponenta pre priechodná podlahy, opäť vytvoríme triedu rovnako
ako minule, urobíme ju verejnú, dedíme od Model3D
a zase
vytvoríme konštruktor:
public Podlaha(int x, int z): base(new Vector3(x*20+10,0,z*20+10),Matrix.Identity,new Vector3(1.34f),"podlaha"){ }
Všetko je prakticky rovnaké ako pri stene. Len sa zmenilo meno modelu. Iste vás zaujal podivný výpočet polohy. Bude sa hodiť neskôr. O tom, ako tento vzorček funguje, sa zmienim baňou, ak na to nezabudnem.
Mapa
Tretí komponent, s ktorou budeme pracovať, je mapa. Mapa v sebe bude mať uložené všetky steny a podlahy, bude ich pridávať do herného okna a opäť zase odoberať. Skrátka bude mať na starosti podobu bludisko. Ako už zmijozelák naznačil vo svojom článku, mapa levelu bludisko je uložená vo dvojrozmernom poli celých čísel. Každé číslo bude reprezentovať jeden typ políčka. V nasledujúcej tabuľke je súhrn:
0 | voľno |
1 | múr |
99 | štartové pole |
100 | cieľové pole |
Opäť si založíme súbor s triedou Mapa v priečinku pre komponenty.
Opäť dedíme od triedy Component
. Vytvoríme si zoznam, v ktorom
budeme uchovávať nami pridané komponenty:
private List<Component> Komponenty;
V konstruktoru ho vytvoríme:
public Mapa(){ Komponenty = new List<Component>(); }
Vytvoríme si metódu Nacti
, kde budeme preberať bludisko zo
súboru. Ako parameter metódy odovzdáme cestu k súboru. Ale keďže sme
programátori a sme leniví písať niečo čo už sme napísali znovu, tak sa
pozrieme do zmijozelákova článku, nájdeme rovnako pomenovanú metódu,
nakopírujeme si ju a celkom ju promázneme. Asi tak ako som to urobil ja:
public void Nacti(string cesta){ string[] radky = File.ReadAllLines(cesta); for (int j = 0; j < radky.Length; j++){ // rozbití řádku podle separátoru string[] radek = radky[j].Split(','); // naparsování hodnot v řádku for (int i = 0; i < radek.Length; i++){ int typ = int.Parse(radek[i]); } } }
Prakticky zmizlo všetko s ukladaním do poľa a tiež si proparsovaný
výsledok ukladáme do premennej. Nie je to úplne bezpečný spôsob, čo keď
sa nám tam dostane nejaký znak namiesto číslica? Tak nám aplikácie
pochopiteľne spadne, to ošetríme zmenou metódy z Parse
na
TryParse
:
int typ=-1; int.TryParse(radek[i],out typ);
Ako to celé inak funguje sa dočítate v predchádzajúcom článku. Nám už len zostáva pridať príslušnú komponent na dané miesto, to sa bude robiť veľmi ľahko, použijeme switch, hoci by som tam najradšej napchal stromček if-else, ale pre výukové potreby sa obetujem:
Component c=null; switch (typ){ case 0:{ c=new Podlaha(i, j); break; } case 1:{ c=new Zed(i, j); break; } }
A ak bude premenná c
rozdielna od null
, tak ju
pridáme do nášho zoznamu a zároveň aj do herného okna:
if (c != null){ Parent.AddComponent(c); Komponenty.Add(c); }
Tu je vidieť mierna nedomyšlenost enginu ako takého. Bolo by vhodnejšie a
lepšie, keby mohla mapa sama riadiť vykresľovanie súčasťou bludisko. Sama
si ich spravovať, pridávať a mazať aby musela komponenty dávať do herného
okna. Engine na to ale nie je pripravený, ale keďže sa bude hodiť aj pre
iné prípady, tak si túto vlastnosť dopíšeme niekedy v nejakom inom dieli.
Ešte je tam jeden menší zádrhel. Premenná c
bude vytváraná
zakaždým pri priechode vnútorným cyklom. Ak budeme mať bludisko 10x10, tak
to bude 100x. Čo nie je úplne zdravé. Presunieme deklaráciu pred oba cykly a
v každom koliesku ju len vynulujeme. Potreba bude tiež metóda, ktorá nám
premaže prvky bludisko. Vytvoríme si teda metódu Promaz
, ktorá
sa nám o to postará:
public void Promaz(){ foreach (Component c in Komponenty){ Parent.RemoveComponent(c); } Komponenty.Clear(); }
A túto metódu zavoláme v metóde Nacti
ako úplne prvá vec.
To nám zaistí zmiznutie starého bludisko v prípade načítanie nové.
Bystrejší z vás si všimli, že zatiaľ nepridávame žiadnu štartovej ani
cieľovú podlahu. Je to z toho dôvodu, že vytvorenie týchto tried v sebe
skrýva jedno malé úskalia a preto si ich ponechám na nabudúce.
Kompletujeme
Tu by mohol tento článok končiť, ale keďže chcem ukázať, že naša
snaha nebola zbytočná a že už v tejto chvíli si možno bludisko v hre
prejsť, premiestnime sa do nášho herného okna a premažeme všetko okrem
kamery, mriežky a samozrejme farebného pozadia. Vytvoríme si komponentu s
mapou, pridáme ju do zoznamu našich komponentov a až potom načítame súbor
přízračně nazvaný ddd.map
. Ja som to meno nevymyslel, to iní.
Tento súbor si premiestnime do priečinka, kde sa nachádza skompilovaný exe
súbor, ja ho mám v priečinku Debug
.
Mapa mapa = new Mapa(); AddComponent(mapa); mapa.Nacti("ddd.map");
U mriežky upravíme raster na 20 okienok sa šírkou tiež 20:
AddComponent(new Mrizka(20,20));
Napodiv je všetko hotové. Ak sa nám všetko podarilo urobiť správne, tak by pri spustení mal byť vidieť takýto nejaký výsledok:
Diery nám zatiaľ zostávajú pre štartové a koncovú dlaždicu.
Nabudúce si doplníme štartovú a koncovú dlaždicu a začneme uvažovať nad tým, ako zabrániť priechodu múrov. Bude potrebné si vytvoriť akýsi kolízne manažér, ktorý je obslúži. Zdrojový kód s celým projektom nájdete na obvyklom mieste pod článkom. Navyše som doňho pridal merania FPS. Mňa sa drží okolo šesťdesiatky, určite napíšte koľko máte vy treba v komentároch pod článkom, je ich totiž ako šafranu, zdá sa teda že všetci všetkému rozumie, všetko chápu, čo je super, lenže bez spätnej väzby sa mi funguje zle. Preto prosím, ak tento článok čítajte a páčil sa vám alebo sa vám nepáčil tak to dole v komentároch vyjadrite. Ďakujem a teším na nabudúce opäť dovidenia.
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é 247x (1.74 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#