Rács alapú útvonalkeresés | hyperPad Documentation

Loading...

Logo

Ebben a bemutatóban egy útvonalkeresési szimulációt készítünk egy 2-dimenziós tömb alapú rács alapján. Ez megadja nekünk az alapvető ötletet az útvonalkeresési tevékenységek létrehozásához a játékainkban. A rácsot üres négyzet objektumokkal fogjuk vizualizálni, mint csempék, és egy kerek objektumként, mint avatár, amely a parancsunkkal mozoghat ezen a rács területen.

Video_2019-07-30__2_32_01_PM.gif

I. Az objektumok beállítása

Csak négy objektumot fogunk használni a projektünkben. Zöld avatárunk, egy kék csempe, egy fehér blokk és a rács címkéje a rácsunk beállításához és vizualizálásához.

Photo_2019-07-29__1_50_10_PM.png

Avatár

Az avatárunk egy üres objektum, amelynek az x és y mérete 50%. A ütközését kerek formára állítsuk, hogy olyan legyen, mint az alábbi képen. Ennek az objektumnak három előre meghatározott attribútuma lesz: a csempén, a korábbi csempe, és a célcsempe. Ezeket az attribútumokat alapértelmezetten nullára kell állítani, hogy ne legyen null értékük, amikor később megpróbáljuk elérni őket.

Photo_2019-07-29__1_53_38_PM.png

Csempe Objektum

Hozzunk létre egy másik üres objektumot, amelyet a rácsunkban a csempék vizualizálására fogunk használni. Ez is 50%-os méretű, és csak egy előre meghatározott attribútuma van: csempén. Állítsuk ezt az értéket is nullára.

Photo_2019-07-29__1_53_51_PM.png

Blokkoló Objektum

Hozzunk létre egy másik üres objektumot, amely blokként fog szolgálni a rácsunkban. Ez egy fehér üres objektum, amelynek a mérete 40%. Az avatárunk nem tud átkelni arra a csempére, amelyen blokk található.

Rács Címke

Ez csupán egy címke, amely olyan viselkedéseket tartalmaz, amelyek lehetővé teszik a rácsunk beállítását és vizualizálását. Előre meghatározott attribútumai vannak: kezdő x érték 4, kezdő y érték 3. Ezek az értékek eltérések, amelyeket a csempék elhelyezéséhez fogunk használni, hogy a rácsunk szépen a középre kerüljön.

Photo_2019-07-29__1_56_01_PM.png

Avatár/Csempe előre meghatározott attribútumai:

Itt egy csempét egy 2-dimenziós tömbként definiálunk, amely x és y értékekkel fog rendelkezni a rácsunk alapján.

  • csempén - ez az a csempeérték, amin az objektumunk jelenleg áll a rácsunkban
  • korábbi csempe - a csempe, amelyet korábban járt be az avatárunk
  • célcsempe - az a csempe, ahova az avatárunk megy

II. A rács beállítása

A rács címkéjén belül definiáljuk a 2D tömbünket és a rácsunk létrehozását. Ennek az objektumnak 2 fő szempontja van: a tömb beállítása, és a tömb vizualizálása. Először a beállító tömb csomagot csináljuk.

Photo_2019-07-29__3_05_10_PM.png

A tömb beállítása - csomag

Első lépés egy üres tömb létrehozása, amelynek neve 'Rács'. Ez a tömb a 2-dimenziós tömbünket fogja tartalmazni. Lesz egy doboz konténerünk, amelynek neve 'x sor szám', értéke 24, és egy másik üres tömb, amelynek neve 'y sor', amely 18 üres értéket tartalmaz.

Photo_2019-07-29__1_55_28_PM.png

A csomagunk első viselkedése egy ciklus, amely a 'x sor szám' számú ismétlésből áll. Ennek a ciklusnak minden lépésében hozzáadunk egy üres y sort a 'Rács tömbhöz'. Ez egy tömböt hoz létre a rácsunkban mérettel 24x18.

Észrevettük, hogy a csomagunk elején van egy inaktív komment, hogy megakadályozzuk a gyökér viselkedés automatikus végrehajtását. A gyökér viselkedés olyan viselkedés, amely nem indítódik el események alapján, és nyíltan a felületen helyezkedik el.

A rács vizualizálása - csomag

Amit itt fogunk csinálni, az az, hogy az 'Rács tömb' minden értékén átmegyünk, és létrehozunk egy csempe objektumot. A ciklusunkba kondíciókat is hozzáadunk, amelyek lehetővé teszik, hogy fehér blokkot helyezzünk el a csempe objektumok fölött.

