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í.

3. diel - Kreslíme a píšeme v MonoGame

V minulej lekcii, Vloženie obsahu MonoGame hry , sme si ukázali vloženie obsahu MonoGame hry. Teraz máme teda všetko pripravené na to, aby sme si prácu s obsahom vyskúšali. Poďme na to :)

Načítanie obsahu

Obsah musíme najprv načítať. Už vieme, že to sa robí v metóde LoadContent(). Než sa k metóde presunieme, vytvoríme si potrebné premenné. Neanimované sprity sa v MonoGame ukladajú do dátového typu Texture2D. Pre SpriteFonty máme typ SpriteFont.

Pridáme teda premenné:

private Texture2D kostkyPozadi, mraky, pozadi;
public SpriteFont fontCourierNew, fontBlox, fontBloxMaly;

S modifikátory prístupu si nelámte hlavu, hudba a fonty sú verejné, pretože ich budeme v budúcnosti zdieľať medzi komponentmi.

Presuňme sa konečne do metódy LoadContent(). Za vytvorením inštancie spriteBatch začneme načítať obsah. Už vieme, že na to použijeme vlastnosť Content, presnejšie Load(). Metóda je generická, musíme teda špecifikovať typ obsahu, ktorý načítame. Zaujímavé je, že nezadávame príponu súboru. Načítame sprity:

pozadi = Content.Load<Texture2D>(@"Sprity\pozadi_level");
kostkyPozadi = Content.Load<Texture2D>(@"Sprity\pozadi_kostky");
mraky = Content.Load<Texture2D>(@"Sprity\spr_mraky");

A fonty:

fontCourierNew = Content.Load<SpriteFont>(@"Fonty\font_courier_new");
fontBlox = Content.Load<SpriteFont>(@"Fonty\font_blox");
fontBloxMaly = Content.Load<SpriteFont>(@"Fonty\font_blox_maly");

Máme načítané, nebola to žiadna veda. Poďme kresliť.

Vykresľovanie spritov

Presuňme sa do metódy Draw. Kód budeme písať za vymazanie zobrazovacieho zariadenia. Už sme si hovorili, že vykresľovanie sprites prebieha pomocou inštancie spriteBatch. Vykresľovanie musíme najprv začať, to urobíme metódou Begin():

spriteBatch.Begin();

Následne vykreslíme sprity. Iste ste si všimli, že sú vo formáte PNG. To preto, že PNG obsahuje tzv. Alfakanál a umožňuje urobiť rôzne časti obrázku rôzne priehľadné. Toho som využil a pozadie levelu s robotom je hore priehľadné. Pod neho vykreslíme pozadia kociek a medzi kocky a robota vykreslíme mraky.

Samotné vykreslenie Spritu prebieha pomocou metódy Draw():

spriteBatch.Draw(kostkyPozadi, new Vector2(0, 0), Color.White);
spriteBatch.Draw(mraky, new Vector2(0, 0), Color.White);
spriteBatch.Draw(pozadi, new Vector2(0, 0), Color.White);

Vidíme, že prvý parameter metódy je textúra k vykreslenie. Druhým parametrom je pozícia a tretím farba. Metóda má ďalšie preťaženie, ktoré umožňujú napr. Obrázok rozťahovať alebo rotovať, ale tá v našom kurze nevyužijeme.

Význam textúry je jasný. Pozoruhodné môže byť, že súradnice zadávame pomocou vektora. Ešte divnejšie môže byť, že to nie sú celé čísla, ale čísla desatinné, presnejšie typu float. S vektory sa v XNA pracuje preto, že umožňujú veľmi jednoducho riešiť rôzne pohyby, smery, uhly, zrážky, zistiť vzdialenosť 2 objektov a podobne. My je v tomto seriáli budeme používať len ako súradnice, ale aj tu je výhoda, že môžeme objektu napr. Zadať reálnu rýchlosť pohybu miesto celočíselné a túto rýchlosť ku zložkám vektora (súradniciam objektu) pričítať. Farba určuje zafarbenie textúry, biela textúru nemení.

Vykresľovanie nakoniec ukončíme metódou End():

spriteBatch.End();

