Lekce 11 - 3D bludiště v XNA - Časujeme
Vítejte po jednadvacáté. V minulém díle, 3D bludiště v XNA - Kolize potřetí a snad naposledy, jsme konečně úplně dodělali náš kolizní systém.
Chvíli jsem přemýšlel, jestli budu i nadále číslovat, ale vzhledem k tomu, že to nikdo jiný nedělá, tak ano, budu V tomto díle si naší pokusnou kuličkou zkusíme projet bludiště na čas. Vytvoříme si komponentu obecného časovače a k tomu další časovač, který pude vykreslovat na obrazovku. Také si jej do hry naroubujeme. Budeme tedy moci projet bludiště na čas Pusťme se do toho.
Timer
Časovačů a jistě dokonalejších najdeme všude hromady. Nám postačí
snadňoučký, který půjde odstarovat, vynulovat a zase zastavit. Nic moc
těžkého. V metodě Update
se bude nasčítávat čas. Přidáme
si tedy nový soubor do našeho enginu, konkrétně do složky s komponentami.
Třídu nazveme Timer
. Učiníme ji veřejnou a tak dále, však to
znáte. Dědíme od třídy Component
. Čas budeme skladovat v
proměnné typu TimeSpan
.
public TimeSpan Time{ get; private set; }
V konstruktoru jej vynulujeme:
public Timer(){
Time = TimeSpan.Zero;
}
Dodáme také proměnnou pro indikaci zda-li je časovač aktivní:
public bool Running{ get; private set; }
Nastavování necháme soukromé, nechceme, aby bylo možné s proměnnou manipulovat mimo třídu. Následuje sled veřejných virtuálních metod:
public virtual void Start(){ Running = true; } public virtual void Stop(){ Running = false; } public virtual void Reset(){ Time = TimeSpan.Zero; }
Jejich význam není snad potřeba vysvětlovat. Poslední součástí je
přepsaná metoda Update
, kde nasčítáváme čas. Tedy asi
takto:
public override void Update(){ if(Running)Time += Parent.Engine.GameTime.ElapsedGameTime; }
Hotovo. Více toho opravdu není. Základní časovač je tedy hotov. My ale potřebujeme čas i ukazovat.
Vykreslovatelný timer
Přidáme si další třídu do složky s komponentami. Já jsem ji nazval
GameTimer
, ale opět jméno ponechám na vašem uvážení. Dědit
budeme od třídy Timer
, kterou jsme si připravili nahoře. Opět
je třída veřejná, ale to už víte lépe než já. Text budeme vykreslovat
skrze SpriteBatch
, jak jinak že. Potřebujeme znát jeho
pozici:
public Vector2 Pozice{ get; set; }
Jeho barvu
public Color Color{ get; set; }
A jakým fontem budeme vykreslovat:
private string fontName; protected SpriteFont Font;
V konstruktorech všechny parametry nastavíme:
public GameTimer(string font, Vector2 pozice): this(font,pozice,Color.Black){ } public GameTimer(string font, Vector2 pozice, Color color){ fontName = font; Pozice = pozice; Color = color; }
Tradičně v metodě Load
nahrajeme font.
protected override void Load(){ Font = Parent.Engine.Content.Load<SpriteFont>(fontName); }
A konečně v metodě Draw
vše vykreslíme:
public override void Draw(Microsoft.Xna.Framework.Matrix View, Microsoft.Xna.Framework.Matrix Projection, Microsoft.Xna.Framework.Vector3 CameraPosition){ Parent.Engine.SpriteBatch.Begin(); Parent.Engine.SpriteBatch.DrawString(Font, Time.ToString(@"mm\:ss\.ff"), Pozice, Color); Parent.Engine.SpriteBatch.End(); }
Vykreslovat počítání času na hodiny snad nebude potřeba. Zkusíme si přidat nový časovač do našeho herního okna.
AddComponent(new GameTimer("Maly", new Vector2(0, 10)));
Hru si pustíme a vidíme náš nádherný čas a také vidíme průšvih.
Je důležité si uvědomit, že pokaždé, když pracujeme se
SpriteBatch
, je třeba navrátit stav grafické karty do normálu.
Takže po vykreslení je navrátíme.
Parent.Engine.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
Parent.Engine.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
Parent.Engine.GraphicsDevice.BlendState = BlendState.Opaque;
Hotovo. Nyní je vše jak má být. Chybí nám už jen časovač odstartovat.
Startovní a cílová podlaha
To se bude dít na těchto našich speciálních podlahách. Začneme se
startovní podlahou, kterou až kulička/hráč opustí, tak se časovač
spustí. Otevřeme si tedy třídu se startovní podlahou. Změníme třídu od
které dědíme na CollidableModel3D
. Stejně jako jsme učinili u
zdi. Přepíšeme metodu Load
. Necháme zavolat metodu
Load
u předka. Naši kolizní krabici ale musíme na ose
Y
zvětšit, protože model jen jen placka a my potřebujeme plnou
krabici.
this.CollisionSkin.ZakladniKrabice.Max.Y = 15;
Zkusíme si hru spustit, zda-li je vše v pořádku. Je snad jasné, že
když na to tak upozorňuji, něco v pořádku nebude. Vůbec se nám nepovede
odjet pryč. Nečekaně. Systém nám detekuje kolizi a kuličku nepustí ani o
pixel. V našem systému chybí možnost udělat kůži průchozí. Ptáte se
proč ji tedy potřebujeme, když se skrze ní dá projít, ale právě o to
nám jde. Aby se zavolala událost a aby vše bylo na jednom místě. Podíváme
se tedy do naší kůže a do ní přidáme parametr Solid
:
public bool Solid{ get; set; }
V konstruktoru jej nastavíme na true
. Vše bude pevné jen na
výjimky, které si stanovíme. Jednou takovou je právě uděláme u startovní
podlahy, takže nastavíme Solid
na false
.
this.CollisionSkin.Solid = false;
Ještě jej potřebujeme zohlednit v kolizním manažeru. Do metody
Collide
přidáme před přidání kůže do seznamu podmínku, zda
je pevná:
if (skin.CheckCollision(sphere) && skin.Solid) colliding.Add(skin);
Pokud nyní hru spustíme, tak už se nám povede odjet. To byl onen zádrhel, který jsem avizoval minule. Více se jich snad už nenaskytne. Doufejme.
Poslední věcí, kterou potřebujeme, je odchytit událost, že kulička pole opustila. Přidáme si ji tedy:
this.CollisionSkin.UnCollided += new CollisionEnd(CollisionSkin_Collided);
Zároveň nám to vytvoří i obslužnou metodu. Uvnitř ní najdeme mezi komponentami časovač a spustíme jej:
void CollisionSkin_Collided(BoundingSphere koule){ GameTimer t = null; foreach (Component c in Parent.Components){ if (c is GameTimer){ t = c as GameTimer; break; } } if (t != null){ t.Start(); } }
Pokud nyní hru spustíme a odjedeme ze startovacího pole, vualáá, časovač jede. Stejný postup aplikujeme u cílové podlahy, jen časovač zastavíme a reagujeme na vstup do políčka ne na výstup. Pokud by měl někdo s tímto problém, tak vás odkazuji na celý kód pod článkem.
Příště, 3D bludiště v XNA - Hráčská kamera, si uděláme kameru a nahradíme jí tak kuličku. Poprvé si bludiště projdeme jako hráči.
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 160x (1.8 MB)
Aplikace je včetně zdrojových kódů v jazyce C# XNA