Photo_2019-07-29__3_56_37_PM.png

Először is meg kell kapnunk az 'y sor tömb' számát, az objektum 'kezdő x' attribútumának értékét és a 'kezdő y' attribútum értékét.

Hozzuk létre a ciklust, amely 'x sor számú' ismétléssel rendelkezik, és minden ilyen lépésben hozzáadjuk a ciklus index értékét a 'kezdő x' attribútum értékéhez. Ez egy abszolút x pozíciót eredményez, amelyet később a felnövekvő csempe pozicionálásához fogunk használni. A következő lépés a 'y sor ciklus', amely 'y sor számú' ismétléssel rendelkezik. Minden ilyen lépésben hozzáadjuk a ciklus index értékét a 'kezdő y' attribútum értékéhez, amely most abszolút y pozíciót eredményez.

Photo_2019-07-29__4_03_51_PM.png

Miután hozzáadtuk az értékeket a 'y sor ciklus alatt', egy kék objektumot hozunk létre. Állítsuk be az életben lévő objektumok számát 999-re, mert sokra szükségünk lesz a rácsunkhoz, és a tartam is 0. Ezután mozgassuk a létrehozott objektumot egy x pontra, amely az x ciklus 'hozzáadott értékeiből' származik, és a y pontra az y ciklus 'hozzáadott értékeiből'.

Következő lépésként adjunk hozzá egy tömböt 2 üres értékkel, amelyet 'Csempén' néven fogunk hívni, amelyet csupán tömb helyett használunk. Miután elmozdítottuk a csempe objektumot, módosítsuk a 'Csempén' tömböt azzal, hogy 0 indexnél az értékét felváltjuk a 'y sor ciklus' értékével. Ezután adjunk hozzá egy új tömb módosítást, amelyben a 1. indexben a 'y sor index' értékét helyettesítjük. Ez a rácsunk x és y koordinátái, amelyek az objektumunk 'csempén' attribútumaként fognak szerepelni.

Most állítsuk be a létrehozott objektum attributumát egy dinamikus kulccsal, 'csempén', és a 'Csempe - tömb' értékével.

Photo_2019-07-29__4_41_55_PM.png

Még mindig a 'y sor ciklus alatt' vannak a feltételek a fehér blokk létrehozásának. Azt fogjuk tenni, hogy 2 az 5-höz az esély, hogy ezt a csomagot végrehajtsuk, ami hozzáadja a véletlenszerűséget a rácsunkhoz. Ezután a 'Rács' tömbben 1 értéket állítunk be az x és y koordinátáknál, ami azt jelzi, hogy az adott koordinátán blokk él.

Először is, kapjunk egy véletlen számot 1 és 5 között. Ha ez a szám kevesebb vagy egyenlő 2-vel, akkor létrehozunk egy blokkot. Állítsuk be az élő objektumok számát 999-re, és mozgassuk ezt az objektumot a korábban létrehozott kék csempe ugyanarra a pontra, szintén 0 tartammal.

Következő lépésként tároljuk az információt, hogy a koordinátát blokkolták, ha létrejöttek. Ezt úgy tudjuk megtenni, hogy azt az koordinátát 1 értékkel megjelöljük. Először is kapjuk meg az 'x sor ciklus' értékét a 'Rács' tömbből. Ez az érték egy 'y sor' tömböt ad nekünk. Módosítjuk ezt a 'y sort' azzal, hogy felváltjuk a 'y sor ciklus' értékét 1-re, amely a megjelölt érték. Mivel ez az érték módosítás csak az értékre vonatkozik, és nem a magára a 'Rács'-ra, vagyis a 'Rács' tömböt is módosítanunk kell. Cseréljük ki a 'Rács' tömb 'x sor ciklus' indexét az 'előző y sor - tömb' értékkel.

Miután a játékot játszottuk, ennek ilyen formának kellene lennie.

Photo_2019-07-29__4_45_18_PM.png

III. Csempe megnyomása

A rács interakciójához szükségünk van egy csomag viselkedésre, amikor megnyomunk egy kék csempét. Az első nyomás eredménye az avatárunk megjelenése a rácsunkban, és minden további nyomás után elkezdődik az útvonalkeresése.

A kék objektumokon olyan viselkedési csomag található, amely három fő lépést tartalmaz: az avatárunk korábbi csempe értékének visszaállítása, a csempe beállítása/beállítása a célcsempe, majd szín animáció hozzáadása, hogy vizualizáljuk a nyomógomb eseményt a képernyőn.

