IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

1. diel - Hra JellyBox v MonoGame - Vykreslenie hracej plochy a hráča

V nasledujúcej sérii tutoriálu si urobíme hru, ktorú som nazval JellyBox a budete v nej ako multi-želé musieť chytať padajúce želé kocky. Nebude to tak jednoduché ako to znie.

Hru píšem v MonoGame, ale prakticky nijako sa to nelíši od XNA, takže ak nemáte MonoGame po ruke, tak môžete pokojne siahnuť po XNA a všetko bude fungovať ako má.

Najprv si založíme nový projekt vo Visual Studiu, ja som zvovil MonoGame Windows OpenGL Project. Vygeneruje sa nám projekt a môžeme začať tvoriť.

Textúry

V dnešnom diele budeme potrebovať iba 3 textúry a to textúru pozadia, hráča a krajiny po ktorej sa bude náš hráč pohybovať.

Textúry si nahráme do zložky Content, ktorá sa nám v projekte vygenerovala a odkiaľ je tiež bude nahrávať.

zem - Hra JellyBox v MonoGame
pozadie - Hra JellyBox v MonoGame
hráč - Hra JellyBox v MonoGame

Vykreslenie pozadia a krajiny

Teraz si v triede Game1 vytvoríme 2 inštancie triedy Texture2D pre naše pozadie a zem. Kód bude vyzerať nasledovne.

private Texture2D ground, background;

Ich inicializácii si zaistíme v metóde LoadContent, kde do nich nahráme naše textúry.

ground = Content.Load<Texture2D>("ground");
background = Content.Load<Texture2D>("Background");

Je tu výhoda, že za názvami súborov nemusíte písať ich koncovky ako napr. Background.png Týmto by sme mali naše textúry pripravené na vykreslenie, ale ako sa k tomu dostaneme, tak si najprv upravíme veľkosť hracieho okna a pridám nejaké pomocné metódy.

Zmeníme si veľkosť hracieho okna a to v konstruktoru Game1. Nastavenie vykonáme vďaka tunajšiemu GraphicDevice­Manageru. Na jeho inštanciu je dostupná celá rada šikovných nastavenia obrazu, ale my tu využijeme iba PreferredBackBuf­ferHeight a Width, čím nastavíme výšku a šírku obrazu.

Ja som zvolil 800x600, pretože používam notebook a nemám veľký display, ale môžete si vybrať ľubovoľnú veľkosť.

graphics.PreferredBackBufferHeight = 600;
graphics.PreferredBackBufferWidth = 800;

Teraz si pridáme 2 metódy, ktoré nám budú poskytovať užitočné informácie. Prvé metódou bude GetSreenSize, ktorá nám bude vracať 2-zložkový vektor zložený z šírky a výšky herného okna. Druhá metóda bude GetGroundRect, ktorá nám bude vracať rectangle našej krajiny, čo využijeme pri testovaní kolízií.

public Vector2 GetScreenSize()
{
     return new Vector2(graphics.PreferredBackBufferWidth,
          graphics.PreferredBackBufferHeight);
}

public Rectangle GetGroundRect()
{
     return new Rectangle(0, (int)ScreenSize().Y - 150, (int)ground.Width,
          (int)ground.Height);
}

Je dobré myslieť pri písaní hry trochu dopredu a nejaké veci, ako sú tieto užitočné metódy využívať, ušetríte tým potom veľa zbytočných riadkov kódu.

Teraz, keď už sme si všetko pripravili, tak sa môžeme vrhnúť na samotnej vykreslenie pozadia a krajiny. Pri vykresľovanie je nutné pamätať na to, že sa vykresľuje po "vrstvách", takže záleží na poradí s ktorým vykresľuje. Tým je jasné že pozadie bude vždy v poradí ako prvý, pretože je nežiaduce, aby bolo niečo vykreslené za pozadím a tým pádom skryté.

spriteBatch.Begin();

spriteBatch.Draw(background, new Vector2(0, 0), Color.White);
spriteBatch.Draw(ground, GetGroundRect(), Color.White);

spriteBatch.End();

Tu je hneď vidieť využitie jednej z našich metód. Použili sme ju tu na určenie pozície, kde sa má textúra vykresliť. Teraz keď si hru zapneme, tak môžeme vidieť krásne pozadie a na spodku obrazovky našu zem. Ale to by toho bolo málo, tak tam ešte pridáme našu postavu.

Vykreslenie hráča

Než sa pustíme do vykreslí hráča, tak bude potrebné vytvoriť 2 triedy a to triedu Player, kde bude umiestnená logika hráča a triedu GameObejct, ktorá bude základným kameňom všetkých našich objektov v hre. Bude poskytovať určité základné metódy, ktoré budú všetky objekty zdieľať, ale sami uvidíte, že objektových návrh a pekné rozdelenie do tried len spríjemňuje programovania a redukuje počet nepotrebných riadkov v kóde.

Triedy GameObject a Player

V triede GameObject si inštanciu triedy Texture2D a inštanciu triedy Vector2. Pomenujeme si ich texture a position. Tieto 2 premenné je potrebné nastaviť na protected, pretože budeme z tejto triedy dediť.

