Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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 12 - 3D bludiště v XNA - Hráčská kamera

Vítejte po dva-a-dvacáté. V předchozí lekci, 3D bludiště v XNA - Časujeme, jsme si přidali časomíru.

V tomto díle si pokusnou kuličku nahradíme kamerou a poprvé si tedy vyzkoušíme bludiště projít jako hráči, tedy z pohledu 1. osoby.

Hráčská kamera

Jako kameru pro hráče nemůžeme použít tu co máme nyní. Naše kamera nerespektuje kolize a navíc s ní lze létat nahoru a dolů. Vytvoříme si tedy kameru novou, do složky na kamery si přidáme nový soubor s třídou FPSKamera. Dědit budeme od TargetKamery, stejně jako v případě volné kamery. Potřeba budou dvě proměnné pro natočení kamery, nic nového pod sluncem:

float fYaw, fPitch;

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

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

Novinkou je naopak kolizní koule.

BoundingSphere koule;

Kterou si v konstruktoru spolu s ostatními proměnnými nastavíme:

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

  koule = new BoundingSphere(pozice, 5);
}

Pozice středu koule je stejná jako pozice kamery a poloměr koule je pět jednotek. Jen připomenu, že velikost kostek jsme si zvolili na 20 jednotek, takže je kolem koule dostatek místa pro pohyb. Máme vše připraveno až na to, že kamera je zatím statická. Vezmeme si metodu Update z volné kamery a tu si jen mírně upravíme. Takže jen pro úplnost jak metoda vypadá:

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();
}

První věc, kterou musíme napravit, je rotační matice. Nechceme, aby bylo možné stoupat s kamerou nahoru a dolů. Proto nastavíme druhý parametr na nulu:

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

Rychlost pohybu je moc velká, poloviční bude stačit a proto změníme konstantu z 0,1 na 0,05:

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

Nyní je čas zohlednit kolize. Máme vypočteno o kolik se jakým směrem chceme pohnout. Stejně jako u pokusné kuličky si uložíme starou pozici:

Vector3 stara = koule.Center;

Vypočteme novou pozici koule:

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

A pokud není pohyb nulový tak zkontrolujeme kolize:

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 posunout cíl kam se kamera dívá. Ale zde budeme potřebovat oba dva úhly, umožníme hráči dívat se nahoru a dolů. Vypočteme si znovu rotační matici a výpočet cíle necháme tak jak byl:

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

V herním okně pak už jen přenastavíme kameru za nově vytvořenou. Její polohu a to kam se dívá vezmeme z načtené mapy:

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

Povšimněte si, že jsem zvolil výšku 10. Pokusně jsem se k tomuto číslu dostal a zkrátka to s ním vypadalo asi nejlépe. Pro budoucí použití se nám sice moc hodit nebude a to v případě, kdy bychom chtěli aplikovat gravitaci a brát výšku z terénu. Prozatím to ale bude stačit. Pokud si nyní zkusíte hru zapnout a testovací bludiště si projít, dříve nebo později narazíte na problém. Myš se vám dostane na konec obrazovky a jednoduše už nemůžete zatáčet na jednu stranu. :-) To je celkem velký problém, avšak není neřešitelný. Do třídy Input, která se nám stará o klávesnici a myš, si přidáme novou metodu CenterMouse, která nám myš pěkně vycentruje na střed obrazovky a nikdy se nám už nestane, že by se myš dostala do pozice, ze které by nám nešlo hru ovládat. Nejsem si jist, jak přesně tento problém řeší ostatní, ale podle mě to asi ani jinak nejde. Do této třídy si předně přidáme proměnnou pro engine, skrze ní budeme získávat velikost okna a budeme moci myš vždy centrovat:

private Engine Engine;

V kontruktoru ji nastavíme:

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

A konečně můžeme přidat onu metodu CenterMouse, ta myš vycentruje:

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

V konstruktoru enginu pak přidáme parametr:

fInput = new Input(this);

A máme hotovo. V naší nové kameře pak už jen tuto metodu zavoláme. A to ihned po tom, co zjistíme o kolik se myš pohnula:

Parent.Engine.Input.CenterMouse();

Hotovo. Nyní už by se mělo povést bludiště projít bez komplikací. Je pravdou že kolize nejsou optimální a že se občas stane že se postava zasekne, obzvláště když vybírá zatáčku nebo se snaží klouzat po zdi. Je to ale doufám přijatelná oběť za jednoduchost toho jak jsou kolize řešeny.

3D bludiště v C# .NET XNA - 3D bludiště v XNA

To by bylo pro dnešek vše.

Příště, 3D bludiště v XNA - Vertex a index buffer, se mrkneme na problematiku index a vertex bufferů. Opět čekám na komentáře.


 

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 267x (1.78 MB)
Aplikace je včetně zdrojových kódů v jazyce C# XNA

 

Předchozí článek
3D bludiště v XNA - Časujeme
Všechny články v sekci
3D bludiště v XNA
Přeskočit článek
(nedoporučujeme)
3D bludiště v XNA - Vertex a index buffer
Článek pro vás napsal vodacek
Avatar
Uživatelské hodnocení:
3 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