Photo_2019-07-29__5_00_44_PM.png

Először is, kapjuk meg a csempe objektum 'csempén' attribútumát. Állítsuk be az avatárunk 'korábbi csempe' attribútumát 0-ra. Az avatárunkat úgy állítjuk be, hogy elkerülje, hogy visszatérjen egy 'korábbi csempe' értékhez, ezért minden csempe nyomáskor visszaállítjuk a 'korábbi csempe' értékét.

Következő lépés, hogy megkaphassuk az avatárunk 'csempén' attribútumát. Az első if feltétel az, hogy a 'csempe' értéke 0, azaz ha az avatárunk még nem jelent meg, akkor ez igaznak kell lennie. Ha igaz, akkor beállítjuk az 'csempe' attribútumot a csempe objektum 'csempe' attribútuma értékére. Ezután az avatárunk pozícióját a csempe objektum pozíciójára állítjuk, az x és y értékeket a pontra állítva, tartam 0.

Ha a 'csempe' értéke nem egyenlő 0-val, akkor beállítjuk az avatárunk célcsempe attribútumát a csempe objektum 'csempén' attribútumának értékére. Ez azt jelenti, hogy az avatárunk már a rácsunkban van, és végrehajthatjuk a csomag viselkedést, az 'útvonalkeresést'. Még nincs meg ez a viselkedésünk, de ezt a bemutató későbbi részében kijavítjuk, amikor a 'útvonalkereső' csomagra kerül a sor.

Most, hogy helyesen beállítottuk az avatárunkat a rácsunkhoz, csupán a megnyomási esemény vizualizálására van szükségünk. Először a gyökér viselkedéssel kapjunk egy színt, hogy szerezze meg az eredeti színét. Majd a nyomás eseménye után beállítjuk a csempe objektum színét feketévé 0 tartammal, majd visszaállítjuk az eredeti színére 0.2 tartammal.

A kék csempe megnyomásának eredménye a következőképpen kell, hogy kinézzen.

Photo_2019-07-30__1_04_42_PM.png

IV. Az útvonalkereső csomag végrehajtása

A bemutatónk utolsó részén megvalósítjuk az algoritmust, amely lehetővé teszi számunkra, hogy megtaláljuk a legközelebbi csempét, amelyet az avatárunk elérhet a céljához. Ezt a csomagot ismételten végrehajtjuk minden csempe lépés során, amelyen az avatárunk a rácsunkon mozog.

Az algoritmust belül a avatár objektumunkban állítjuk be, és három fő lépésből áll: a szomszédos csempék megtalálása, a legközelebbi szomszédos csempe megtalálása, és a mozgás a szomszédos csempére.

Photo_2019-07-29__5_39_25_PM.png

A szomszédos csempék megtalálása

Ebben a részben összegyűjtjük az összes szomszédos csempét, amelyet az avatárunk átléphet. Ellenőrizzük a négy irányban elhelyezkedő szomszédos csempéket, és megnézzük, hogy vannak-e blokkok a tetejükön, vagy hogy korábban léptek-e a rácsunkra.

Photo_2019-07-29__5_40_24_PM.png

Először hozzáadunk egy 'Szomszédos csempék' tömböt. Egy 'Irány' tömb két üres értékkel, és a négy irányú tömbök, amelyeknek mindenik 2 értéke van: Észak (0,1), Dél (0,-1), Kelet (1,0), Nyugat (-1,0).

A csomagunk első viselkedése az, hogy töröljük a szomszédos csempéket. Mivel ezt a csomagot ismételten végrehajtjuk, szükségünk van a 'gyűjtött szomszédos csempék' visszaállítására minden alkalommal. A következő négy viselkedés a 'Irány' tömb módosításai. A 'Irány' tömb négy alkalommal állítja be a négy irányú tömböt, majd a következő csomagra lépünk. Ezt úgy tesszük, hogy különböző 'Irány' tömb értékekkel is létrehozunk egy ciklust.

Photo_2019-07-29__6_04_42_PM.png

Most, hogy van irányunk, csak annyit kell tennünk, hogy egyesítjük az ő x és y értékeiket az avatárunk 'csempén' attribútumával. Ezután a célértéket elérjük a 'Rács' tömbben, hogy megtudjuk, hogy a csempe blokkolva van-e.

'Irány x' az 'Irány' tömb 0 indexénél lévő érték, a 'csempe x' az x értéke a 'csempe x' indexén. A cél x a 'irány x' és 'csempe x' összeadott értéke. Ugyanez a y értékekben, de a cél indexe 1.

