Lekce 5 - XNA tvorba ve 3D - Engine poprvé
Je to již pošesté, co píši úvod k nějakému článku. Minule, XNA tvorba ve 3D - Modely, jsme si ukázali modely.
V tomto díle se podíváme na úvod do napsání enginu. Bylo to celkem
nevyhnutné, nemá smysl to moc natahovat. Čím dříve si jej napíšete, tím
lépe. Zjednoduší nám to práci a psaní kódu bude snadnější a dosažené
výsledky budou lepší. Budeme moci velmi snadno zavést pohyblivou kameru a
další pokročilejší věci. Je sice pravdou, že se na internetu povaluje
hodně více-či méně hotových a funkčních enginů. Pokud je ale budete
při učení se využívat (a to samé platí i pro frameworky, a teď se
chytám do pastičky, protože XNA
je také framework), tak se
může snadno stát, že na daném prostředí zůstanete závislí. Nedovede si
představit jiné řešení než za použití dané věci. Uznávám, že pro
větší projekty nemá asi smysl psát si vlastní engine, ale použít už
něco hotového, co dané vlastnosti už má, ale pro naučení se základních
principů je napsání si vlastního podle mého názoru nutné. Dále je také
dobré mít na paměti poučku, kterou jsem našel někde na internetu, ale už
si nejsem jistý kde to bylo, takže zatím bez zdroje:
Nepište engine, ale hru.
Chytil jsem se také Nicméně abychom hru napsat mohli, nějaký základ potřebujeme a ten se pokusím v následujících dvou dílech provést. Není vše z mé hlavy. Za prvotní impulz vděčím Seanu Jamesovi (http://www.innovativegames.net/) a taky jeho knize, odkud sem načerpal spoustu zajímavých věcí, které tu budu prezentovat později. Sean provedl myslím do té doby nevídanou věc, udělal z psaní enginu tutoriál. Jistě lze předložit holou kostru a tím si to odbýt (pro mě jako autora nejlepší, co si budeme namlouvat Dovolil jsem si tedy vzít jeho práci, upravit ji podle sebe a potřeb, které vzešly dalším vývojem, a tu se vám tady pokusím předložit. Zároveň hodlám jít ještě o krůček dále a zároveň s tvorbou jednotlivých komponent paralelně pracovat i na editoru, který umožní plné využití enginu jako takového. Jak takový editor vypadá v akci se může podívat v tomto mém videu:
Není to nic moc (oblíbený kravský obraz nesmí chybět), ale základ je
to slušný. Zanechme ale úvodních řečí a pusťme se do díla. Engine
samotný se skládá ze tří hlavních tříd. Základem enginu jsou takzvané
komponenty. Vyjadřuje je třída Component
. Jedná se kupříkladu
o model, text nebo třeba fyzikální systém. Až takto daleko lze zajít.
Nepotřebujeme fyzikální systém? Nepřidáme komponentu. Jak snadné.
Komponenta obsahuje metody Draw
, Load
a
Update
, stejně jako jsme měli doposud. Komponenty se sdružují
do herních oken reprezentovaných třídou GameScreen
. Tato
třída řídí pořadí vykreslování jednotlivých komponent. Stará se také
o volání správných metod v komponentách. A na závěr třída
Engine
. Ta sdružuje herní okna a určuje které bude vykresleno.
Umožňuje herní okno přidat, odebrat a podobně. Celý systém je snadný jak
na pochopení tak na implementaci. Určitě připomíná velmi nápadně
systém, který je v XNA
již vestavěn. Není potřeba nějak
zastírat, že tomu tak opravdu je. Přesto si myslím, že když si jej
napíšeme sami, tak to bude lepší.
Jako základ použiji obsah z předcházející lekce, pouze jsem odstranil
vše, co souviselo s modelem. Vložíme nový a čistý projekt typu
Windows Game Library
(knihovna). Zkontrolujte si, že používáte
.NET Framework 4. Jméno projektu nechám jen a jen na vás. Já jsme zvolil
sobecky VodacekEngine
, jelikož se mi stejně už jmenuje to co
mám vytvořeno a bude pro mě pohodlnější mít stejný název. Vytvoříme
si v něm tři soubory s třídami Engine
, GameScreen
a Component
. Nezapomeňte je učinit veřejně přístupné
(public před class). Přidáme reference na knihovny
XNA
. Klikneme na reference, v menu vybereme
Add refenrece
, záložka .NET
, sjedeme ukazatelem
úplně dolů (zde pozor, chvíli to trvá než se seznam načte) a vybereme
všechny s názvem Microsoft.Xna.Framework
. Je jich celkem 9.
V projektu s naší hrou učiníme podobný krok, ale namísto knihoven
XNA
přidáme knihovnu s naším enginem. (záložka Projects).
Nyní máme vše připraveno a můžeme se pustit do samotného psaní. Do
všech tří tříd vložíme potřebné jmenné prostory:
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content;
Začneme třídou Engine. Vytvoříme si metody Update a Draw, netřeba snad říkat, k čemu tyto metody budou sloužit. Pokaždé si v nich uložíme současný herní čas (proměnná v parametru).
private GameTime gameTime; public GameTime GameTime{ get { return gameTime; } } public void Update(GameTime time){ this.gameTime = time; } public void Draw(GameTime time){ this.gameTime = time; }
Vytvoříme si také konstruktor enginu, jako parametr předáme instanci na naši současnou hru. Bude se nám posléze hodit kupříkladu na nastavování titulku okna. Instanci si také uložíme do proměnné:
private Game parent; public Game Parent { get { return parent; } } public Engine(Game parent){ this.parent = parent; }
Dále budeme potřebovat GraphicsDevice
, abychom skrze něj
mohli vykreslovat. Uděláme si tedy pro něj proměnnou:
private GraphicsDevice graphics; public GraphicsDevice GraphicsDevice{ get { return graphics; } }
a v konstruktoru ji naplníme:
this.graphics = parent.GraphicsDevice;
Hodit se určitě bude také SpriteBatch
. Tak si ji vytvoříme
také:
private SpriteBatch spriteBatch; public SpriteBatch SpriteBatch{ get { return spriteBatch; } }
a opět v konstruktoru ji vytvoříme:
this.spriteBatch = new SpriteBatch(graphics);
Dále nám chybí prostředník pro načítání modelů, textur a jiných
věcí. Jedná se o třídu ContentManager
, časem bude možná
potřeba napsat si vlastní stejně jako to udělal Sean ve svém enginu, ale
pro začátek bych to nekomplikoval, takže pouze takto:
private ContentManager content; public ContentManager Content{ get { return content; } }
a opět do konstruktoru:
this.content = parent.Content;
Nyní máme všechny důležité proměnné hotové. Zbývá nám jen pole pro herní okna:
public List<GameScreen> Screens;
které opět inicializujeme v konstruktoru:
Screens = new List<GameScreen>();
U tohoto pole pro herní obrazovky bude vhodné se více zastavit. Má totiž
fungovat jako takzvaný zásobník. Ten si můžeme představit jako takovou
věž. Na vrchol dáváme jednotlivá okna, ale když je chceme vybrat, tak je
odebíráme opět ze shora. Někdy se tomu také říká LIFO
(last
in first out – poslední dovnitř a první ven). Pro práci s tímto
zásobníkem budeme používat metodu PushGameScreen
, která herní
okno na zásobník položí a provede jeho načtení. Dále také metodu
PopGameScreen
, která herní okno ze zásobníku vyzvedne. Toto
řešení nám umožní později mít najednou vykreslované více než jedno
herní okno.
public void PushGameScreen(GameScreen okno){ Screens.Add(okno); } public GameScreen PopGameScreen(){ if (Screens.Count == 0) return null; GameScreen ret=Screens[Screens.Count-1]; Screens.Remove(ret); return ret; }
Nyní přidáme do třídy naší GameScreen
virtuální metody
Draw
a Update
. Tentokráte již bez parametrů:
public virtual void Update(){ } public virtual void Draw(){ }
V třídě s Enginu
je na příslušných místech zavoláme. Po
úpravě budou tedy vypadat následovně:
public void Update(GameTime time){ this.gameTime = time; foreach (GameScreen okno in Screens){ okno.Update(); } } public void Draw(GameTime time){ this.gameTime = time; foreach (GameScreen okno in Screens){ okno.Draw(); } }
Gratuluji. Máme třídu s enginem připravenu. Do dalších tříd se pustíme zase příště. Jen doufám, že to nikoho z vás neodradilo a pokud přecijen ano, tak nezoufejte. Dole pod článkem jako vždy naleznete kompletní zdrojový kód, ovšem stále si myslím, že pokud si jej napíšete sami a pochopíte tak jak funguje, že to bude lepší než jen přeložit hotový kód a teď s tím budeme dělat. Co se děje vevnitř vás nemusí zajímat, něco se tam stane a tady je takovej výsledek. Těším se také na komentáře, hlavně abych si o ně nemusel říkat
V další lekci, XNA tvorba ve 3D - Engine podruhé a ne naposledy, engine dokončíme.
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 299x (1.57 MB)
Aplikace je včetně zdrojových kódů v jazyce C#