Válí se ti projekty v šuplíku? Dostaň je mezi lidi a získej cool tričko a body na profi IT kurzy v soutěži ITnetwork summer 2017!
Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

1. díl - Struktura XNA hry

C# .NET XNA game studio Robotris Struktura XNA hry

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V úvodním dílu o XNA jsme si udělali úvod do XNA a framework jsme si nainstalovali. Dnes se podíváme na strukturu XNA hry a vyzkoušíme si úplné základy práce s frameworkem.

Ještě jednou upozorňuji, že tento seriál se věnuje výuce frameworku XNA, nikoli výuce jazyka C#. Pokud C# neovládáte, přečtě si nejprve alespoň první 2 sekce C# tutoriálů a potom práci se soubory.

XNA Game Studio jsme si již nainstalovali minule, spusťme si tedy Visual Studio a založme nový projekt XNA Game, který pojmenujeme Robotris:

Založení nového XNA projektu

Pokud vám název připomněl Tetris, máte pravdu, celý seriál se bude točit okolo této hry. Postupně si vytvoříme hru, herní menu, online skóre tabulku a obrazovku s autory hry. Naučíte se základy práce s frameworkem a budete poté schopni vytvořit jakoukoli vlastní hru :)

Struktura projektu

XNA hra má svou specifickou strukturu. V novém solution nalezneme vlastně 2 projekty, první (Robotris) je samotná XNA hra, jejíž kód máme nyní otevřený. Druhý projekt (RobotrisContent) je tzv. obsah. Tak Microsoft nazval obrázky, zvuky a hudbu. Právě do tohoto projektu je budeme přidávat.

Zaměřmě se nejprve na třídu Game1.cs, kterou nám Visual Studio vygenerovalo a popišme si její kód, který vypadá nějak takto:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Robotris
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

Jmenné prostory

Nejprve máme deklaraci několika jmenných prostorů. Ty pro nás nejsou příliš důležité. Přejděme k tříde Game1.

Třída Game

Třídu přejmenujeme na Hra a to tak, že přemístíme kurzor na Game1 a stiskneme F2, následující dialog též potvrdíme. Vidíme, že třída dědí z Microsoft.Xna­.Framework.Ga­me.

Máme založené 2 proměnné a sice graphics a spriteBatch.

Graphics je typu GraphicsDevice­Manager a poskytuje metody např. pro změnu velikosti herního okna, přepnutí fullscreen (celoobrazovkového režimu) a podobně.

spriteBatch je instance třídy SpriteBatch, která poskytuje funkcionalitu pro práci se sprity. Máme zde nový termín - Sprite. Sprite (sprajt, sprit) je vlastně obrázek. Ten je klíčovým prvkem 2D her, přes sprity se řeší v podstatě vše od pozadí, přes postavy ve hře až po písmo, kde je každé písmeno jeden sprite. Sprity mohou být i animované.

Konstruktor a metoda Initialize

Přejděme ke konstruktoru. Zde se inicializuje proměnná graphics a také se nastaví kořenová složka pro Content. Již víme, že je to složka, ve které budou naše herní data.

Kromě konstruktoru zde máme i metodu Initialize(). To může být matoucí a také, že je :) Microsoft vlastně nijak neříká, kdy použít k inicializaci konstruktor a kdy metodu Initialize.

Rozdíl je v tom, že konstruktor se volá hned při vytvoření hry (nebo herní komponenty, o těch až později) a měl by nastavit hru nebo komponentu tak, aby byla funkční. To je u hry vždy a proto sem nic již psát nebudeme. Další význam konstruktoru je k předání závislostí, to poznáme u komponent, ze kterých se hra potom může skládat.

Metoda Inicialize() potom slouží k načtení dat, které nejsou obsah (Content, tedy nejsou sprity, zvuky nebo hudba), mohou to být např. nějaké soubory map. Také zde provedeme veškerou inicializace hry, vytvoření potřebných objektů, nastavení proměnných na výchozí hodnoty a podobně.

V initialize máme vložený řádek kódu:

base.Initialize();

Ten se stará o spuštění metody Initialize() na všech komponentách hry. O komponentách ale až později. Podobný řádek nalezneme i v dalších metodách třídy.

Load content

Dále máme ve třídě metodu LoadContent(), do té patří načítání obsahu, tedy spritů, zvuků a hudby. Vidíme, že se zde vytváří i spriteBatch. Na konec metody můžeme psát logiku, kterou potřebujeme spustit až po načtení obsahu. Např. nemůžeme v Initialize() zjistit výšku fontu, který ještě není načtený, proto by kód patřil do LoadContent.

UnloadContent se volá po skončení hry, protože my budeme vždy používat Content (což je vlastnost hry, kde je instance ContentManageru), která si uvolnění zdrojů řeší sama, není pro nás metoda důležitá.

Následují 2 nejdůležitější metody:

Update

Update() obsahuje real-time logiku, tedy vše, co se zpracovává v reálném čase. Většinou je to klávesnice, případně myš nebo jiné ovladače, potom kolize a pohyb objektů ve hře. Obecně sem patří reakce na nějaké události a posun objektů, případně jejich animace. Metoda se vykonává 60x za vteřinu. Pokud posuneme postavu v této metodě o 1, bude chodit stejně rychle i na jinak rychlém počítači. Jiný interval můžeme nastavit jako desetinné číslo menší než 1 pomocí vlastnosti hry TargetElapsed­Time, ale to nebudeme potřebovat. Důležité je vědět, že XNA za nás bude samo dělat optimalizace i když počítač nebude hru stíhat a to tak, že bude vynechávat vykreslování.

