4. díl - 3D bludiště v XNA - Mapy, zdi a podlaha

C# .NET XNA game studio 3D bludiště 3D bludiště v XNA - Mapy, zdi a podlaha

Vítejte po patnácté. Jistě jste si všimli předchozího článku od zmijozeláka. Editor pro naše bludiště bude velmi potřeba, zrychlí tvorbu nových levelů. My se ale nebudeme zaobírat v tomto článku pokračováním v editoru, ale pohneme se hrou. Vytvoříme si komponentu s mapou a také komponenty pro zdi a podlahy. Pokusíme se také načíst soubor s mapou. Je to hodně práce, tak se do toho hned pustíme.

Zeď

První bude potřeba komponenta pro zdi. Nebude to nic zázračného, celý kód je velmi velmi krátký. Vytvoříme si tedy složku pro komponenty v naší hře. Zde si vytvoříme novou třídu, pojmenujme si ji třeba Zed. Učiníme ji veřejnou, upravíme jmenný prostor. Budeme dědit od třídy Model3D, která se nám modely reprezentuje. Do obsahu hry přidáme model podlaha, který budeme používat. Vytvoříme si konstruktor:

public Zed(int x, int z): base(new Vector3(x*20+10,0,z*20+10),Matrix.Identity,new Vector3(1.34f),"zed"){

}

Jako parametr předáváme souřadnice x a y v poli s bludištěm, které pak přepočteme na skutečné ve světě. Rotace nechceme žádné, měřítko jsem pokusně stanovil na 1.34x, i když jsem v Cinemě 4D nastavil velikost na přesně 100, tak jsou zde velikosti jiné. Zeď je prozatím hotova. Věci pro kolize přidáme příště.

Podlaha

Další komponenta pro průchozí podlahy, opět vytvoříme třídu stejně jako minule, uděláme ji veřejnou, dědíme od Model3D a zase vytvoříme konstruktor:

public Podlaha(int x, int z): base(new Vector3(x*20+10,0,z*20+10),Matrix.Identity,new Vector3(1.34f),"podlaha"){

}

Vše je prakticky stejné jako u zdi. Jen se změnilo jméno modelu. Jistě vás zaujal podivný výpočet polohy. Bude se hodit později. O tom, jak tento vzoreček funguje, se zmíním doleji, pokud na to nezapomenu.

Mapa

Třetí komponenta, se kterou budeme pracovat, je mapa. Mapa v sobě bude mít uložené všechny zdi a podlahy, bude je přidávat do herního okna a opět zase odebírat. Zkrátka bude mít na starosti podobu bludiště. Jak už zmijozelák naznačil ve svém článku, mapa levelu bludiště je uložená ve dvojrozměrném poli celých čísel. Každé číslo bude reprezentovat jeden typ políčka. V následující tabulce je souhrn:

0 volno
1 zeď
99 startovní pole
100 cilové pole

Startovní a cílové pole by se měly vyskytovat v každé mapě jen jednou. Jistě může být více cílů, jeden snadno dosažitelný a další hůře, ale to prozatím pro jednoduchost vynechme. Prostoru pro typy políček je tam mnoho. Můžete si vymyslet políčka, která hráče zbrzdí, násilně jej otočí, otočí mu kameru vzhůru nohama a pak zas naopak... Fantazii se meze nekladou. Pro začátek si vystačíme s tímto základem.

Opět si založíme soubor s třídou Mapa ve složce pro komponenty. Opět dědíme od třídy Component. Vytvoříme si seznam, ve kterém budeme uchovávat námi přidané komponenty:

private List<Component> Komponenty;

V konstruktoru jej vytvoříme:

public Mapa(){
  Komponenty = new List<Component>();
}

Vytvoříme si metodu Nacti, kde budeme načítat bludiště ze souboru. Jako parametr metody předáme cestu k souboru. Ale jelikož jsme programátoři a jsme líní psát něco co už jsme napsali znovu, tak se podíváme do zmijozelákova článku, najdeme stejně pojmenovanou metodu, nakopírujeme si ji a docela ji promázneme. Asi tak jak jsem to udělal já:

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 zmizelo vše s ukládáním do pole a také si proparsovaný výsledek ukládáme do proměnné. Není to úplně bezpečný způsob, co když se nám tam dostane nějaký znak namísto číslice? Tak nám aplikace pochopitelně spadne, to ošetříme změnou metody z Parse na TryParse:

int typ=-1;
int.TryParse(radek[i],out typ);

Jak to celé jinak funguje se dočtete v předcházejícím článku. Nám už jen zbývá přidat příslušnou komponentu na dané místo, to se bude dělat velmi snadno, použijeme switch, ač bych tam nejraději nacpal stromeček if-else, ale pro výukové potřeby se obětuji:

Component c=null;
switch (typ){
  case 0:{
    c=new Podlaha(i, j);
    break;
  }
  case 1:{
    c=new Zed(i, j);
    break;
  }
}

A pokud bude proměnná c rozdílná od null, tak ji přidáme do našeho seznamu a zároveň i do herního okna:

if (c != null){
  Parent.AddComponent(c);
  Komponenty.Add(c);
}

Tady je vidět mírná nedomyšlenost enginu jako takového. Bylo by příhodnější a lepší, kdyby mohla mapa sama řídit vykreslování součástí bludiště. Sama si je spravovat, přidávat a mazat aniž by musela komponenty dávat do herního okna. Engine na to ale není připravený, ale jelikož se bude hodit i pro jiné případy, tak si tuto vlastnost dopíšeme někdy v nějakém jiném dílu. Ještě je tam jeden menší zádrhel. Proměnná c bude vytvářena pokaždé při průchodu vnitřním cyklem. Pokud budeme mít bludiště 10x10, tak to bude 100x. Což není úplně zdravé. Přesuneme deklaraci před oba cykly a v každém kolečku ji jen vynulujeme. Potřeba bude také metoda, která nám promaže prvky bludiště. Vytvoříme si tedy metodu Promaz, která se nám o to postará:

public void Promaz(){
  foreach (Component c in Komponenty){
    Parent.RemoveComponent(c);
  }
  Komponenty.Clear();
}

A tuto metodu zavoláme v metodě Nacti jako úplně první věc. To nám zajistí zmizení starého bludiště v případě načtení nového. Bystřejší z Vás si všimli, že zatím nepřidáváme žádnou startovní ani cílovou podlahu. Je to z toho důvodu, že vytvoření těchto tříd v sobě skrývá jedno malé úskalí a proto si je ponechám na příště.

Kompletujeme

Zde by mohl tento článek končit, ale jelikož chci ukázat, že naše snaha nebyla zbytečná a že již v tuto chvíli si lze bludiště ve hře projít, přemístíme se do našeho herního okna a promažeme vše kromě kamery, mřížky a samozřejmě barevného pozadí. Vytvoříme si komponentu s mapou, přidáme ji do seznamu našich komponent a až potom načteme soubor přízračně nazvaný ddd.map. Já jsem to jméno nevymyslel, to jiní. Tento soubor si přemístíme do složky, kde se nalézá zkompilovaný exe soubor, já jej mám ve složce Debug.

Mapa mapa = new Mapa();
AddComponent(mapa);
mapa.Nacti("ddd.map");

U mřížky upravíme rastr na 20 okének se šířkou také 20:

AddComponent(new Mrizka(20,20));

Kupodivu je vše hotovo. Pokud se nám vše povedlo udělat správně, tak by při spuštění měl být vidět takovýto nějaký výsledek:

3D bludiště v C# .NET XNA

Díry nám zatím zůstávají pro startovní a koncovou dlaždici.

