C# týden November Black Friday
Black Friday je tu! Využij jedinečnou příležitost a získej až 80 % znalostí navíc zdarma! Více zde
Pouze tento týden sleva až 80 % na e-learning týkající se C#

Lekce 1 - Struktura MonoGame hry

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 MonoGame jsme si udělali úvod do MonoGame a framework jsme si nainstalovali. Dnes se podíváme na strukturu MonoGame hry a vyzkoušíme si úplné základy práce s frameworkem.

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

MonoGame jsme si již nainstalovali minule, spusťme si tedy Visual Studio a založme nový projekt MonoGame (MonoGame Cross Platform Desktop Project), který pojmenujeme Robotris:

Založení nového projektu

Pokud vám název připomněl Tetris, máte pravdu, celý kurz se bude točit okolo této hry. Postupně si vytvoříme hru, herní menu, on-line 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

MonoGame hra má svou specifickou strukturu. V novém solution nalezneme složky x64/ a x86/, které spolu s se soubory *.dylib zajišťují chod Cross-Platform, pro náš tutoriál je důležitý soubor Game1.cs, který je samotná MonoGame hra. A složka Content/ je tzv. obsah. Tak MonoGame (Původně Microsoft v XNA) nazval obrázky, zvuky a hudbu. Právě do této složky přes MonoGame Pipeline Tool je budeme přidávat.

Zaměřme 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 Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Robotris
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : 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
        /// game-specific 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)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                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ů. Zde si můžeme všimnout, že žádný MonoGame namespace vlastně není a že vše je z jmenného prostoru Microsoft.Xna.Framework. To díky postavení MonoGame na XNA frameworku a vývojáři se rozhodli zachovat původní jmenný prostor. Máme vysvětleno a teď přejděme ke třídě 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.Game.

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

  • graphics je typu GraphicsDeviceManager 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()

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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 :) MonoGame 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 Initialize() 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.

LoadContent()

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 ContentManager), 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 TargetElapsedTime, ale to nebudeme potřebovat. Důležité je vědět, že MonoGame 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 MonoGame 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 MonoGame 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 MonoGame

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


 

Stáhnout

Staženo 347x (29.14 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 sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Všechny články v sekci
Od nuly k tetrisu v MonoGame
Miniatura
Následující článek
Vložení obsahu MonoGame hry
Aktivity (5)

 

 

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

Avatar
Martin Bruna
Člen
Avatar
Martin Bruna:30.3.2013 22:20

http://stackoverflow.com/…-studio-2012
snad pomůže, oskoušeno na vs 2012 ultimate snad bude fungovat i na express

 
Odpovědět
30.3.2013 22:20
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
Mo8ilε 15 Ѐλđ
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
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
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
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
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Martin Bruna
Člen
Avatar
Martin Bruna:31.3.2013 12:18

express má soubor WDExpress.exe

 
Odpovědět
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