Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

12. diel - 3D bludisko v XNA - Hráčska kamera

Vitajte po dva-a-dvadsiatej. V tomto diele si pokusnú guličku nahradíme kamerou a prvýkrát si teda vyskúšame bludisko prejsť ako hráči, teda z pohľadu 1. osoby.

Hráčska kamera

Ako kameru pre hráčov nemôžeme použiť tú čo máme teraz. Naša kamera nerešpektuje kolízie a navyše s ňou dá lietať hore a dole. Vytvoríme si teda kameru novú, do priečinka na kamery si pridáme nový súbor s triedou FPSKamera. Dediť budeme od TargetKamery, rovnako ako v prípade voľnej kamery. Potreba budú dve premenné pre natočenie kamery, nič nové pod slnkom:

float fYaw, fPitch;

public float Yaw{
  get{
    return fYaw;
  }
  set{
    fYaw = value;
  }
}

public float Pitch{
  get{
    return fPitch;
  }
  set{
    fPitch = value;
  }
}

Novinkou je naopak kolízne gule.

BoundingSphere koule;

Ktorú si v konstruktoru spolu s ostatnými premennými nastavíme:

public FPSKamera(GameScreen okno, Vector3 pozice, Vector3 target)
  : base(okno, pozice, target){
  fYaw = 0;
  fPitch = 0;

  koule = new BoundingSphere(pozice, 5);
}

Pozícia stredu gule je rovnaká ako pozície kamery a polomer guľa je päť jednotiek. Len pripomeniem, že veľkosť kociek sme si zvolili na 20 jednotiek, takže je okolo gule dostatok miesta pre pohyb. Máme všetko pripravené až na to, že kamera je zatiaľ statická. Vezmeme si metódu Update z voľnej kamery a tú si len mierne upravíme. Takže len pre úplnosť ako metóda vyzerá:

public override void Update(){
  fYaw -= Parent.Engine.Input.DeltaX*0.01f;
  fPitch -= Parent.Engine.Input.DeltaY * 0.01f;

  Matrix rotace = Matrix.CreateFromYawPitchRoll(fYaw, fPitch, 0);

  Vector3 posun = Vector3.Zero;
  if (Parent.Engine.Input.DrzenaKlavesa(Keys.Up)) posun += Vector3.Forward;
  if (Parent.Engine.Input.DrzenaKlavesa(Keys.Down)) posun += Vector3.Backward;
  if (Parent.Engine.Input.DrzenaKlavesa(Keys.Left)) posun += Vector3.Left;
  if (Parent.Engine.Input.DrzenaKlavesa(Keys.Right)) posun += Vector3.Right;

  posun *= 0.1f * (float)Parent.Engine.GameTime.ElapsedGameTime.TotalMilliseconds;

  Pozice += Vector3.Transform(posun,rotace);

  Target = Pozice + Vector3.Transform(Vector3.Forward,rotace);
  base.Update();
}

Prvá vec, ktorú musíme napraviť, je rotačné matice. Nechceme, aby bolo možné stúpať s kamerou hore a dole. Preto nastavíme druhý parameter na nulu:

Matrix rotace = Matrix.CreateFromYawPitchRoll(fYaw, 0, 0);

Rýchlosť pohybu je moc veľká, polovičné bude stačiť a preto zmeníme konštantu z 0,1 na 0,05:

posun *= 0.05f * (float)Parent.Engine.GameTime.ElapsedGameTime.TotalMilliseconds;

Teraz je čas zohľadniť kolízie. Máme vypočítané o koľko sa akým smerom chceme pohnúť. Rovnako ako u pokusné guličky si uložíme starú pozíciu:

Vector3 stara = koule.Center;

Vypočítame novú pozíciu guľa:

Pozice += Vector3.Transform(posun, rotace);
koule.Center = Pozice;

A ak nie je pohyb nulový tak skontrolujeme kolízie:

if (posun != Vector3.Zero && Parent is CollidableGameScreen){
  CollidableGameScreen okno = Parent as CollidableGameScreen;
  koule.Center = okno.CollisionManager.Collide(koule, stara, koule.Center);
  Pozice = koule.Center;
}

Musíme posunúť cieľ kam sa kamera pozerá. Ale tu budeme potrebovať oba dva uhly, umožníme hráči pozerať sa hore a dole. Vypočítame si znovu rotačné maticu a výpočet ciele necháme tak ako bol:

rotace = Matrix.CreateFromYawPitchRoll(fYaw, fPitch, 0);

V hernom okne potom už len zmeníte nastavenie kameru za novovytvorenú. Jej polohu a to kam sa pozerá vezmeme z načítané mapy:

Kamera = new FPSKamera(this, new Vector3(mapa.Start.X, 10f, mapa.Start.Z), new Vector3(mapa.Start.X, 10f, mapa.Start.Z));

Všimnite si, že som zvolil výšku 10. Pokusne som sa k tomuto číslu dostal a skrátka to s ním vyzeralo asi najlepšie. Pre budúce použitie sa nám síce moc hodiť nebude a to v prípade, kedy by sme chceli aplikovať gravitáciu a brať výšku z terénu. Zatiaľ to ale bude stačiť. Ak si teraz skúsite hru zapnúť a testovacie bludisko si prejsť, skôr alebo neskôr narazíte na problém. Myš sa vám dostane na koniec obrazovky a jednoducho už nemôžete zatáčať na jednu stranu. :-) To je celkom veľký problém, avšak nie je neriešiteľný. Do triedy Input, ktorá sa nám stará o klávesnicu a myš, si pridáme novú metódu CenterMouse, ktorá nám myš pekne vycentruje na stred obrazovky a nikdy sa nám už nestane, že by sa myš dostala do pozície, z ktorej by nám nešlo hru ovládať. Nie som si istý, ako presne tento problém rieši ostatné, ale podľa mňa to asi ani inak nejde. Do tejto triedy si najprv pridáme premennú pre engine, skrze nej budeme získavať veľkosť okna a budeme môcť myš vždy centrovať:

private Engine Engine;

V kontruktoru ju nastavíme:

public Input(Engine en){
  Engine = en;
}

A konečne môžeme pridať onú metódu CenterMouse, tá myš vycentruje:

public void CenterMouse(){
  Mouse.SetPosition(Engine.GraphicsDevice.PresentationParameters.BackBufferWidth / 2, Engine.GraphicsDevice.PresentationParameters.BackBufferHeight / 2);
  mysState = Mouse.GetState();
}

V konstruktoru enginu potom pridáme parameter:

fInput = new Input(this);

A máme hotovo. V našej novej kamere potom už len túto metódu zavoláme. A to ihneď po tom, čo zistíme o koľko sa myš pohla:

Parent.Engine.Input.CenterMouse();

Hotovo. Teraz už by sa malo podariť bludisko prejsť bez komplikácií. Je pravdou že kolízie nie sú optimálne a že sa občas stane že sa postava zasekne, obzvlášť keď vyberá zákrutu alebo sa snažia kĺzať po stene. Je to ale dúfam prijateľná obeť za jednoduchosť toho ako sú kolízie riešené.

3D bludisko v C# .NET XNA - 3D bludisko v XNA

To by bolo pre dnešok všetko. Nabudúce neviem čo urobíme, máme možnosť urobiť menu a hru tak doobalit do nejakého výsledného tvaru. Opäť čakám na komentáre.


 

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é 267x (1.78 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Predchádzajúci článok
3D bludisko v XNA - ČASU
Všetky články v sekcii
3D bludisko v XNA
Preskočiť článok
(neodporúčame)
3D bludisko v XNA - Vertex a index buffer
Článok pre vás napísal vodacek
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
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