V parametru metody dostaneme instaci GameTime. Zde je uložen herní čas, nalezneme na něm 2 užitečné vlastnosti:

  • ElapsedGameTime - TimeSpan s časem uběhnutým od posledního update.
  • TotalGameTime - TimeSpan s celkovým časem běhu hry.

Díky těmto hodnotám můžeme v Update pracovat s reálným časem, udělat něco třeba každou sekundu, minutu a podobně. Vše si ukážeme během seriálu.

Další vlastnost na gameTime je IsRunningSlowly, ta je true, pokud se hra "seká" a XNA vynechává vykreslování. Můžeme tak na tuto situaci reagovat, ale my takto náročné hry zatím vytvářet nebudeme :)

V metodě je již doplněná jedna reakce na tlačítko Zpět na gamepadu, které ukončí hru. To je důležitý kód proto, aby šla hra ukončit na XBoxu, kdybychom ji tam chtěli nahrát. Mimo jiné vidíme, že ukončení hry se provede pomocí metody Exit().

Draw

Draw() se stará o vykreslení hry (jak již název napovídá). Vykreslování probíhá voláním metod na instanci SpriteBatch. Grafické zařízení musíme před každým snímkem (frame) vymazat, aby na něm nezůstaly vykreslené objekty z minula. Toho je docíleno metodou Clear a modrou barvou (na barvě vlastně nazáleží, pokud bude mít hra pozadí). Setkáváme se zde se strukturou Color, ta v XNA slouží k ukládání barev. Má na sobě několik statických metod, které navrátí její instanci nastavenou na určitou barvu.

Herní smyčka

Je důležité vědět, jak uvnitř hra pracuje. Herní metody se volají v tzv. herní smyčce a to v tomto pořadí:

  1. Initialize
  2. LoadContent
  3. Update
  4. Draw
  5. UnloadContent

Update a Draw se stále opakují, dokud není hra ukončena. Cyklus znázorněný pomocí vývojového diagramu by vypadal takto:

Herní smyčka v XNA

Příště si do projektu vložíme sprity, fonty, zvuky a hudbu, půjde tedy o vložení obsahu :)


 

Stáhnout

Staženo 336x (28.44 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
10 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Miniatura
Všechny články v sekci
Od nuly k tetrisu v XNA game studio
Miniatura
Následující článek
Vložení obsahu XNA hry
Aktivity (1)

 

 

Komentáře
Zobrazit starší komentáře (11)

Avatar
Michal Žůrek (misaz):30.3.2013 22:20

Hloupost, mě na 12tkách jede, jenomžé já nemám expres.

Odpovědět 30.3.2013 22:20
Nesnáším {}, proto se jim vyhýbám.
Avatar
Theodor Johnson
Redaktor
Avatar
Theodor Johnson:31.3.2013 9:35

Martin Bruna Express neobsahuje soubor devenv.exe

Michal Žůrek (misaz) neříkal jsem že nejde vůbec ve 2012kách, ale v expressu asi nepůjde

Odpovědět 31.3.2013 9:35
Přecházím na "Cross-Platform Development"
Avatar
Odpovídá na Theodor Johnson
Michal Žůrek (misaz):31.3.2013 10:22

Express neobsahuje soubor devenv.exe
Místo toho tam je jiný soubor. Devenv.exe je samotná aplikace visual studia.

Odpovědět 31.3.2013 10:22
Nesnáším {}, proto se jim vyhýbám.
Avatar
magic44
Redaktor
Avatar
magic44:31.3.2013 10:46

Díky. A jakej soubor maj Express místo devenv.exe?

Odpovědět 31.3.2013 10:46
Moudrý člověk nechce být lepší než ostatní, ale lepší, než byl sám včera.
Avatar
Odpovídá na magic44
Michal Žůrek (misaz):31.3.2013 11:13

Nevím, otevři si program files, měla by tam být složka Visual Studio 12\Common7\IDE a tam někde hledej exe soubor s ikonou visual studia express. Druhá variante je že se mrkneš do vlastností zástupce, ze kterého visual studio express spouštíš, tam ta cesta taky je.

Odpovědět 31.3.2013 11:13
Nesnáším {}, proto se jim vyhýbám.
Avatar
magic44
Redaktor
Avatar
magic44:31.3.2013 11:30

Nasel jsem dva exe s ikonou visual studia, ale stejne to nefunguje. Asi to na Express nejde.

Odpovědět 31.3.2013 11:30
Moudrý člověk nechce být lepší než ostatní, ale lepší, než byl sám včera.
Avatar
magic44
Redaktor
Avatar
magic44:31.3.2013 11:30

Nasel jsem dva exe s ikonou visual studia, ale stejne to nefunguje.

Odpovědět 31.3.2013 11:30
Moudrý člověk nechce být lepší než ostatní, ale lepší, než byl sám včera.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na magic44
David Čápka:31.3.2013 11:36

Stahni si VS 2010 a nemusíš nic řešit.

Odpovědět 31.3.2013 11:36
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Martin Bruna
Člen
Avatar
Martin Bruna:31.3.2013 12:18

express má soubor WDExpress.exe

 
Odpovědět  +1 31.3.2013 12:18
Avatar
Ondřej Pohořelý:18.6.2016 17:57

Ahoj mám VS 2013 a xna 3.5 bohužel se mi nevytváří "obsah" nevíte co s tím ?

Odpovědět 18.6.2016 17:57
Nezastavuj se dlouho protože život nikdy nečeká !
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 21. Zobrazit vše