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

3. diel - Hra JellyBox v MonoGame - Strely a Logika

V minulom tutoriále o MonoGame sme si do hry pridali želé a score. V dnešnom diele dorobíme všetko čo chýba u score, pridáme si triedu Logic, ktorá nám bude ovládať logiku objektov, aby sme zredukovali množstvo kódu v triede Game1 a tiež si pridáme strely, ktoré bude môcť hráč strieľať.

Textúry

V dnešnom diele budeme potrebovať iba 1 textúru a to textúru pre strelu. Textúru opäť nahráme do zložky Content.

bullet - Hra JellyBox v MonoGame

Ako je vidieť, tak dnes sa budeme prevažne venovať iba kódu.

FadeEffect

Ešte, než sa pustíme do úplne nových vecí je potrebné dorobiť náš FadeEffect pre score. Urobíme preto 2 úpravy v triede Game1. Nájdeme si tu metódu Update a pridáme nasledujúci kód.

foreach (FadeEffect fe in fades)
    fe.Update(gameTime);

for (int i = 0; i < fades.Count; i++)
{
    if (fades[i].Faded)
        fades.RemoveAt(i);
}

Cyklus foreach slúži k updatu všetkých fade EFFECT v liste. Spodná cyklus for slúži na to, že prejde všetky položky v liste a ak daná položka má vlastnosť Faded nastavenú na true, tak túto položku vymaže.

Týmto máme už score plne funkčný a bude nám pekne miznúť.

Bullet (strela)

Teraz si vytvoríme novú triedu pre strelu s názvom Bullet. Trieda bude dediť z triedy GameObject, ale to už snáď vieme, pretože je strela pevný objekt.

class Bullet : GameObject

V triede si vytvoríme privátne int speed, ktorý bude ovládať rýchlosť našej strely. Potom verejnú vlastnosť bool Delete, ktorá bude rozhodovať o tom, či sa má strela zmazať. Trieda bude obsahovať 3 metódy. Prvá metóda je Update, ktorá iba zabezpečuje pohyb strely smerom nahor. Druhou metódou je Draw, ktorá vykreslí našu strelu. Tretia metódou je Collision, kde máme ako vstupný parameter Box. Akonáhle sa strela zrazí s nejakým boxom (želé), tak sa strela aj želé vymaže a hráči sa pripočíta score.

private int speed;
public bool Delete { get; set; }

public Bullet(Texture2D texture, Vector2 position, int speed)
    : base(texture, position)
{
    this.texture = texture;
    this.position = position;
    this.speed = speed;
    this.Delete = false;
}

public void Update(GameTime gameTime)
{
    position.Y -= speed;
}

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

public void Collision(Box obj, Game1 game)
{
    if (GetRectangle().Intersects(obj.GetRectangle()))
    {
        obj.Delete = true;
        this.Delete = true;
        game.AddScore(2, obj.GetCenterPosition());
    }
}

Ako je tu vidieť, tak namiesto dlhého určovaní nového Vectoru stredu boxu tu iba zavoláme metódu GetCenterPosition a máme hotovo.

Player

Ešte, než sa pustím do triedy Logic, tak vďaka tomu, že už máme boxy (želé) a strely hotové, dorobíme v triede Player metódu Collision. Tú sme predtým iba definovali, ale nenastavili žiadne správanie.

public void Collision(Box obj)
{
    if (GetRectangle().Intersects(obj.GetRectangle()))
    {
        obj.Delete = true;
        EatedJellies++;
        game.AddScore(5, obj.GetCenterPosition());
    }
}

Nastavili sme vstupný parameter Box. Akonáhle sa hráč stretne s boxom, tak sa box vymaže, počet zjedených želé sa inkrementuje a pridáme hráči 5 score. Teraz už je všetko pripravené a môžeme sa vrhnúť na triedu Logic a všetko rozpohybovať.

Logic

Teraz si vytvoríme novú triedu Logic, ktorá bude obsahovať väčšinu "kúziel" našej hry. Tu bude vykonávať updatami prakticky všetkých objektov a tiež nejakú tú nevyhnutnú logiku spolu s mazaním objektov, či kontrolou kolízií. Ušetríme si tým hromadu miesta v triede Game1, kde potom budeme riešiť menu, game over a generovanie objektov.

V triede si vytvoríme novú inštanciu Random, ktorá bude slúžiť na náhodnému generovanie boxov. Ďalej inštanciu triedy Game1, odkiaľ budeme potrebovať naše metódy. Novú instaci List <Box>, kde budeme mať všetky vygenerované boxy. 3 inštancie Texture2D (zelené želé, hnedé želé, želé strela). Novú inštanciu List <Texture2D>, kam nasypeme textúry našich boxov a potom z tohoto listu budeme vyberať náhodnú textúru. Novú inštanciu List <Bullet>, kde budeme mať všetky vegenerované strely. Ako posledný bool keyPressed, ktorý bude slúžiť na kontrolu výstrelu, aby sa vystrelilo 1 pri stlačení klávesy.

private Random random;
private Game1 game;
private List<Box> boxes;
private Texture2D greenBox, brownBox, jellyBullet;
private List<Texture2D> textures;
private List<Bullet> bullets;
private bool keyPressed;

