5. diel - XNA tvorba v 3D - Engine prvýkrát
Je to už po šiestykrát, čo píšem úvod k nejakému článku. V tomto
diele sa pozrieme na úvod do napísanie enginu. Bolo to celkom nevyhnutné,
nemá zmysel to moc naťahovať. Čím skôr si ho napíšete, tým lepšie.
Zjednoduší nám to prácu a písania kódu bude ľahšie a dosiahnuté
výsledky budú lepšie. Budeme môcť veľmi ľahko zaviesť pohyblivú kameru
a ďalšie pokročilejšie veci. Je síce pravdou, že sa na internete povaľuje
veľa viac-či menej hotových a funkčných enginov. Pokiaľ je ale budete pri
učení sa využívať (a to isté platí aj pre frameworky, a teraz sa chytám
do pastičky, pretože XNA
je tiež framework), tak sa môže
ľahko stať, že na danom prostredí zostanete závislí. Nedokáže si
predstaviť iné riešenie než za použitie danej veci. Uznávam, že pre
väčšie projekty nemá asi zmysel písať si vlastný engine, ale použiť už
niečo hotového, čo danej vlastnosti už má, ale pre naučenie sa
základných princípov je napísanie si vlastného podľa môjho názoru
nutné. Ďalej je tiež dobré mať na pamäti poučku, ktorú som našiel
niekde na internete, ale už si nie som istý kde to bolo, takže zatiaľ bez
zdroja:
Nepíšte engine, ale hru.
Chytil som sa tiež Avšak aby sme hru napísať mohli, nejaký základ potrebujeme a ten sa pokúsim v nasledujúcich dvoch dieloch vykonať. Nie je všetko z mojej hlavy. Za prvotný impulz vďačím Seanovi Jamesovi ( http://www.innovativegames.net/) a taky jeho knihe, odkiaľ sem načerpal veľa zaujímavých vecí, ktoré tu budem prezentovať neskôr. Sean vykonal myslím dovtedy nevídanú vec, urobil z písania enginu tutoriál. Iste možno predložiť holú kostru a tým si to odbiť (pre mňa ako autora najlepšie, čo si budeme nahovárať Dovolil som si teda vziať jeho prácu, upraviť ju podľa seba a potrieb, ktoré vzišli ďalším vývojom, a tú sa vám tu pokúsim predložiť. Zároveň hodlám ísť ešte o krôčik ďalej a zároveň s tvorbou jednotlivých komponentov paralelne pracovať aj na editora, ktorý umožní plné využitie enginu ako takého. Ako taký editor vyzerá v akcii sa môže pozrieť v tomto mojom videu:
Nie je to nič moc (obľúbený kravský obraz nesmie chýbať), ale základ je to slušný. Zanechajme ale úvodných rečí a pusťme sa do diela. Engine samotný sa skladá z troch hlavných tried. Základom enginu sú takzvané komponenty. Vyjadruje je triedaComponent
. Jedná sa napríklad o
model, text alebo napríklad fyzikálny systém. Až takto ďaleko možno
zájsť. Nepotrebujeme fyzikálny systém? Nepridáte komponent. Ako ľahké.
Komponent obsahuje metódy Draw
, Load
a
Update
, rovnako ako sme mali doteraz. Komponenty sa združujú do
herných okien reprezentovaných triedou GameScreen
. Táto trieda
spravuje poradie vykresľovania jednotlivých komponentov. Stará sa tiež o
volanie správnych metód v komponentoch. A na záver trieda
Engine
. Tá združuje herné okná a určuje ktoré bude
vykreslené. Umožňuje herné okno pridať, odobrať a podobne. Celý systém
je jednoduchý tak na pochopenie tak na implementáciu. Určite pripomína
veľmi nápadne systém, ktorý je v XNA
už vstavaný. Nie je
potreba nejako zastierať, že to tak naozaj je. Napriek tomu si myslím, že
keď si ho napíšeme sami, tak to bude lepšie.
Ako základ použijem obsah z predchádzajúcej lekcie, len som odstránil
všetko, čo súviselo s modelom. Vložíme nový a čistý projekt typu
Windows Game Library
(knižnica). Skontrolujte si, že používate
.NET Framework 4. Meno projektu nechám len a len na vás. Ja sme zvolil sebecky
VodacekEngine
, pretože sa mi rovnako už volá to čo mám
vytvorené a bude pre mňa pohodlnejšie mať rovnaký názov. Vytvoríme si v
ňom tri súbory s triedami Engine
, GameScreen
a
Component
. Nezabudnite je urobiť verejne prístupné
(public pred class). Pridáme referencie na knižnice
XNA
. Klikneme na referencie, v menu vyberieme
Add refenrece
, záložka .NET
, zídeme ukazovateľom
úplne dolu (tu pozor, chvíľu to trvá než sa zoznam načíta) a vyberieme
všetky s názvom Microsoft.Xna.Framework
. Je ich celkom 9.
V projekte s našou hrou učiníme podobný krok, ale namiesto knižníc
XNA
pridáme knižnicu s naším enginom. (Záložka Projects).
Teraz máme všetko pripravené a môžeme sa pustiť do samotného písania. Do
všetkých troch tried vložíme potrebné menné priestory:
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Content;
Začneme triedou Engine. Vytvoríme si metódy Update a Draw, netreba snáď hovoriť, na čo tieto metódy budú slúžiť. Zakaždým si v nich uložíme súčasný herný čas (premenná v parametri).
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; }
Vytvoríme si tiež konštruktor enginu, ako parameter odovzdáme inštanciu na našu súčasnú hru. Bude sa nám neskôr hodiť napríklad na nastavovanie titulku okna. Inštanciu si tiež uložíme do premennej:
private Game parent; public Game Parent { get { return parent; } } public Engine(Game parent){ this.parent = parent; }
Ďalej budeme potrebovať GraphicsDevice
, aby sme skrze neho
mohli vykresľovať. Urobíme si teda pre neho premennú:
private GraphicsDevice graphics; public GraphicsDevice GraphicsDevice{ get { return graphics; } }
a v konstruktoru ju naplníme:
this.graphics = parent.GraphicsDevice;
Hodiť sa určite bude tiež SpriteBatch
. Tak si ju vytvoríme
tiež:
private SpriteBatch spriteBatch; public SpriteBatch SpriteBatch{ get { return spriteBatch; } }
a opäť v konstruktoru ju vytvoríme:
this.spriteBatch = new SpriteBatch(graphics);
Ďalej nám chýba prostredník pre načítanie modelov, textúr a iných
vecí. Jedná sa o triedu ContentManager
, časom bude možno
potrebné napísať si vlastný rovnako ako to urobil Sean vo svojom enginu, ale
pre začiatok by som to nekomplikoval, takže iba takto:
private ContentManager content; public ContentManager Content{ get { return content; } }
a opäť do konstruktoru:
this.content = parent.Content;
Teraz máme všetky dôležité premenné hotové. Zostáva nám len pole pre herné okna:
public List<GameScreen> Screens;
ktoré opäť inicializujeme v konstruktoru:
Screens = new List<GameScreen>();
U tohto poľa pre herné obrazovky bude vhodné sa viac zastaviť. Má totiž
fungovať ako takzvaný zásobník. Ten si môžeme predstaviť ako takú veža.
Na vrchol dávame jednotlivé okná, ale keď ich chceme vybrať, tak je
odoberáme opäť zo zhora. Niekedy sa tomu tiež hovorí LIFO
(last in first out - posledný dnu a prvý von). Pre prácu s týmto
zásobníkom budeme používať metódu PushGameScreen
, ktorá
herné okno na zásobník položí a vykoná jeho načítanie. Ďalej tiež
metódu PopGameScreen
, ktorá herné okno zo zásobníka vyzdvihne.
Toto riešenie nám umožní neskôr mať naraz vykresľovanie viac ako 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; }
Teraz pridáme do triedy našej GameScreen
virtuálnej metódy
Draw
a Update
. Tentokrát už bez parametrov:
public virtual void Update(){ } public virtual void Draw(){ }
V triede s Enginu
je na príslušných miestach zavoláme. Po
úprave budú teda vyzerať nasledovne:
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(); } }
Gratulujem. Máme triedu s enginom pripravenú. Do ďalších tried sa pustíme zase nabudúce. Len dúfam, že to nikoho z vás neodradilo a ak predsa len áno, tak nezúfajte. Dole pod článkom ako vždy nájdete kompletný zdrojový kód, avšak stále si myslím, že ak si ho napíšete sami a pochopíte tak ako funguje, že to bude lepšie ako len preložiť hotový kód a teraz s tým budeme robiť. Čo sa deje vo vnútri vás nemusí zaujímať, niečo sa tam stane a tu je takovej výsledok. Teším sa tiež na komentáre, hlavne aby som si o ne nemusel hovoriť
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é 299x (1.57 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#