V triede bude hneď niekoľko metód. Prvá metóda je GetPosition, ktorá nám vracia pozíciu objektu. Druhou metódou je GetTexture, ktorá nám vráti textúru objektu. Tretia metódou je GetRectangle, ktorá nám vráti rectangle objektu, čo sa veľmi hodí pri detekcii kolízie, kde potom nemusíme zdlouhavně vytvárať nový Rectangle. A posledná metódou je GetSize, ktorá nám vráti výšku a šírku objektu.

protected Texture2D texture;
protected Vector2 position;

public GameObject(Texture2D texture, Vector2 position)
{
     this.texture = texture;
     this.position = position;
}

public Vector2 GetPosition()
{
     return position;
}

public Texture2D GetTexture()
{
     return texture;
}

public Rectangle GetRectangle()
{
     return new Rectangle((int)position.X, (int)position.Y, (int)texture.Width,
           (int)texture.Height);
}

public Vector2 GetSize()
{
     return new Vector2(texture.Width, texture.Height);
}

Teraz, keď máme hotovú triedu GameObject, sa môžeme pustiť do tvorby triedy Player, kde budeme mať vekreslení hráčov, ale aj jeho logiku.

Ako som už spomínal, trieda Player bude dediť z triedy GameObject, pretože náš hráč je vlastne herný object (všetko čo má hmotnú predstavu a môže potenciálne kolidovat bude dediť z triedy GameObject).

class Player : GameObject

Teraz si v triede vytvoríme novú inštanciu triedy Game1, aby sme mali dostupné naše pomocné metódy. Ďalej si vytvoríme premenné Lives, Speed, EatedJellies. Tieto premenné nastavíme public a budú to vlastnosti. Nechávam je public, pretože sa pravdepodobne dostaneme k ich modifikáciám a úpravám z vonku a preto bude dobré je mať public.

V konstruktoru nadefinuje všetko čo je potrebné a použijeme kľúčové slovo: base, pretože dedíme z inej triedy. Premennou EatedJellies nastavíme v konstruktoru na 0, táto premenná bude zaznamenávať počet zjedených želé.

Ďalej si vytvoríme metódu Update, Collision a Draw. V metóde Update budeme pohybovať naším hráčom a preto tu využívame KeyboardState a gametime. KeyboardState zachytáva klávesnicu, takže tu máte prístup k metóde IsKeyDown, ktorú použijeme. Metódu Collision zatiaľ necháme prázdnu a budeme ju editovať až neskôr. A posledná metóda Draw bude slúžiť ku skutočnému vykreslenie nášho hráča.

private Game1 game;
public int Lives { get; set; }
public int Speed { get; set; }
public int EatedJellies { get; set; }

public Player(Texture2D texture, Vector2 position, int Lives, int Speed, Game1 game)
    : base(texture, position)
{
    this.texture = texture;
    this.position = position;
    this.Lives = Lives;
    this.Speed = Speed;
    this.game = game;
    EatedJellies = 0;
}

public void Update(KeyboardState ks, GameTime gameTime)
{
    if (ks.IsKeyDown(Keys.Left) && position.X > 0)
        position.X -= Speed;
    else if (ks.IsKeyDown(Keys.Right) && position.X < game.GetScreenSize().X - texture.Width)
        position.X += Speed;
}

public void Collision()
{

}

public void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(texture, position, Color.White);
}

V metóde Update, ak je stlačená klávesa Left alebo Right, posunieme hráča vľavo, alebo naopak, ale zároveň v podmienkach strážime to, že hráč nevyšiel z hracej plochy. Tu treba uplatníme metódu GetSreenSize, ktorú sme si vytvorili.

A ako posledných už len pár zmien v triede Game1. Kde musíme vytvoriť novú inštanciu triedy Player a vykresliť nášho hráča.

private Player player;

A inicializujeme ho v metóde LoadContent. Tento krok sa prakticky nemení.

player = new Player(Content.Load<Texture2D>("player"),
                new Vector2(GetScreenSize().X / 2, GetScreenSize().Y - 200), 5, 5, this);

Nastavíme všetky požadované parametre. Pozícia je nastavená tak, aby bol hráč pekne na vrchu našej krajiny. Avšak môžete použiť metódu GetGroundRect a nastaviť Y súradnicu tak, aby jeho pozícia ladila s akýmkoľvek rozlíšením. Všimnite si na konci metódy parametra this, tým odovzdávame inštanciu triedy Game1, v ktorej práve pracujeme.

V metóde Update zavoláme našu metódu Update, ktorú som u hráča vytvorili.

KeyboardState ks = Keyboard.GetState();

player.Update(ks, gameTime);

Iba si tu vytvoríme novú inštanciu KeyboardState, ktorú budeme v našom projekte využívať.

A posledná úprava bude v metóde Draw, tu zavoláme iba metódu Draw, ktorú sme hráčovi pridali.

player.Draw(spriteBatch);

Teraz sa nám hráč veselo pohybuje. To je dnes všetko a nabudúce budeme pokračovať v tvorbe našej hry.


 

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

 

Všetky články v sekcii
Hra JellyBox v MonoGame
Preskočiť článok
(neodporúčame)
Hra JellyBox v MonoGame - Želé a Score
Článok pre vás napísal Jakub Lásko[Saarix]
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Věnuji se programování v C#, MonoGame a Unity.
Aktivity