V dnešním díle seriálu se podíváme na Content Pipeline, hře vytvoříme pozadí, napíšeme třídu základního herního objektu a na závěr vám povím něco o vektorech.
Vítejte zpět u seriálu o tvorbě 2D hry v XNA Game Studiu. Dnes do hry přidáme pozadí a třídu základního herního objektu.
Přidání obsahu
Jak jsem psal v minulém díle, seriál bude z větší části založen na videotutoriálu z creators.xna.com, takže i obsah bude odtud, jsem totiž výtvarný antitalent. Potřebné soubory naleznete zde. Soubory nakopírujte do složky Content přes Solution Explorer.
Content Pipeline
XNA s sebou přineslo zajímavou novinku, a tou je Content Pipeline. Je to rozhraní pro načítání a práci s herním obsahem (textury, shadery, modely, …). Při kompilaci se všechen obsah složky Content zkonvertuje do formátu xnb a přidá do Content Pipeline. Je to především kvůli Xbox 360, který neumí pracovat se soubory tak, jako Windows a pomocí Content Pipeline mu to usnadníme.
Pozadí
Pozadí bude první věc, co si dnes naprogramujeme, nic těžkého.
Viewport rectangle
Ze všeho nejdřív si vytvoříme viewport rectangle. Viewport rect. je obdélník s velikostí plochy, na které se promítá hra. Díky němu můžeme umísťovat objekty na relativní pozici, roztahovat sprity na celou plochu (pozadí) nebo kontrolovat, zda je nějaký bod mimo "obrazovku".
Pro jeho implementaci ve hře, deklarujeme v třídě Game1 nový statický člen viewportRect typu Rectangle a v metodě LoadContent jej nastavíme na velikost viewportu.
viewportRect = new Rectangle(0,0,
graphics.GraphicsDevice.Viewport.Width,
graphics.GraphicsDevice.Viewport.Height);
Načtení pozadí
Ve třídě Game1
deklarujeme proměnnou background typu Texture2D
.
private Texture2D background;
A v metodě LoadContent do ní načteme texturu pozadí.
background = Content.Load<Texture2D>("Sprites\\background");
Pokud jste se ještě nesetkali s lomenými závorkami, tak vám povím, že metoda Load
je generická, generika je způsob, jak se zbavit boxingu a unboxingu. Generika umožňuje pracovat s objekty, o kterých nevíme, jakého typu jsou. Známý příklad je generická třída List.
Za názvy načítaných souborů nemusíte psát žádnou příponu, stejně to bude mít po kompilaci všechno příponu xnb.
Vykreslení pozadí
K vykreslování spritů používáme objekt spriteBatch
. Všechny prvky, které chceme zobrazit, musíme vykreslit mezi voláním metod spriteBatch.Begin
a spriteBatch.End
. Příprava grafického zařízení pro vykreslení spritu totiž chvíli trvá a když vykreslíme několik spritů najednou, ušetříme tím mnoho času. K vykreslení samotných spritů se používá metoda spriteBatch.Draw
.
Do metody Draw
si přidejte tento kód:
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
spriteBatch.Draw(background, viewportRect, Color.White);
spriteBatch.End();
Metodu spriteBatch.Begin
voláme s parametrem SpriteBlendMode.AlphaBlend
. Tento parametr nám umožní použít alpha blending. Metodě spriteBatch.Draw
předáváme sprite, viewport a barvu osvětlení, bílá nechá sprite takový, jaký je.
Základní objekt
Podstatou naší hry bude sestřelování létajících těles pomocí viditelných střel z objektu, který nemění pozici, jen rotuje. Pro tyto účely nám bude stačit jednoduchá třída GameObject
která ponese informace o spritu, pozici, rotaci a středu a třídy z ní dědící. Zde jsem využil jiný postup, než použil autor videotutoriálu, tento způsob se mi zdá lepší (přehlednější, jasnější).
Pro větší přehlednost si vytvořte nový soubor a pojmenujte ho GameObjects.cs
. Následně do něj nakopírujte tento kód:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Hra
{
class GameObject
{
protected Texture2D sprite;
protected Vector2 position;
protected Vector2 center;
protected float rotation;
}
}
Sprite
je textura, position
obsahuje souřadnice pozice objektu a center
souřadnice jeho středu (X = polovina šířky spritu, Y = polovina výšky spritu). Dále budeme potřebovat nějaký konstruktor.
public GameObject(Texture2D loadedTexture)
{
sprite = loadedTexture;
position = Vector2.Zero;
center = new Vector2(sprite.Width / 2.0f, sprite.Height / 2.0f);
}
A nakonec přidáme metodu Draw, ta bude vždy stejná.
public virtual void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(sprite, position, null, Color.White, rotation, center, 1.0f, SpriteEffects.None, 0);
}
Jen kvůli tomu, že jsme chtěli předat metodě rotaci objektu, musíme použít nejukecanější verzi spriteBatch.Draw
. Pojďme si shrnout význam jejich parametrů.
- sprite – textura spritu
- position – pozice spritu ve viewportu
- rectangle – obdélník (viewport), v rámci kterého se má sprite vykreslovat; my nevyplníme nic, je to zbytečné, když používáme celé okno
- color – barva osvětlení. Pokud zvolíme bílou, bude sprite vykreslen beze změny, když zvolíme zelenou, bude mít sprite zelený nádech.
- rotation – rotace spritu
- origin – bod otáčení, v našem případě střed
- scale – násobek původní velikosti spritu. Pokud chcete sprite vykreslit zvětšený či zmenšený, je tento parametr ten pravý.
- effects – efekt použitý při vykreslování. Vypadá to zajímavě, ale za atraktivním názvem se skrývá pouze horizontální či vertikální převrácení.
- layerDepth – vrstva, ve které je objekt umístěn (0 – front, 1 – back)
Metoda Draw
přijímá referenci spriteBatch. Budeme ji totiž volat v metodě Draw
třídy Game1
a pokud chceme, aby naše metod mohla vykreslovat, musíme jí SpriteBatch
předat. Je to nejjednodušší způsob. Metodu budeme také překrývat, proto klíčové slovo virtual
.
A tímto máme naši třídu kompletní, další třídy herních objektů budeme odvozovat od této.
Vector
Vector2, Vector3 a Vector4 jsou další z věcí, které nám XNA Framework přichystal, abychom je nemuseli psát sami. Vektory jsou totiž součást téměř každé hry, velice usnadňují práci. Prostě místo toho, abyste museli psát ChangePosition(float positionX, float positionY)
, napíšete ChangePosition(Vector2 position)
. Číslo za názvem Vector značí počet rozměrů. Vektory v XNA jsou struktury, takže se nacházejí v bufferu, což s sebou taktéž nese jisté výhody (oproti třídě). Navíc obsahují některé užitečné metody a díky přetíženým operátorům můžete vectory jednoduše sčítat, odečítat, násobit, porovnávat,… Jako bonus nabízí vektory v XNA již předdefinované vektory, např. Vector2.Zero
.
Závěr
Dnešní díl je u konce, v příštím vytvoříme herní objekty.