Skúsime si hru spustiť, mali by sme vidieť takýto výsledok:

Robotris, ukážková hra v XNA Game Studio - Od nuly k tetrisu v MonoGame

Vďaka dodržanie poradie spritov pri vykreslenie sú naozaj mraky vložené medzi 2 pozadia. Ešte u spritov chvíľku zostaneme, skúsime si totiž mraky rozpohybovať. Založíme si novú privátne premennú pozice typu Vector2. V Initialize() ju nastavíme na počiatok súradnicového systému (ľavý horný roh obrazovky):

pozice = new Vector2(0, 0);

Teraz zmeníme riadok s vykreslením mrakov. Ako pozíciu odovzdáme premennú pozície a farbu vynásobíme 0.8f, tým spôsobíme, že mraky budú z 20% priehľadnej:

spriteBatch.Draw(mraky, pozice, Color.White * 0.8f);

Teraz sa mraky vykresľujú na pozíciu, ktorú určuje premenná. V metóde Update() zložku vektora X vždy o 1 znížime:

pozice.X--;

Po posune ošetríme, či sme s mrakmi nevyšli z obrazovky. To urobíme tak, že sa spýtame, či je X mrakov menšia ako -šírka obrázku mrakov. Tú získame pomocou vlastnosti Width na textúre mrakov:

if (pozice.X < -(mraky.Width))
    pozice.X = 0;

Ak ste postupovali správne, budú mraky jazdiť doľava a akonáhle vyjdú z obrazovky, vráti sa na štartovaciu pozíciu.

Teraz zmeníme vykresľovanie tak, aby sa vykresľovali niekoľko mrakov vedľa seba:

for (int i = 0; i < 6; i++)
     spriteBatch.Draw(mraky, new Vector2(pozice.X + i * mraky.Width, 0), Color.White * 0.8f);

Dostaneme pekný efekt nekonečné, plaviace oblohy:

Robotris, ukážková hra v XNA Game Studio - Od nuly k tetrisu v MonoGame

Pôsobivé, že? :)

Zmena farby spritov

Ešte si skúsime meniť farbu mrakov. Budeme jednoducho meniť jej jednotlivé zložky, určite vieme, že farby v počítači sú zložené z červenej, zelenej a modrej zložky. Urobiť zmenu farby tak, aby sme vystriedali celé spektrum je zložité a efekt bude veľmi podobný tomu, keď budeme striedať farieb len niekoľko. Do triedy pridáme 2 ďalšie premenné, zmenu a smer:

private int zmena;
private int smer;

Premenná zmena sa bude meniť medzi hodnotou 0 - 96, ako kyvadlo. Premenná smer určuje smer zmeny tejto premennej, 1 rastúci, -1 klesajúci.

V Initialize() nastavíme zmenu na 0 a smer na 1, teda rastúce.

zmena = 0;
smer = 1;

V Update() teraz pripočítame smer k zmene. Tým docielime, že sa bude s kladným smerom zvyšovať a so záporným znižovať. Tiež zmenu pomocou 2 podmienok udržíme medzi 0 a 96:

zmena += smer;
if (zmena >= 96)
    smer = -1;
if (zmena <= 0)
    smer = 1;

Hotovo. Tento kyvadlový princíp si zapamätajte, bude sa nám v hrách hodiť, my ho ešte minimálne 2x použijeme inde. No a poďme do metódy Draw(). Tam si pred for cyklom založíme premennú barva a zmeníme jej zložky pomocou premennej zmena, tie môžeme zadať jednoducho v poradí RGB (červená, zelená, modrá) do konstruktoru farby. Potom farbu dosadíme do farby vykreslenie Mařák:

Color barva = new Color(128 + zmena, 255 - zmena, 128 + zmena);
for (int i = 0; i < 6; i++)
    spriteBatch.Draw(mraky, new Vector2(pozice.X + i * mraky.Width, 0), barva * 0.8f);

Červená zložka bude mať základ 128 + zmena, bude sa teda meniť medzi 128 - 224. Zelená medzi 255 - 159 a modrá opäť 128 - 225. Môžete si s tým pohrať, ale pozor, aby hodnota nebola vyššia ako 255 alebo nižšia ako 0. Program by nespadol s chybou, ale farba by sa menila podivne.