'Cél y sor' a 'Rács' tömb értéke 'Cél x' indexén. A 'Cél index' a 'Cél y sor' tömb értéke a 'Cél y' indexén. Ez a koordináta a rácsunkban, amely meg tudja mondani, hogy az blokkolva van-e.

Photo_2019-07-29__6_17_41_PM.png

Ha a 'Cél index' y sorban lévő értéke 1, az azt jelenti, hogy az a csempe blokkolva van. De ha az érték nem egyenlő 1-gyel, akkor folytathatjuk a csomagot.

Mivel a Cél x és y áthaladt a feltételünkön, hozzáadtunk egy új üres csempe tömböt, amelyet 'Új szomszédos csempe'-ként hívunk. Ez a cél x és y értékeket fogja tárolni csempe tömbként. Beállítjuk a cél x értékét a 'Új szomszédos csempe' 0 indexére, és a cél y értékét az 1 indexére.

Most kapjuk meg az avatárunk 'korábbi csempe' attribútumát. Ha a 'korábbi csempe' nem egyenlő az 'új szomszédos csempe'-val, az azt jelenti, hogy az új csempe nem volt korábban bejárva. Ezért biztonságosan hozzáadhatjuk az 'Új Szomszédos csempe' tömböt a 'Szomszédos csempék' tömbhöz azáltal, hogy hozzáadjuk azt.

"Bővítheti ezt a csomagot úgy, hogy készítsen egy 8 irányú tömböt is, amely lehetővé teszi avatárjának a diagonális irányokban való mozgatását."

A legközelebbi szomszédos csempe megtalálása

Most, hogy összegyűjtöttük megbízható szomszédos csempéinket, csak annyit kell tennünk, hogy megtaláljuk azt a szomszédos csempét, amelyik a legközelebb van az avatárunk célcsempéjéhez. A számítást a célcsempe és a szomszédos csempék x és y értékeinek felhasználásával végezzük.

Ennek a csomagnak két fő szempontja van: a változók inicializálása a számításhoz, és a távolságok kiszámítása a csempe mellett lévő csempékben egy cikluson belül.

a. A változók inicializálása

Először is, meg kell kapnunk a szomszédos csempék számát. Ezután megkapjuk az avatárunk 'célcsempe' attribútumát, és megkapjuk az x és y értékeit. Hozzáadunk 2 új doboz konténert: a 'Min távolság' és a 'Cél csempe index'. A 'Min távolság' kezdeti értékét 9999-re állítjuk, a 'Cél csempe index' értékét pedig 0-ra. A min távolságot magasan állítjuk, hogy a kezdeti távolság a legkisebb legyen. A célcsempe index az a referenciaindex a 'Szomszédos csempék' tömbben, amely a legkisebb távolságot mutat a célcsempe felé.

Fő célunk itt, hogy megkaphassuk a szomszédos csempe távolságot a 'Szomszédos csempék' tömbben, amelyik a legközelebb van a 'célcsempéhez'.

Photo_2019-07-29__6_47_43_PM.png

b. A csempe távolságának kiszámítása

Ebben a csomagban a számítást egy ciklusban végezzük el, amelyet minden szomszédos csempére végrehajtunk. A ciklus az 'szomszédos csempék számán' ismétlődik, és a ciklus indexét használva megszerezzük a 'Szomszédos csempék' tömb csempeértékét.

Kapjuk meg a csempe x és y értékeit, majd kiszámítjuk a távolságot a 'célcsempe' és a 'szomszédos csempe' x és y értékeivel a következő képlet alkalmazásával:

távolság = sqrt((x2 - x1)^2+(y2 - y1)^2)
x1 = Cél x
x2 = Szomszédos x
y1 = Cél y
y2 = Szomszédos y

Először levonjuk az x és y értékeket, majd megszorozzuk azt saját magával, hogy megkapjuk az exponenciális értékeket. Az így kapott értékeket összeadjuk, majd gyököt vonunk az összegből, hogy megkapjuk a távolság értékét.

Photo_2019-07-29__6_46_04_PM.png

Ha a 'Távolság' értéke kisebb, mint a 'Min távolság' doboz értéke, akkor beállítjuk a 'célcsempe index' értékét a ciklus aktuális indexére, amely a begyűjtött csempe indexe a 'Szomszédos csempék' tömbben. A 'Min távolság' doboz értékét a 'Távolság' értékre állítjuk, hogy a következő csempével hasonlíthassuk össze.

