Slevový týden - Březen C# týden
Využij náš slevový týden a získej až 30 % bodů navíc zdarma! Zároveň také probíhá C# týden se slevou na e-learning až 80 %
Hledáme fulltime programátora do ITnetwork týmu -100% homeoffice, 100% časově flexibilní #bezdeadlinu Mám zájem!

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
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!

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

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

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.


 

Stiahnuť

Stiahnuté 524x (11.85 MB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

 

Článok pre vás napísal David Čápka
Avatar
Ako sa ti páči článok?
Ešte nikto nehodnotil, buď prvý!
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 sa informačné technológie naučil na Unicorn College - prestížnej súkromnej vysokej škole IT a ekonómie.
Predchádzajúci článok
Vloženie obsahu MonoGame hry
Všetky články v sekcii
Od nuly k tetrisu v MonoGame
Miniatúra
Nasledujúci článok
Zvuky, hudba, klávesnica a myš v MonoGame
Aktivity (1)

 

 

Komentáre

Avatar
anticary
Člen
Avatar
anticary:11.3.2014 17:01

Už to vím. :)

 
Odpovedať
11.3.2014 17:01
Avatar
petr.vidrman
Člen
Avatar
petr.vidrman:28.5.2014 21:15

Nevleze se to na obrazovku mobilu :(
Vidím jen půlku obrazovky. Měním šířku na šířku mobilu
graphics.Prefe­rredBackBuffer­Width = 320;
graphics.Prefe­rredBackBuffer­Height = 480;

Zkouším změnu orientace obrazu
// Allow portrait mode as well
graphics.Suppor­tedOrientations = DisplayOrienta­tion.Portrait |
DisplayOrienta­tion.Landscape­Left |
DisplayOrienta­tion.Landscape­Right;

a stejně to nepomáhá...

V čem je problém...?

Editované 28.5.2014 21:18
 
Odpovedať
28.5.2014 21:15
Avatar
CallMany Vyhlídal:18.8.2015 11:44

ahoj potřeboval bych poradit jenom když si zkopíruju tohle

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

Tak mi to normálně funguje .. Ale když si to prostě jen opíšu a nezkopíruju tak mi to vykreslí pouze jeden mrak :/

 
Odpovedať
18.8.2015 11:44
Avatar
CallMany Vyhlídal:18.8.2015 11:54

https://ctrlv.cz/PPd0 - opsané
https://ctrlv.cz/v7TI - okopírované

 
Odpovedať
18.8.2015 11:54
Avatar
Pjanus
Člen
Avatar
Odpovedá na CallMany Vyhlídal
Pjanus:18.8.2015 12:35

V okopírovaném je pozice.X + i zatím co v opsaným máš pozice.X + 1

 
Odpovedať
18.8.2015 12:35
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
Odpovedá na Pjanus
CallMany Vyhlídal:18.8.2015 13:03

Ajo :D Já jsem blbec díky moc ^^

 
Odpovedať
18.8.2015 13:03
Avatar
Vojta
Člen
Avatar
Vojta:23.7.2017 17:11

Měl jsem stejný problém, spočíval v tom, že moje png obrázky nebyly "included in project". Stačilo v Solution exploreru na ně kliknout pravým tlačítkem a následně include in project.

 
Odpovedať
23.7.2017 17:11
Avatar
Patrik Pastor:20.6.2019 20:32

co je ta trida Vektor2? dival jsem se do dokumentace a nasel jsem jenom ze to je pro hardwarovou akceleraci, ale uplne nevim co to je. A za druhe, ten vector jde v tom vykreslovani (metoda Draw()) misto Rectangle, tedy vektor asi ten obdelnik vykresli (to bych ocekaval, kdyz bere 2 parametry - x,y), ale tyto parametry jsou nastavene na nulu... takze to stejne zadny obdelnik nevykresli. Jaky to ma teda smysl? Diky za odpoved.

 
Odpovedať
20.6.2019 20:32
Avatar
Odpovedá na Patrik Pastor
Patrik Pastor:20.6.2019 20:43

Spise bych upravil svuj dotaz jeste kvuli vykresleni... png mraky se vykreslilo mezi pozadiKostky a kostky, coz souhlasi (jak je napsano, poradi draw() jsou mraky presne mezi deklaraci), nicmene vsechny vydkresleni draw() maji vektor nastaveny na x=0,y=0 takze jak je mozne ze je pozadiKostky je vykresleno v PRAVEM rohu a mraky v LEVEM? kdyz oba maji nastavene stejne souradnice vektoru?

 
Odpovedať
20.6.2019 20:43
Avatar
Patrik Pastor:20.6.2019 21:49

Mam dotaz ohledne xml u fontu courierNew. Jelikoz ve hre nejde moc tento popis videt, chtel jsem zmenit v xml uzel <Style></Style>, a dovnitr jsem misto Regular napsal Bold. Ulozil jsem a vypnul. Zapnul znovu, ale styl se nezmenil, ackoliv kdyz se znovu divam do zml souboru, je nakonfigurovan dobre, a bold hodnota tam opravdu je. Ale v aplikaci, nikde.... Nevite proc?

 
Odpovedať
20.6.2019 21:49
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!