Příště si doplníme startovní a koncovou dlaždici a začneme uvažovat nad tím, jak zabránit průchodu zdí. Bude potřeba si vytvořit jakýsi kolizní manažer, který je obslouží. Zdrojový kód s celým projektem najdete na obvyklém místě pod článkem. Navíc jsem do něj přidal měření FPS. Mě se drží kolem šedesátky, určitě napište kolik máte vy třeba v komentářích pod článkem, je jich totiž jako šafránu, zdá se tedy že všichni všemu rozumí, všechno chápou, což je super, jenže bez zpětné vazby se mi funguje špatně. Proto prosím, pokud tento článek čtěte a líbil se vám nebo se vám nelíbil tak to dole v komentářích vyjádřete. Děkuji a těším na příště opět na shledanou.


 

Stáhnout

Staženo 235x (1.74 MB)
Aplikace je včetně zdrojových kódů v jazyce C# XNA

 

  Aktivity (1)

Článek pro vás napsal vodacek
Avatar
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.

Jak se ti líbí článek?
Celkem (3 hlasů) :
55555


 


Miniatura
Předchozí článek
3D bludiště v XNA - Editor map
Miniatura
Všechny články v sekci
3D bludiště v XNA

 

 

Komentáře
Zobrazit starší komentáře (5)

Avatar
David
Redaktor
Avatar
David:

59,999995 nebo tak nějak fakt je to asi stardantnich tych +- 60 FPS

Odpovědět 23.1.2013 18:03
Nic néni nemožné!
Avatar
KlimiCZ
Člen
Avatar
KlimiCZ:

Jak se vytvářejí ty obrázky s koncovkou fbx ?

Odpovědět 15.6.2013 8:22
Nesnaž se zakrýt něco, co jsi provedl úmyslně. Svět je tak malý, že dotyčný se to stejně dozví.
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na KlimiCZ
Jiří Gracík:

xnb? pokud pracuješ v XNA tak automaticky, pokud v Monu, tak je musíš zkompilovat externě nebo si pro to něco dopsat. Já používám XNAFormatter, musíš mít nainstalované XNA aby to mohlo kompilovat :)

http://www.softpedia.com/…matter.shtml

Odpovědět 15.6.2013 8:30
Creating websites is awesome till you see the result in another browser ...
Avatar
KlimiCZ
Člen
Avatar
Odpovídá na Jiří Gracík
KlimiCZ:

stáhl jsem si tenhle soubor (nahoře save) a chtěl bych ty ikonky ,ale nejdeto

Odpovědět 15.6.2013 8:51
Nesnaž se zakrýt něco, co jsi provedl úmyslně. Svět je tak malý, že dotyčný se to stejně dozví.
Avatar
vodacek
Redaktor
Avatar
Odpovídá na Jiří Gracík
vodacek:

ne fbx

Editováno 15.6.2013 10:38
 
Odpovědět 15.6.2013 10:37
Avatar
vodacek
Redaktor
Avatar
Odpovídá na KlimiCZ
vodacek:

vymodeluješ objekt třebas v blenderu nebo jako já v Cinema4D a pak to do tohoto formátu vyexportuješ

 
Odpovědět 15.6.2013 10:37
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na vodacek
Jiří Gracík:

áha, tak promiň, s 3D jsem v XNA ještě nedělal :P

Odpovědět 15.6.2013 10:53
Creating websites is awesome till you see the result in another browser ...
Avatar
KlimiCZ
Člen
Avatar
Odpovídá na vodacek
KlimiCZ:

Takže to je 3D model ?

Odpovědět 15.6.2013 13:34
Nesnaž se zakrýt něco, co jsi provedl úmyslně. Svět je tak malý, že dotyčný se to stejně dozví.
Avatar
vodacek
Redaktor
Avatar
 
Odpovědět 15.6.2013 13:38
Avatar
KlimiCZ
Člen
Avatar
Odpovídá na vodacek
KlimiCZ:

Dík teď sem zase o něco chytřejší :)

Odpovědět 15.6.2013 14:21
Nesnaž se zakrýt něco, co jsi provedl úmyslně. Svět je tak malý, že dotyčný se to stejně dozví.
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 10 zpráv z 15. Zobrazit vše