public Logic(Game1 game, List<Box> boxes, List<Bullet> bullets, Texture2D greenBox, Texture2D brownBox,
    Texture2D jellyBullet)
{
    this.game = game;
    this.boxes = boxes;
    this.bullets = bullets;
    this.greenBox = greenBox;
    this.brownBox = brownBox;
    this.jellyBullet = jellyBullet;

    keyPressed = false;
    random = new Random();

    textures = new List<Texture2D>();
    textures.Add(this.greenBox);
    textures.Add(this.brownBox);
}

V konstruktoru nastavíme keyPressed na false, inicializujeme random a textures. Do textures přidíme textúry, ktoré budeme používať pre želé, čo sú v našom prípade Greenbox a brownBox.

Teraz do triedy pridáme metódu s názvom SpawnBox, táto metóda bude mať ako vstupný parameter List <Box>. Vnútri skrze random vyberieme náhodné číslo textúry z nášho zoznamu textúr. Do premennej x zadáme skrze random náhodné číslo, ktoré bude od 0 po pravý okraj hracej plochy - šírka textúry, ktorú sme vybrali. Ako posledný vložíme do listu boxov nový box s nami vybranou textúrou a náhodne vygenerovanú pozičné hodnotou x.

public void SpawnBox(List<Box> b)
{
    int t = random.Next(0, textures.Count);
    int x = random.Next(0, (int)game.GetScreenSize().X - textures[t].Width);

    b.Add(new Box(textures[t], new Vector2(x, -100)));
}

Takto budeme v triede Game1 ľahko generovať nové boxy.

Teraz majoritný časť triedy Logic a tou je metóda Update o ktoré nám tu v podstate ide. Nechal som v kóde popisky pre lepšiu hľadanie daných funkcií. U metódy update budeme mať 3 parametre (KeyboardState pre stav klávesnice, Player ako inštancia hráča, gametime čas hry, ktorý používame pri rôznych metód).

public void Update(KeyboardState ks, Player player, GameTime gameTime)
{
    // střelba
    if (ks.IsKeyDown(Keys.Space) && !keyPressed)
    {
        bullets.Add(new Bullet(jellyBullet,
            new Vector2(player.GetPosition().X + player.GetRectangle().Width / 2 - jellyBullet.Width / 2,
            player.GetPosition().Y - jellyBullet.Height / 2), 3));

        keyPressed = true;
    }
    if (ks.IsKeyUp(Keys.Space) && keyPressed)
        keyPressed = false;

    // updatování střel, kontrola kolize střel a boxů
    foreach (Bullet bullet in bullets)
    {
        // update střel
        bullet.Update(gameTime);
        // kolize střel
        foreach (Box box in boxes)
            bullet.Collision(box, game);
    }

    // updatování boxů a kontrola jejich kolize se zemí
    foreach (Box b in boxes)
    {
        b.Update(game, gameTime);
        b.Collision(game.GetGroundRect(), game, player);
    }

    // kontrola kolize hráče a boxů
    foreach (Box b in boxes)
        player.Collision(b);

    // mazaní boxů
    for (int i = 0; i < boxes.Count; i++)
    {
        if (boxes[i].Delete)
            boxes.RemoveAt(i);
    }

    // mazání střel
    for (int i = 0; i < bullets.Count; i++)
    {
        if (bullets[i].Delete)
            bullets.RemoveAt(i);
    }

    // mazání střel, jakmile vyjedou z hrací plochy
    for (int i = 0; i < bullets.Count; i++)
    {
        if (bullets[i].GetPosition().Y < 0 - bullets[i].GetRectangle().Height)
            bullets.RemoveAt(i);
    }
}

Na začítku sme si vytvorili streľbu. Ak stlačíme medzerník a keyPressed je false, tak sa vytvorí nová strela a keyPressed sa nastaví na true (obrana proti generovanie viac striel pri 1 stlačení. Nižšie v podmienke akonáhle je keyPressed true a medzerník nie je stlačený, tak keyPressed nastavíme na false.

Ďalej prechádzame cyklom foreach všetky strely, updatom je a potom pomocou foreach cyklu prejdeme boxy a kontrolujeme či sa daná strela nestretla s jedným z boxov.

Ďalej prechádzame cyklom foreach všetky boxy, updatom je a kontrolujeme, či sa nestretli so zemou.

V ďalších 2 for cykloch sa prechádza zoznam striel a boxov, akonáhle je vlastnosť Delete true, tak daný objekt vymažeme zo zoznamu.

Ďalej prechádzame cyklom for zoznam striel a kontrolujeme či sa strela dostala mimo hracej plochy, ak áno, tak ju rovno zmažeme.

To by bolo zatiaľ v našej triede Logic všetko. Namiesto sa neodvratne kráti, takže toto je pre dnešok všetko a nabudúce si pridáme našu triedu Logic do triedy Game1 a sprevádzkujeme logiku a všetko rozhýbeme. Snáď sa dnešný diel páčil a nabudúce už bude aj so zábavnou spustiteľnú verzií.


 

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

 

Predchádzajúci článok
Hra JellyBox v MonoGame - Želé a Score
Všetky články v sekcii
Hra JellyBox v MonoGame
Preskočiť článok
(neodporúčame)
Hra JellyBox v MonoGame - Logika a Nové želé
Č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