IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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
Štartové a cieľové pole by sa mali vyskytovať v každej mape len raz. Iste môže byť viac cieľov, jeden ľahko dosiahnuteľný a ďalšie horšie, ale to zatiaľ pre jednoduchosť vynechajme. Priestoru pre typy políčok je tam veľa. Môžete si vymyslieť políčka, ktorá hráča zbrzdí, násilne ho otočí, otočí mu kameru hore nohami a potom zas naopak ... Fantázii sa medze nekladú. Pre začiatok si vystačíme s týmto základom.

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:

3D bludisko v C# .NET XNA - 3D bludisko v XNA

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#

 

Predchádzajúci článok
3D bludisko v XNA - Editor máp
Všetky články v sekcii
3D bludisko v XNA
Preskočiť článok
(neodporúčame)
3D bludisko v XNA - Dokončenie editoru máp
Článok pre vás napísal vodacek
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Vodáček dělá že umí C#, naplno se již pět let angažuje v projektu ŽvB. Nyní studuje na FEI Upa informatiku, ikdyž si připadá spíš na ekonomice. Není mu také cizí PHP a SQL. Naopak cizí mu je Java a Python.
Aktivity