Miután a ciklus lezárult, összehasonlítottuk a szomszédos csempéinket, és megkaptuk az index értékét a csempének, amelyik a legközelebb van a 'célcsempéhez'.

Mozgás a szomszédos csempére

A bemutatónk utolsó csomagjában az avatárunkat a legközelebbi szomszédos csempére fogjuk mozgatni, és újra végrehajtjuk az egész 'Útvonalkereső' csomagot, ha még nem léptünk el a 'célcsempénktől'.

Photo_2019-07-30__1_23_31_PM.png

Először is ellenőrizzük, hogy az 'szomszédos csempék szám' nagyobb, mint 0. Ez biztosítja, hogy csak akkor mozgunk, ha legalább egy megbízható szomszédos csempét gyűjtöttünk be.

A 'Legközelebbi csempe' nevével az 'Cél csempe index' értékét fogjuk felhasználni, hogy megkapjuk a 'Szomszédos csempék' tömb jellemzőit.

Ahhoz, hogy megkapjuk azt a pontot, ahova az avatárunk elmozdul, szükségünk lesz a csempe x és y értékeire, és meg kell kapnunk a 'kezdő x' és 'kezdő y' attribútum értékeket a 'Rács' címkénkhez. Ezen értékek alapján adjuk hozzá a 'legközelebbi csempe' x értékét a 'kezdő x' értékhez, és ugyanígy a y értékek esetében is. Ezek az összeadott értékek a cél x és y pontok, ahová az avatárunk mozogni fog.

Az elmozdulás előtt állítsuk be az avatárunk 'korábbi csempe' értékét a jelenlegi 'csempe' attribútumának értékével. Ezt az 'csempe' értéket a korábbi csomagokból kaphatjuk meg. Ezután az avatárunkot a célpontokhoz mozgassuk 0.2 tartammal.

A 'Pontohoz mozgás' viselkedés befejezése után beállítjuk az avatáruk 'csempe' attribútumának értékét a 'legközelebbi csempe' tömb értékével. Ha a 'legközelebbi csempe' tömb értéke nem egyenlő a 'célcsempe' tulajdonsággal, akkor végrehajtjuk a 'Útvonalkereső' csomagot, tehát ismételjük az egész csomagot. A 'célcsempe' attribútum értéke a korábbi csomagból információval megkapható.

Ha megnyomjuk bármely kék csempét, és az avatárunk a rácsunkban megjelenik, az 'Útvonalkereső' csomag végrehajtódik. Ez elindítja az avatár mozgatását csempről csempre.

Következtetés

Ebben a bemutatóban megtanultuk, hogyan készítsünk egy objektumra alapuló útvonalkereső tevékenységet egy tömb segítségével, amelyet 'Rács'-nak nevezünk, ami tárolja az információt, hogy az adott csempe foglalt-e vagy sem. Bővítheti ezt az ötletet, hogy objektumok id-jait használja információtárolóként, nem csupán számokat a 'Rács' tömbben. Ez megbízhatóbb információt adhat, amelyet felhasználhatunk az útvonalkereséseknél. Például megkaphatjuk az objektum id attribútumait, hogy megtudjuk, hogy életben van-e vagy sem, és hogy léphetünk-e a csempéjére vagy sem.

Ez a bemutató csak az útvonalkeresés alapötletet szolgáltatta. Egy hátránya, hogy nem hoz létre a lehető legrövidebb utat a cél csempe felé, és csak a jelenlegi szomszédos csempéit ellenőrzi. Ez mozgási ciklushoz vezethet, amely nem visz sehová.

Ez azonban megoldható úgy, hogy bővítjük az útvonalkereső algoritmusunkat. Ezt megtehetjük úgy, hogy átirányítjuk a begyűjtött szomszédos csempéket, hogy megtalálják a szomszédos csempéket is, amíg el nem érjük a célcsempénket. Minden található legközelebbi szomszédos csempe hozzáadásra kerül egy listához. Az végtelen ciklus elkerülésére adjon hozzá egy feltételt, hogy ha az a szomszédos csempe már ellenőrzve van, akkor ez a csempe nem kerül hozzáadásra a listához. Szintén tegyen korlátot az iterációs számra, hogy elkerülje a célcsempe által okozott végtelen ciklust, ha az túl messze van, vagy nem található. Amint az iteráció megtalálja a célcsempét, kilépünk abból az iterációból, és elkezdjük az avatárunkat a csempről csempe mozgását a csempe listán keresztül.</p>