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í.

Lekce 6 - 3D bludiště v XNA - Podlahy podruhé a kolize

Vítejte po šestnácté. V minulé lekci, 3D bludiště v XNA - Dokončení editoru map, jsme dokončili náš editor map.

V tomto díle si vytvoříme cílovou a startovní podlahu, které budou jinak barevné než zbylé podlahy. Vytvoření oněch podlah není tak triviální jako u podlahy normální, ale to se hnedle ukáže. Dále se podíváme na možnosti kolizí a celý systém promyslíme. Na závěr si napíšeme pomocné třídy pro vykreslení krabice a koule.

Startovní a cílová podlaha

Vytvoříme si stejně jako posledně soubor ve složce na komponenty. Třídu opět nazvěte tak jak je vám libo, já jsem zvolil StartovniPodlaha. Konstruktor zůstane stejný jako minule:

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

}

Zatím není žádná podivnost na obzoru. Nyní má ale podlaha stejný vzhled jako podlahy ostatní. Ale my chceme dlaždici zvýraznit jinou barvou. Máme v zásadě dvě možnosti. Buď si v modelovacím programu dlaždici nabarvíme a uděláme si tak nový model a máme po problémech a nebo si barvu při vykreslení upravíme. První možnost je pro sraby a tak si barvu jednoduše změníme při vykreslení.

Přepíšeme si metodu Draw s našimi parametry:

public override void Draw(Matrix View, Matrix Projection, Vector3 CameraPosition)

A nakopírujeme vlastně celý obsah původní metody, takže pro přehled ji zde uvádím:

Matrix world = Utility.CreateWorld(Pozice, Rotace, Meritko);
foreach (ModelMesh mesh in Model.Meshes){
  foreach (ModelMeshPart part in mesh.MeshParts){
    if (part.Effect is BasicEffect){
      BasicEffect efekt = part.Effect as BasicEffect;
      efekt.View = View;
      efekt.Projection = Projection;
      efekt.World = transformace[mesh.ParentBone.Index] * world;
      efekt.EnableDefaultLighting();
    }
  }
  mesh.Draw();
}

A půl práce je hned hotovo. Ještě nezapomenout nastavit poli s transformacemi modifikátor na protected, stejně jako jsem udělal já:

protected Matrix[] transformace;

Barvu vykreslované plochy změníme velmi snadno. BasicEffect na to má přímo proměnnou DiffuseColor. Ale ta není kupodivu typu Color jak by se čekalo, ale Vector3. Grafická karta totiž nepracuje s barvami ve formátu 0-255 ale 0-1 a na jejich uložení se hodí právě Vector3. Vector4 se pak šikne pro barvy s alfa kanálem, ale tím se zatím nebudeme zatěžovat. Třída vektoru tak dostává už třetí význam. Připomeňme, že první bylo určení pozice a druhý byl vektor třeba pro pohyb. Jak je navzájem převést nemusíme řešit. Struktura Color na to má metodu ToVector3, kterou použijeme. Vector3 ani Color už ale zpětnou metodu nemá. Do efektu tedy přiřadíme třeba světlemodrou barvu:

efekt.DiffuseColor = Color.Aqua.ToVector3();

Najdeme si třídu s mapou a do switche si přidáme další větev s novou podlahou:

case 99:{
  c = new StartovniPodlaha(i, j);
  break;
}

Zkusíme si výsledek spustit abychom viděli novou tyrkysovou pohromu, která je rozlezlá po všech podlahách.

Podlahy v 3D bludišti v C# XNA - 3D bludiště v XNA

Důvod je jasný. XNA se snaží šetřit a tak pokaždé, když se pokusíme o nahrání modelu nebo čehokoliv, tak se podívá, zda-li jsme tak již neučinili a v případě že ano nám vrátí uloženou instanci. To se nám moc nehodí, celou věc to mírně komplikuje, ale není to nic nepřekonatelného. Úplně bude stačit, když při vykreslení navrátíme původní barvu. Takže hned za vykreslení dané meshe modelu přidáme další foreach cyklus, kde barvu navrátíme:

foreach (ModelMeshPart part in mesh.MeshParts){
  if (part.Effect is BasicEffect){
    BasicEffect efekt = part.Effect as BasicEffect;
    efekt.DiffuseColor = Color.Blue.ToVector3();
  }
}

To je vše. Pokud nyní hru spustíme, tyrkysové zůstalo jen jedno pole a to je to, co chceme. Úplně stejně budeme postupovat i v případě cílové podlahy, pouze zvolíme jinou výraznou barvu (já jsem dal červenou), jiné číslo pole, v tomto případě 100, a jiný název souboru a třídy.

Podlahy v 3D bludišti v C# XNA - 3D bludiště v XNA

Kolize

