Unity-suli: kígyók a képernyődön
Újraalkotni a klasszikus Snake játékot nem tartozik a legnagyobb kihívások közé. Cikkünkben be is bizonyítjuk, hogy milyen egyszerű a folyamat.
Sok felhasználónak első komolyabb mobilos játékélményeként örökre az emlékezetébe égett a Nokia készülékek pixelkígyója. Ez a játék bárkit meg tudott izzasztani dacára annak, hogy minden volt, csak épp komplex nem. A folyamatosan növekvő csúszómászóval azóta már rengeteg platformon, számtalan körítésben találkozhattál, a gondolat azonban, hogy saját verziót készíts ebből az örökzöldből, talán még nem merült fel benned. Ám most, hogy sikeresen elültettük a bogarat a füledben, ideje nekilátnod az alkotásnak. Csak csináld úgy, ahogy mi, és menni fog.
Kiegészítő sem kell
A klasszikus játék egy lecsupaszított, ám teljes mértékben játszható verziójának elkészítésén vezetünk végig, amihez minden szükséges elemet megtalálsz majd, amennyiben továbbmerészkednél az alapoknál, és még csiszolgatnád a projektet. Szerencsére egyszerűsége miatt nem igényel komolyabb kiegészítőket az alkotási folyamat, sokkal inkább a kódolási ismereteidet dolgoztatja meg a kígyóbűvölés. Éppen ezért, ha a számítógépeden bevetésre készen áll a Unity, már el is indíthatod 2D-s módban. Itt kel majd életre a kígyód.
Az üres felületen először hozz létre a Hierarchy fül alatti Create segítségével egy üres GameObject állományt. Ha ez bekerült a jelenetbe, akkor jelöld ki, és a jobb oldali Inspector fül alatt a pozíciójának mindhárom értékét állítsd nullára. Ezek után az Add Component gombbal csatolj egy Sprite Renderert a felülethez, mivel enélkül az üres elemed semmit sem tudna megjeleníteni a képernyőn.
Keresd meg a Sprite tulajdonságát, és a mellette található kis körre kattintva válaszd ki a Knob objektumot, amely egy körként jelenik meg a képernyőn. Hogy még jobban látszódjék ez az elem, az X és Y Scale értékét is növeld meg 3-ra, ezzel pedig el is készült kígyód jelképes feje (igény esetén akár színezheted is a Color tulajdonság módosításával).
Mozdulj meg!
A hüllő életre keltéséhez szükség lesz egy kis kódolásra. Kezdd azzal, hogy létrehozol az alul található Projects fül alatt egy új szkriptet (Create/C# Script), elnevezed snakeCode-nak, majd egy szerkesztővel meg is nyitod módosításra. A következő lépésben a billentyűs vezérlést kell megoldanod. Hogy a kontrollálandó objektumot egyszerűen lokalizáld a játékon belül, kreálj egy változót a kígyód fejének (public GameObject snakeHead;), a léptetéshez kelleni fog még egy irány is, ehhez szintén készíts el egy változót (public Vector3 gridDir;).
Most áttérhetsz az Update()-be, itt hozd létre azokat a feltételeket, amelyek a megfelelő gomb lenyomására a kívánt irányba indítják el a karaktert (a felfelé mutató nyílhoz tartozó kódrészlet: if (Input.GetKeyDown(KeyCode.UpArrow)){ gridDir = new Vector3(0,1,0);}). Ha mind a négy irányt sikeresen meghatároztad, akkor már csak a karakternek kell átadnod a megfelelő értéket. Erre a célra a snakeHead.transform.position+= gridDir; utasítást vesd be, amit minden feltételes ág végére bátran biggyessz oda.
Mielőtt tesztelnéd az alkotást, hozz létre egy üres GameObjectet a jelenetben, és ehhez társítsd a kódot, majd a szkripthez csatold a jelenetben található kígyófejet. Ha futtatod a programot, akkor már lehetőséged nyílik arra, hogy a nyilakkal körbejárd a játékteret. Mivel a Snake koncepciója szerint egy folyamatosan mozgó csúszómászót kell kontrollálnod, még van egy kis dolgod, mielőtt késznek nyilváníthatnád a játékot. Térj vissza a szkript felületére, és élesíts egy időzítőt (public float timer=0.0f;), majd növeld ennek az értékét minden megjelenített képkocka hatására a timer +=Time.deltaTime; segítségével.
A kirajzolásnál is használd ezt a számot egy feltételben (if(timer>=1.0f){}), amelynek belsejébe helyezd át a gombnyomásos vezérlés mozgatóutasítását (snakeHead.transform.position+=gridDir;), majd nullázd az időzítő értékét (timer=0.0f;). Utolsó lépésként pedig add meg a Start()-ban a kezdőlökést karakterednek a gridDir = new Vector3(1,0,0); kóddal. Ha most elindítod a szoftvert, akkor alapértelmezetten jobbra lódul meg a kígyó, de a mozgás iránya a billentyűkkel változtatható.
Gyűjts pontokat!
A következő lépés a pontok létrehozása és gyűjtése lesz. Ehhez klónozd a kígyófej gömbjét, színezd át, és helyezd valamilyen egész értékű pozícióba, hogy könnyen hozzáférhető legyen (amennyiben szükségét látod, akár át is méretezheted). Hozz létre egy új szkriptet collectPoint néven, majd nyisd meg szerkesztőnézetben. A felületéről törölheted a Start és az Update függvényeket, mert a kódot csak ütközésdetektálásra használod majd. A felületen készíts el egy objektumra mutató referenciát (public GameObject snakePoint;) majd aktiváld a void OnTriggerEnter2D(Collider2D other){} kódot.
Ennek belsejében egy feltételben vizsgáld a játékossal történő ütközést (if(other.gameObject.tag == "Player"){}), aminek bekövetkezésekor klónozd a pontot (Instantiate(snakePoint,new Vector3(Random.Range(-5,5),Random.Range(-5,5),0),Quaternion.identity);), majd töröld az eredeti objektumot a képernyőről (Destroy(gameObject);). Az így elkészült kódot társítsd a jelenetben lévő ponthoz, a működésének azonban feltétele még néhány Collider és Tag használata. Ebből a célból elsőként kapcsolj a pöttyhöz egy Circle Collider 2D-t az Add Component révén, és a beállításai között aktiváld az IsTrigger melletti pipát.
A kígyó fejét jelölő GameObjectet is módosítsd, felületén szintén helyezz el egy Circle Collider 2D-t, valamint egy Rigidbodyt is (utóbbinál figyelj arra, hogy a Gravity Scale a 0 értéken álljon, különben a karakter kizuhan a képernyőből). Ha ezekkel megvagy, már csak annyi a teendőd, hogy a felül található Tag-értékeknél a legördülő menüből kiválasztod a Player feliratú opciót. Amikor futtatod az alkalmazást, az ütközés hatására eltűnik a pont, és egy új pozícióban bukkan fel.
Hízó csúszómászó
A pontok gyűjtése után már csak egyetlen fontos feladatod maradt: megnövelni a karakter testhosszát minden felszedett pont után. Másold le a kígyó fejét, és készíts belőle Prefabot, majd töröld a jelenetből. Ha ez sikerült, akkor térj vissza a snakeControl kódod szerkesztőnézetébe, és készíts egy hivatkozási pontot a kígyó testének elemeihez (public GameObject snakePart;), egy listát, amelyben a fej mozgási pozícióit tárolod (public List<Vector3> positions;), valamint jelöld a kígyó aktuális méretét is (public static int snakeSize=1;).
Ezek után ugorj az Update() függvény belsejében az időzítő ellenőrzési feltételébe, és hasonlítsd össze a pozíciókat tartalmazó lista méretét a kígyó aktuális hosszával. Amennyiben egyeznek (if(positions.Count==snakeSize){}), töröld az első helyen található elemet a listából (positions.RemoveAt(0);), bővítsd az aktuális pozícióval (positions.Add(snakeHead.transform.position);), majd jelenítsd is meg a képernyőn (Instantiate(snakePart,positions[snakeSize-1], Quaternion.identity);).
A feltétel else ágában csak a növelést és a képernyőre rajzolást használd. Ha most futtatod a kódot, akkor láthatod, hogy az útvonalon megjelennek a pöttyök, a kígyó méretét azonban még szabályoznod kell. Ehhez helyezz el a Prefabon egy "Respawn" taget, majd lépj vissza a program felületére. A pozíciók összevetésének igaz ágában az új elem hozzáadása után, de még a megjelenítés előtt biggyeszd a szkriptedbe a GameObject[] destroyable = GameObject.FindGameObjectsWithTag("Respawn"); kifejezést, a kapott listából pedig az if(destroyable.Length>snakeSize){Destroy(destroyable[0]);} sorral töröld a legrégebben a jelenetbe került objektumot.
Ha most teszteled a programot, akkor egyetlen testkomponens követi csak folyamatosan a fejet, a komponensek a számát azonban a pontfelvétellel növelheted, feltéve, hogy a kódban az ütközés vizsgálatakor elhelyezed a snakeControl.snakeSize += 1; utasítást. Az alapprogramod ezzel el is készült.
Így fejleszd tovább!
Rengeteg lehetőséget rejt magában ez a projekt, és számtalan módon kiegészítheted az elkészített játékmechanikai csontvázat. Mindenképp érdemes lesz egy kicsit dolgoznod a megjelenítésen; ehhez bátran beemelhetsz extra grafikai elemeket is, illetve a hátteret szintén könnyen módosíthatod. Mivel jelen formájában a kígyód mindenféle megkötés nélkül elhagyhatja a képernyő síkját, egy megfelelő Collider-elhelyezéssel elérheted, hogy véget érjen a program.
Ehhez hasonlóan akadályokkal is bővítheted a jelenetet, illetve a kígyó testére is kiterjesztheted ezeket az ütközőket. Módosíthatsz továbbá a véletlenszerűen elhelyezett elemeken is, kódolással ugyanis akár azt is elérheted, hogy olyan pontra ne kerüljön a piros pötty, amely felett épp a kígyó tekereg. Sőt, akár változatos menüelemekkel is felturbózhatod a jelenetet, valamint vezetheted a pontszámítást.