IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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í.

Lekce 5 - Hra JellyBox v MonoGame - Toxic a poslední želé

V minulém tutoriálu o MonoGame, Hra JellyBox v MonoGame - Logika a Nové želé, jsme si do hry doimplementovali třídu Logic, přidali generování želé a vytvořili nový typ Toxic.

V dnešním díle doděláme Toxic a jeho generování. Také si vytvoříme nový a poslední typ želé jménem Sugar, které nám bude zvyšovat ScoreMultiply.

Textury

Jak bylo napovězeno v úvodním textu, tak dnes budeme potřebovat pouze texturu pro Sugar. Texturu si nahrajeme do složky Content.

Sugar - Hra JellyBox v MonoGame

Dokončení Toxic Boxu

Nejprve se podíváme do třídy Logic a zde přidáme a upravíme vše co je potřeba. Přidáme si novou Texture2D pro toxic box a také jsi přidáme do konstruktoru třídy.

private Texture2D toxicBox;

Tím bycgom měli texturu připravenou a nyní si vytvoříme novou metodu jménem SpawnToxicBox, která nám bude řídit generování toxic boxů.

public void SpawnToxicBox()
{
    Box box = new ToxicBox(toxicBox, Vector2.Zero, 100);
    int x = random.Next(0, (int)game.GetScreenSize().X - (int)(box.GetSize().X));
    ((ToxicBox)box).SetPosition(x, -100);

    boxes.Add(box);
}

V metodě nejprve vytvoříme novou instanci boxu, přiřadíme mu texturu, vektor pozice nastavíme prozatím na nulu a nastavíme rozmezí pro "skoky". Dále vygenerujeme náhodnou X-ovou pozici pro náš box a díky metodě SetPosition, kterou toxic box obsahuje, mu nastavíme polohu. A nakonec box přidáme do listu.

Poslední úpravu ve třídě Logic uděláme v metodě Update. Zde změníme cyklus pro updatování a kontrolu kolizí boxů. Cyklus nyní bude vypadat takto.

foreach (Box b in boxes)
{
    b.Update(game, gameTime);
    b.Collision(game.GetGroundRect(), game, player);
}

Jakmile je zde box typu ToxicBox, tak se v instanci boxu b objeví typ ToxicBox a podmínka dále provede metody Update a Collision, které náleží třídě ToxicBox. Jinak instance boxu b zůstává typu Box a provede metody Update a Collision, které náleží této třídě.

Teď se přesuneme do třídy Player a upravíme zde metodu Collision, kterou jsme vytvořili.

public void Collision(Box obj)
{
    if (GetRectangle().Intersects(obj.GetRectangle()))
    {
        if (obj is ToxicBox)
        {
            obj.Delete = true;
            Lives--;
            game.ScoreMultiply = 1;
        }
        else
        {
            obj.Delete = true;
            EatedJellies++;
            game.AddScore(5, obj.GetCenterPosition());
        }
    }
}

Opět jsme si zde přidali podmínku, která zjistí zda je objekt typu ToxicBox a pokud ano, tak provede vymazání objektu, ubere hráči život a ScoreMultiply nastavi na 1. Jinak se hráč srazil s normální boxem (želé) a dostane +score, atd...

A finální upravy uděláme ve třídě Game1. Zde si vytvoříme novou proměnnou typu float, která bude zaznamenávat časový interval pro vygenerování toxic boxu.

private float toxicBoxSpawnTime;

V metodě Initialize tuto proměnnou nastavíme na 0.

toxicBoxSpawnTime = 0;

V metodě LoadContent upravíme inicializaci třídy Logic a načteme zde naši texturu pro toxic box.

logic = new Logic(this, boxes, bullets,
Content.Load<Texture2D>("GreenJelly"),
Content.Load<Texture2D>("BrownJelly"),
Content.Load<Texture2D>("Bullet"),
Content.Load<Texture2D>("ToxicJelly"));

Nyní v metodě Update přidáme generování toxic boxu.

toxicBoxSpawnTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (toxicBoxSpawnTime > 10)
{
    toxicBoxSpawnTime = 0;
    logic.SpawnToxicBox(level.Number);
}

Do proměnné toxicBoxSpawnTime ukládáme aktuální čas od zapnutí hry. Jakmile je čas 10s, tak ho vynulujeme a skrze metodu SpawnToxicBox vygenerujeme nový toxic box.

Tímto bychom měli mít hotový ToxicBox, který nám teď bude vesele poletovat ve hře. Teď se můžeme vrhnout na poslední typ a tím je SugarBox.