Vůbec největší oříšek, kterému budeme čelit, jsou kolize. Pokud se nad tím zamyslíte, tak je lze vyřešit i zcela intuitivně. Máme k dispozici pole s průchozími a neprůchozími políčky. Lze tak pohyb hráče vymezit jen a pouze skrze souřadnice. Je to funkční, je to snadné. Ovšem při tvorbě enginu, o který se tak trochu stále více skrytě pokouším, to není moc taktický krok. V jaké jiné hře toto použijete? Obávám se, že asi už v žádné jiné. Má proto asi větší cenu pokusit se o pokročilejší systém, který na tomto snadném případu můžeme vyzkoušet, vytvořit a pak jej jen na složitější věci aplikovat a případně jej jen kapku rozšířit.

Základem jsou kolizní objekty, které jakoby obalují naše modely a kolize zjednodušují a dělají je matematicky uskutečnitelnými v reálném čase. Zatím jsou naše modely velmi snadné, jak do počtu hran a vrcholů, tak pro kolize, ale ne vždy to tak s modely je. Právě proto se obalují tvarově a výpočetně snazšími objekty. Trpíme tím sice na přesnosti kolize, ale za to dostáváme kratší výpočetní čas. A to je povětšinou to hlavní, o co nám jde, aby hra běžela co nejsvižněji. Používají se dva zásadní tvary: koule a krychle nebo chcete-li kvádr. Pro výpočty je nejrychlejší kolize koule s koulí. Jen se spočítá vzdálenost jejich středů. Kvádry, kterým budu pro jistotu říkat krabice, již mají výpočet složitější, ale je zde zavedeno několik zjednodušujících pravidel.

Krabice používané v XNA jsou osově orientované. Anglicky lze hledat návody a algoritmy pod názvem axis aligned bounding box nebo jen se zkratkou AABB. Co to ale znamená osově orientované? Česky lze říct že s nimi nejde rotovat. Jejich hrany stále zůstávají rovnoběžné s osami herního světa. Jak to vypadá když se objekt otáčí můžete vidět na tomto mém vídeu:

Krabice se nám zvětšuje a opět zmenšuje. Není to moc dobré, ale co naděláme. Máme tu ještě kouli, která se pro rotující objekty hodí více, při rotaci je totiž stále stejná :-) ale ne zas na všechny druhy objektů se hodí. Naše zdi by nebyly příliš dobře obalitelné koulí. Naopak pro hráče se koule hodí myslím poměrně dobře. XNA obsahuje také paprsek Ray, ten se hodí pro střílení a klikání myší na objekty za použití takzvaného ray castingu. Máme také také plochu Plane. Plocha není ničím omezena je tedy nekonečně velká. Ale i tak ji lze použít třeba k ukončení světa.

Hráče si tedy obalíme koulí, zdi zas krabicemi. Stále je ale počet výpočtů, které musíme provést při každém volání metody Update u herního okna (zde totiž budeme kolize počítat), velmi velký. Vezměte si, že máme bludiště 10x10 políček. To máme celkem v nejhorším případě 100 kusů zdí. Hráč může kolidovat se 100 objekty, krabice kolem zdi s dalšími 100 a tak dále. To je nepředstavitelně velký počet výpočtů. Proto označíme krabice pro zdi za statické a tím také ušetříme spoustu výpočetního času. Počítat se bude tedy pouze 100 kolizí, ale i to je poměrně dost. Existují metody, které nám to mohou razantně zmenšit, ale ty prozatím ponechme stranou.

Rozvahu jak to to půjdeme máme tedy hotovu. Dost mi chybí že v návodech na internetu se obvykle jen dočtete jak to řešit, ale proč takto a ne jinak se už nedozvíte. Prostě proto. Snažím se být v tomto směru jiný a své myšlenkové pochody (často realizované v posteli před spaním) v tomto textu prezentovat. Mnohokráte jsem se svými řešeními narazil na nepochopení, naposled výrazněji na sočce, ale tím že sem byl ve státním kole se zde nebudu vytahovat. Pokud vás spíš zajímá, jak si okopírovat bezmyšlenkovitě těch pár řádek kódu, tak to si budete muset počkat na jindy. Nemám zde stále ještě moc jasno jak přesně to uděláme, ale už se obloha protrhává.

Co vím jistě je, že bude potřeba je krabice a koule, na ty se podíváme příště, 3D bludiště v XNA - Krabice a koule.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

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

 

Předchozí článek
3D bludiště v XNA - Dokončení editoru map
Všechny články v sekci
3D bludiště v XNA
Přeskočit článek
(nedoporučujeme)
3D bludiště v XNA - Krabice a koule
Článek pro vás napsal vodacek
Avatar
Uživatelské hodnocení:
2 hlasů
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