Lekce 6 - Hra JellyBox v MonoGame - Sugar a Menu
V minulém tutoriálu o MonoGame, Hra JellyBox v MonoGame - Toxic a poslední želé, jsme si do hry dodělali velice pěkné Toxic želé a začali jsme pracovat na Sugar želé, které bude naším posledním ve hře, ale také asi s nejlepším chováním.
Dnes si sugar dokončíme a začneme pracovat na herním menu, aby hra dostala určitý řád.
Textury
Dnes budeme potřebovat 2 textury, a to textury pro 2 tlačítka, která budou obsažena v menu (New game, Exit). Textury si nahrajeme do složky Content.
Snad mě za tato tlačítka nikdo nepopraví, protože jsem je musel dělat sám Ale pro názornost menu nám postačí.
Sugar Box Finále
Nyní si dokončíme náš sugar box, což bude velice jednoduché, protože to bude pouze o tom vytvořit si pro něj "spawn", přidělit mu texturu a v určitý čas ho generovat. Prní úpravu budeme dělat ve třídě Logic, tak se do ní přepneme a můžeme začít.
Vytvoříme si novou Texture2D, kterou nazveme sugarBox a zde budeme uchovávat texturu pro něj.
private Texture2D sugarBox;
Teď si vytvoříme novou metodu SpawnSugarBox, která nám opět bude generování daného boxu řídit.
public void SpawnSugarBox() { Box box = new SugarBox(sugarBox, Vector2.Zero); int x = random.Next(0, (int)game.GetScreenSize().X - (int)box.GetSize().X - (((SugarBox)box).Scale * 2)); ((SugarBox)box).SetPosition((int)x, -100); boxes.Add(box); }
Nastavíme všechny potřebné parametry jako texturu, pozici, Scale a pak přidáme box do našeho listu.
Pozn. pro ty, kteří zapomněli, tak Scale zde při generování pozice X znamená maximální výchilku při kmitání. Jelikož kmitáme jako do + tak do -, tak musíme použít Scale * 2. Tímto jsme zamezili, aby náš objekt vyjížděl z hrací plochy.
Nyní si zde přidáme novou podmínku, která nám bude zajišťovat, aby se při generování nevygenerovali 2 boxy přes sebe, ale také jakmile narazí např. toxic box do normálního boxu, tak ho zničí. Varuji, že je to trochu brutálnější podmínka, ale když se na ni podíváte trochu více, tak ji určitě hned pochopíte.
for (int e = 0; e < boxes.Count; e++) { for (int i = 0; i < boxes.Count; i++) { if (e != i) { if (boxes[e].GetRectangle().Intersects(boxes[i].GetRectangle())) { if (boxes[e].GetType() != typeof(SugarBox) && boxes[i].GetType() != typeof(SugarBox)) { if (boxes[e].GetType() == typeof(ToxicBox) && boxes[i].GetType() != typeof(ToxicBox)) boxes[i].Delete = true; else if (boxes[i].GetType() != typeof(ToxicBox)) boxes[i].Delete = true; } } } } }
Jakmile v podmínce zjistíme, že do sebe 2 boxy "naráží", tak pak už je to jen o určení jednotlivých typů boxů a jejich následném chování. Takže jakmile se s něčím střetne toxic box, tak ten druhý vymaže, ale u sugar boxu je kolize ignorována a nice se neděje.
Tímto máme třídu Logic hotovou a je třeba doupravit třídu Game1. Jako první si ve třídě Game1 přidáme novou proměnnou typu float sugarBoxSpawnTime, která nám bude zaznamenávat čas pro spawn (vygenerování) sugar boxu.
priva float sugarBoxSpawnTime;
V metodě Initialize ji nastavíme na 0.
sugarBoxSpawnTime = 0;
Teď se musíme mrknout do metody LoadContent a upravit vytváření instance třídy Logic a přidat tam texturu pro náš sugar box.
logic = new Logic(this, boxes, bullets, Content.Load<Texture2D>("GreenJelly"), Content.Load<Texture2D>("BrownJelly"), Content.Load<Texture2D>("Bullet"), Content.Load<Texture2D>("ToxicJelly"), Content.Load<Texture2D>("Sugar"));
A finálně se podíváme do metody Update a přidáme si podmínku pro spawn sugar boxu.
sugarBoxSpawnTime += (float)gameTime.ElapsedGameTime.TotalSeconds; if (sugarBoxSpawnTime > 22) { sugarBoxSpawnTime = 0; logic.SpawnSugarBox(); }
Do proměnné sugarBoxSpawnTime nastavujeme uběhlý čas hry. Pokud dosáhne 22s, tak ho vynulujeme a vygenerujeme nový sugar box.
Málem bych zapoměl, že než to bude kompletní, tak musíme upravit hráčovu kolizi ve třídě Player a zohlednit tam kolizi se sugar boxem a nadefinovat co se má stát. Takže ve třídě Player, v metodě Collision přidáme následujicí podmínku, pod podmínku kdy se obj = ToxicBox.
if (obj is SugarBox) { obj.Delete = true; Lives++; game.score.ScoreMultiply++; }
Nyní jsem nadefinovali, že při kolizi se sugar boxem hráč dostane jeden život a zvýší se mu ScoreMultiply.
Menu
V projektu si vytvořme novou složku s názvem Menu. Než se pustíme do menu jako takového, tak by bylo dobré si vytvořit button, který v něm budeme používat. Vytvořme novou třídu jménem Button (ve složce Menu). Třída bude obsahovat následujicí proměnné.
private Texture2D texture; private Vector2 position; private bool isActive;
Samozřejmě texturu, pozici, ale také bool isActive, který nám bude říkat, zda je button aktivní.
Vytvoříme si konstruktor třídy Button a nastavíme v něm isActive na false;
public Button(Texture2D texture, Vector2 position) { this.texture = texture; this.position = position; isActive = false; }
Nyní si vytvoříme 2 metody (Activate, Deactivate), které budeme používat k aktivování, či deaktivování tlačítka.
public void Activate() { isActive = true; } public void Deactivate() { isActive = false; }
Metody jsou opravdu primitivní, prakticky zatím jde jen o nastavení boolean hodnoty, ale pokud by někdo dělal sofistikovanější menu, tak se mu zde může kód zvětšit.
A jako poslední opět metoda Draw díky které budeme Button vykreslovat.
public void Draw(SpriteBatch spriteBatch) { if (isActive) spriteBatch.Draw(texture, position, Color.White); else spriteBatch.Draw(texture, position, Color.White * 0.5f); }
V metodě Draw rozlišujeme, zda je button aktivní a pokud není, tak mu dáme 50% průhlednost.
Tímto máme button připravený a můžeme se pustit do tvorby menu. Ale než tak učiníme, tak se přesuneme do třídy Game1 a učiníme malou změnu, aby bylo vše připraveno.
Vytvoříme si zde nový veřejný enum eStavHry, který nám bude říkat v jakém je hra stavu.
public enum eStavHry { Hra, Pauza, GameOver, Menu, }
Jak vidíte, zvolil jsem zde stavy (Hra, Pauza, GameOver, Menu), toto jsou všechny stavy, kterých může naše hra nabýt.
Nyní si vytvoříme novou proměnnou typu eStavHry, takže to bude enum a nezveme ji stavHry.
public eStavHry stavHry;
V metodě Initialize ji přiřadíme hodnotu a nastaváme ji na Menu. Je zde velice výhodné, že enum vám ukáže všechny jeho možné hodnoty a vy jednu z nich vyberete, takže se nikdy nestane, že by jste např. v podmínce špatně určili název stavu.
stavHry = eStavHry.Menu;
Teď je vše připraveno a vytvoříme si novou třídu jménem MenuScreen ve složce Menu.
Budeme zde potřebovat 3 textury (pro pozadí, tlačítko nová hra a tlačítko konec), dále si vytvoříme List buttonů a rovnou si vytvoříme jeho instanci. Budeme také potřbovat předat skrze konstruktor instanci třídy Game1 Bool hodnoty, které budou hlídat, aby došlo ke zmáčknutí (nahoru, dolů) pouze jednou (press). Pak int index, který nám bude určovat index buttonu, který je práve aktivní. Jako poslední bool NewGame, který nám bude určovat, zde bylo spuštěna nová hra.
private Texture2D background, newGame, exit; private List<Button> buttons = new List<Button>(); private Game1 game; private bool upPressed, downPressed; private int index; public bool NewGame { get; set; }
Zbytek necháme na příště a to dokončíme Menu, ale i GameOver V tomto stavu jde hra bez problémů spustit, takže si nový typ boxu můžete ihned vyzkoušet. Těším se opět u dalšího tutoriálu o hře v MonoGame.
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 293x (1.89 MB)
Aplikace je včetně zdrojových kódů v jazyce C#