Sugar Jelly

Přidáme si novou třídu jménem SugarBox. Náš SugarBox bude mít velice zvláštní pohyb, kterým bude harmonické kmitání, tak jeho pohyb si můžeme přectavit jako sinusovku.

Harmonické kmitání - Hra JellyBox v MonoGame

Budeme zde potřebovat nějaký ten vzoreček, ale nebojte, na následujicích řádcích se ho pokusím vysvětlit. Bude to vzorec pro výpočet okamžité výchylky harmonického kmitání, čili díky tomuto vzorci zjistíme, kde se daný předmět při kmitání nachází v danou dobu.

Y = Ym * sin(ω*t + φ0)
  • Ym je amplituda výchilky (maximální "bod" kam až se předmět při kmitání dostane).
  • ω je úhlová frekvence (rychlost kmitání) a počítá se úhel / čas, tedy 2Pí / T. T je doba pro 1 otočení.
  • t je čas, čili zde budeme dosazovat čas hry a tím zajistíme průběh kmitání. Zde se např. ptáme t = 5s, takže kde se nachází předmět v čase 5s.
  • φ0 je počáteční úhel. Zde můžeme zadat, že kmítání předmětu bude např. začínat v úhlu 120°, ale to zde nepoužijeme, takže tato složka bude v našem případě 0.

Snad jste z mého výkladu alespoň trochu pochopili jak bude harmonické kmitání fungovat a můžeme se pustit do tvorby třídy.

Třída bude jako obvykle dědit ze třídy Box.

class SugarBox : Box

Vytvoříme si veřejnou vlastnost Scale, která bude reprezentovat přáve Ym, což je maximální výchylka. Také proměnnou typu float time, která bude obsahovat nynější čas hry, což použijeme jako t v našem vzorci.

public int Scale { get; private set; }
private float time;

V konstruktoru nastavíme time na 0 a Scale jsem nastavil na 50, což je příznivá výchylka.

public SugarBox(Texture2D texture, Vector2 position)
    : base(texture, position)
{
    time = 0;
    Scale = 50;
}

Nyní si přepíšeme metodu Update, kterou jsem oddědili od třídy Box. Zde budeme aplikovat vzorec, který jsme si vysvětlovali výše.

public override void Update(Game1 game, GameTime gameTime)
{
    // harmonické kmytání kostky
    time += (float)gameTime.ElapsedGameTime.TotalSeconds;
    position.X += (Scale / 10) * (float)Math.Sin((2 * Math.PI / 1) * time);

    position.Y += 1;
}

Do proměnné time uložíme aktuální čas hry. U vektoru position budeme k X-ové souřadnici přičítat hodnotu našeho vzorce. Jak je vidět, tak hodnotu pro dobu otáčky jsem zvolil 1s, taže kmitání nebude chaotické. Scale ve vzorci vydělíme 10, aby jsme kompenzovali měřítko. To protože jakmile počítáte okamžitou výchylku kmitání, tak Ym se převádí na mm, ačkoliv většinou se udává v cm. My zde pracujeme s pixely, takže dělíme 10. Na konci opět přičteme k hodnotě Y +1, aby nám objekt padal směrem dolů.

Aby někoho nemátlo, že k ose X pouze přičítáme, tak se nebojte, protože Y nám vychází vždy pouze v rozmezí amplitudy, takže (-Ym až Ym), Tím pádem vždy dostaneme aktuální pozici + (0 - Ym), nebo - (Ym - 0).

Nakonec si zde opět nadefinujeme metodu SetPosition, kterou pravděpodobně využijeme u generování boxu.

public void SetPosition(int x, int y)
{
    position = new Vector2(x, y);
}

Tím máme třídu SugarBox kompletní a připravenou k použití.

Opět se řádky krátí, tak abychom neskončili uprostřed rozepsaného kódu si SugarBox doimplenetujeme přístě, Hra JellyBox v MonoGame - Sugar a Menu, a už se pomalu dostaneme na věci jako je animace či menu. Těším se opět u dalšího dílu ze série tutoriálů o MonoGame a doufám, že se ten dnešní líbil.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 179x (1.87 MB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Hra JellyBox v MonoGame - Logika a Nové želé
Všechny články v sekci
Hra JellyBox v MonoGame
Přeskočit článek
(nedoporučujeme)
Hra JellyBox v MonoGame - Sugar a Menu
Článek pro vás napsal Jakub Lásko[Saarix]
Avatar
Uživatelské hodnocení:
4 hlasů
Věnuji se programování v C#, MonoGame a Unity.
Aktivity