Pre lepší efekt by sme si v praxi uložili niekoľko pekných farieb do poľa a potom na ne prechádzali metódou Lerp(). Mraky by tiež nemali byť modré, aby to do farby nezasahovala. Pre naše účely ukážky nám to však takto stačí.

Vykreslenie textu

Vieme, že aj text vykresľujú pomocou SpriteBatch, presnejšie metódou DrawString(). Tá má opäť niekoľko preťaženie pre text orotovaný a podobne, ale tá si určite sami obhliadnete. Presuňme sa do metódy Draw() a pridajme pred spriteBatch.End(); nasledujúce riadky:

spriteBatch.DrawString(fontBlox, "nadpis velky", new Vector2(100, 100), Color.Yellow);
spriteBatch.DrawString(fontBloxMaly, "nadpis maly", new Vector2(100, 180), Color.Yellow);
spriteBatch.DrawString(fontCourierNew, "Příliš žluťoučký kůň úpěl ďábelské ódy", new Vector2(100, 240), Color.Red);

výsledok:

Robotris, ukážková hra v XNA Game Studio - Od nuly k tetrisu v MonoGame

Parametre sú rovnaké, ako u sprites, iba je tu jeden navyše s textom. Nezabúdajte, že font Blox nevie slovenské znaky! Vo fontu Courier je to už v poriadku.

Text môže byť občas zle vidieť, pokúsime sa s tým niečo urobiť, vykreslíme pod neho tieň. Aby sme nemuseli tieň kresliť stále znovu a znovu, urobíme si na text s tieňom metódu. No a aby sme sa precvičili, pridáme ju priamo do spriteBatch, presnejšie SpriteBatch podědíme.

Pridajte si k projektu Robotris novú triedu s názvom LepsiSpriteBatch, dedičov z SpriteBatch. Najprv hore pridáme potrebné using ya triedu opatríme modifikátorom public:

...
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Robotris
{
    public class LepsiSpriteBatch : SpriteBatch
    {

...

Pri dedení triedy musíme vytvoriť konštruktor (hoci prázdny), volajúci konštruktor triedy nadradenej:

public LepsiSpriteBatch(GraphicsDevice graphicsDevice): base(graphicsDevice)
{
}

Teraz pridáme našu metódu TextSeStinem(), ktorá vykreslí zadaný text 2x. raz čierno s trochou transparentnosti a kúsok doprava dole a druhýkrát normálne, ako sme zvyknutí. Parametre opíšeme z pôvodnej metódy DrawString().

public void TextSeStinem(SpriteFont spriteFont, string text, Vector2 position, Color color)
{
    DrawString(spriteFont, text, new Vector2(position.X + 2, position.Y + 2), Color.Black * 0.8f);
    DrawString(spriteFont, text, position, color);
}

Teraz sa vrátime do triedy Hra a zmeníme typ SpriteBatch (hneď na začiatku v definícii atribútov triedy) na LepsiSpriteBatch:

LepsiSpriteBatch spriteBatch;

Podobnú zmenu urobíme ešte na začiatku metódy LoadContent():

spriteBatch = new LepsiSpriteBatch(GraphicsDevice);

V metóde Draw() zmeníme DrawString() na TextSeStinem() a spustíme. Oveľa lepšie, nie?

Metódy v hre sú trochu českoanglické, ale v programovaní to inak nejde a aspoň trochu češtiny som hre chcel dodať, keď už robím českej tutoriály :) Tí pokročilí z vás si to môžu písať anglicky.

To by nám ku spritům stačilo.

Nabudúce, v lekcii Zvuky, hudba, klávesnica a myš v MonoGame , sa pozrieme na hudbu, zvukové efekty a reakciu na klávesy.


 

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

 

Predchádzajúci článok
Vloženie obsahu MonoGame hry
Všetky články v sekcii
Od nuly k tetrisu v MonoGame
Preskočiť článok
(neodporúčame)
Zvuky, hudba, klávesnica a myš v MonoGame
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity