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

5. diel - Hra JellyBox v MonoGame - Toxic a posledná želé

V minulom tutoriále o MonoGame sme si do hry doimplementovali triedu Logic, pridali generovanie želé a vytvorili nový typ Toxic. V dnešnom diele dorobíme Toxic a jeho generovanie. Tiež si vytvoríme nový a posledný typ želé menom Sugar, ktoré nám bude zvyšovať ScoreMultiply.

Textúry

Ako bolo napovězeno v úvodnom texte, tak dnes budeme potrebovať iba textúru pre Sugar. Textúru si nahráme do zložky Content.

Sugar - Hra JellyBox v MonoGame

Dokončenie Toxic Boxu

Najprv sa pozrieme do triedy Logic a tu pridáme a upravíme všetko čo je potrebné. Pridáme si novú Texture2D pre toxic box a tiež si pridáme do konstruktoru triedy.

private Texture2D toxicBox;

Tým bycgom mali textúru pripravenú a teraz si vytvoríme novú metódu menom SpawnToxicBox, ktorá nám bude riadiť generovanie toxic boxov.

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 metóde najprv vytvoríme novú inštanciu boxu, priradíme mu textúru, vektor pozície nastavíme zatiaľ na nulu a nastavíme rozmedzie pre "skoky". Ďalej vygenerujeme náhodnú X-ovú pozíciu pre náš box a vďaka metóde SetPosition, ktorú toxic box obsahuje, mu nastavíme polohu. A nakoniec box pridáme do listu.

Posledné úpravu v triede Logic urobíme v metóde Update. Tu zmeníme cyklus pre updatované a kontrolu kolízií boxov. Cyklus teraz bude vyzerať takto.

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

Akonáhle je tu box typu ToxicBox, tak sa v inštancii boxe b objavia typ ToxicBox a podmienka ďalej prevedie metódy Update a Collision, ktoré náležia triede ToxicBox. Inak inštancie boxu b zostáva typu Box a vykoná metódy Update a Collision, ktoré patria tejto triede.

Teraz sa presunieme do triedy Player a upravíme tu metódu Collision, ktorú sme vytvorili.

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äť sme si tu pridali podmienku, ktorá zistí či je objekt typu ToxicBox a ak áno, tak vykoná vymazanie objektu, uberie hráči život a ScoreMultiply nastavi na 1. Inak sa hráč zrazil s normálnou boxom (želé) a dostane + score, atď .. .

A finálne upravy urobíme v triede Game1. Tu si vytvoríme novú premennú typu float, ktorá bude zaznamenávať časový interval pre vygenerovanie toxic boxu.

private float toxicBoxSpawnTime;

V metóde Initialize túto premennú nastavíme na 0.

toxicBoxSpawnTime = 0;

V metóde LoadContent upravíme inicializácii triedy Logic a načítame tu našu textúru pre toxic box.

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

Teraz v metóde Update pridáme generovanie toxic boxu.

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

Do premennej toxicBoxSpawnTime ukladáme aktuálny čas od zapnutia hry. Akonáhle je čas 10s, tak ho vynulujeme a skrze metódu SpawnToxicBox vygenerujeme nový toxic box.

Týmto by sme mali mať hotový ToxicBox, ktorý nám teraz bude veselo poletovať v hre. Teraz sa môžeme vrhnúť na posledný typ a tým je SugarBox.

Sugar Jelly

Pridáme si novú triedu menom SugarBox. Náš SugarBox bude mať veľmi zvláštne pohyb, ktorým bude harmonické kmitanie, tak jeho pohyb si môžeme přectavit ako sínusoida.

harmonické kmitanie - Hra JellyBox v MonoGame

Budeme tu potrebovať nejaký ten vzorček, ale nebojte, na nasledujúcich riadkoch sa ho pokúsim vysvetliť. Bude to vzorec pre výpočet okamžité výchylky harmonického kmitania, čiže vďaka tomuto vzorcu zistíme, kde sa daný predmet pri kmitaní nachádza v danú dobu.

Y = Ym * sin(ω*t + φ0)
  • Ym je amplitúda výchilky (maximálny "bod" kam až sa predmet pri kmitaní dostane).
  • ω je uhlová frekvencia (rýchlosť kmitania) a počíta sa uhol / čas, teda 2pi / T. T je doba pre 1 otočenie.
  • t je čas, čiže tu budeme dosadzovať čas hry a tým zabezpečíme priebeh kmitania. Tu sa napr. Pýtame t = 5s, takže kde sa nachádza predmet v čase 5s.
  • φ0 je počiatočný uhol. Tu môžeme zadať, že kmitanie predmetu bude napr. Začínať v uhle 120 °, ale to tu nepoužijeme, takže táto zložka bude v našom prípade 0.

Snáď ste z môjho výkladu aspoň trochu pochopili ako bude harmonické kmitanie fungovať a môžeme sa pustiť do tvorby triedy.

Trieda bude ako obvykle dediť z triedy Box.

class SugarBox : Box

Vytvoríme si verejnú vlastnosť Scale, ktorá bude reprezentovať pravá Ym, čo je maximálna výchylka. Tiež premennú typu float time, ktorá bude obsahovať terajší čas hry, čo použijeme ako t v našom vzorci.

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

V konstruktoru nastavíme time na 0 a Scale som nastavil na 50, čo je priaznivá výchylka.

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

Teraz si prepíšeme metódu Update, ktorú som oddědili od triedy Box. Tu budeme aplikovať vzorec, ktorý sme si vysvetľovali vyššie.

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 premennej time uložíme aktuálny čas hry. U vektora position budeme k X-ovej súradnici pričítať hodnotu nášho vzorca. Ako je vidieť, tak hodnotu pre dobu otáčky som zvolil 1s, taže kmitanie nebude chaotické. Scale vo vzorci vydelíme 10, aby sme kompenzovali meradlo. To pretože akonáhle počítate okamžitú výchylku kmitania, tak Ym sa prevádza na mm, hoci väčšinou sa udáva v cm. My tu pracujeme s pixelmi, takže delíme 10. Na konci opäť pripočítame k hodnote Y +1, aby nám objekt padal smerom nadol.

Aby niekoho neklame, že k osi X iba pričítame, tak sa nebojte, pretože Y nám vychádza vždy iba v rozmedzí amplitúdy, takže (-Ym až Ym), Tým pádom vždy dostaneme aktuálnu pozíciu + (0 - Ym), alebo - (Ym - 0).

Nakoniec si tu opäť zadefinujeme metódu SetPosition, ktorú pravdepodobne využijeme u generovanie boxu.

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

Tým máme triedu SugarBox kompletný a pripravenú na použitie.

Opäť sa riadky kráti, tak aby sme neskončili uprostred rozpísaného kódu si SugarBox doimplenetujeme nabudúce a už sa pomaly dostaneme na veci ako je animácia či menu. Teším sa opäť u ďalšieho dielu zo série tutoriálov o MonoGame a dúfam, že sa ten dnešný páčil.


 

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

 

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