Rutenettbaserad vägledning
I den här handledningen kommer vi att göra en simuleringsupplevelse av vägförfinding baserat på ett tvådimensionellt array-gitter. Detta kommer att ge oss den grundläggande idén för att skapa vägförfindande aktiviteter för våra spel. Vi kommer att visualisera gitteret med tomma fyrkantiga objekt som plattor och ett runt objekt som vår avatar som kan röra sig inom det gitterområdet med vår kommando.
I. Sätta upp objekten
Vi kommer endast att använda fyra objekt i vårt projekt. Vår gröna avatar, en blå platta, en vit blockad och gitterets etikett för att ställa in och visualisera vårt gitter.
Avatar
Vår avatar är ett tomt objekt som har en x- och y-skala på 50%. Sätt dess kollision till en rund form så att den ser ut som den på bilden nedan. Detta objekt kommer att ha tre fördefinierade attribut: på plattan, tidigare platta och måltavleplatta. Sätt standardvärdena för dessa attribut till noll så att de inte får ett null-värde när vi försöker hämta dem senare.
Platta Objekt
Skapa ett annat tomt objekt som kommer att användas för att visualisera plattorna i vårt gitter. Dess skala är också 50% och har endast ett fördefinierat attribut: på plattan. Sätt också detta värde till noll.
Blockad Objekt
Skapa ett annat tomt objekt som kommer att fungera som blockader i vårt gitter. Detta är ett vitt tomt objekt med en skala på 40%. Vår avatar kommer inte att kunna förflytta sig till en platta som har en blockad ovanpå den.
Gitter Etikett
Detta är bara en etikett som kommer att ha de beteenden som tillåter inrättandet och visualiseringen av vårt gitter. Det har fördefinierade attribut: start x med ett värde av 4, och start y med ett värde av 3. Dessa värden är förskjutningar som kommer att användas som referenser när vi spawner våra plattor för att positionera vårt gitter snyggt i mitten.
Avatar/Platta Fördefinierade attribut:
Vi definierar en platta här som en 2-storleks array som kommer att ha ett x- och y-värde baserat på vårt gitter.
- på platta - detta är plattvärdet som vårt objekt för närvarande står på i vårt gitter
- tidigare platta - en platta som tidigare tramps av vår avatar
- måltavleplatta - den platta som vår avatar ska gå till
II. Sätta upp gitteret
Inuti gitter etiketten är där vi kommer att definiera vår 2D-array och spawna vårt gitter. Det finns 2 huvudsakliga nyckelpunkter i detta objekt: inställning av arrayen och visualisering av arrayen. Låt oss först göra inställningsarrayen.
Ställ in arrayen - paket
Först är det att skapa en tom array som heter 'Grid'. Denna array kommer att innehålla vår tvådimensionella array. Vi kommer att ha en boxbehållare som heter 'x radantal' som har ett värde av 24 och en annan tom array som heter 'y rad' som har 18 tomma värden.
Den första beteendet i vårt paket är en loop med upprepningstider av 'x radantal'. För varje steg i denna loop kommer vi att lägga till en tom y rad till 'Gitter array'. Detta kommer att skapa en array inom en array med en dimension av 24x18.
Observera att vi har kopplat en inaktiv kommentar i början av vårt paket för att förneka den automatiska exekveringen av detta rotbeteende. Ett rotbeteende är ett beteende som inte utlöses baserat på någon händelse och placeras öppet i gränssnittet.
Visualisera gitteret - paket
Den huvudsakliga uppgiften här är att traversera varje värde i vår 'Gitter array' och spawna ett platt objekt. Vi kommer också att lägga till ett villkor i vår loop som kommer att tillåta att spawnandet av en vit blockad på toppen av platt objektet.
Först är det att hämta arrayantalet av vår 'y rad array', 'start x'-attributvärdet av detta objekt och 'start y'.
Skapa en loop som har en upprepning av 'x radantal' och för varje steg i denna loop kommer vi att lägga till indexvärdet av den loopen och 'start x'-attributvärdet. Detta resulterar i en absolut x-position som vi kommer att använda för att positionera våra spawna plattor senare. Nästa är 'y rad loopen' som har en upprepning av 'y radantal'. För varje steg i denna loop kommer vi att lägga till indexvärdet av den loopen och 'start y'-attributvärdet, vilket nu resulterar i den absoluta y-positionen.
Efter att ha lagt till värdena under 'y rad loopen' är det att spawna det blå objektet. Sätt # av levande objekt av det till 999 eftersom vi kommer att behöva en massa av dem för vårt gitter, och även med en varaktighet av 0. Flytta sedan det spawnade objektet till en x-punkt med ett värde från x-loopen 'lägg till värden', och y-punkten med värde från y-loopen 'lägg till värden'.
Nästa är att lägga till en array med 2 tomma värden som heter 'På platta' som vi endast kommer att använda som en arrayplats. Efter att ha flyttat platt objektet, modifiera 'På platta'-arrayen genom att ersätta sitt värde vid index 0 med värdet av 'x rad loop'. Lägg sedan till en annan arraymodifiering som ersätter värdet vid index 1 med 'y rad index'. Detta är x- och y-koordinaterna för vårt gitter som objektet kommer att ha som ett 'på platta'-attribut.
Nu, sätt attributet för det spawnade objektet med en dynamisk nyckel, 'på platta', och med ett värde av 'På platta - array'.
Under y rad loopen, finns det villkoret för att spawn den vita blockaden. Vi kommer att ha en 2 av 5 chans att exekvera detta paket som kommer att lägga till randomiseringen av vårt gitter. Sedan kommer vi att flagga ett värde av 1 till x och y-koordinaten för det i vår 'Gitter' array som berättar att den koordinaten har en spawnad blockad.
Först är det att ha ett slumpmässigt nummer mellan 1 till 5. Om det numret är mindre än eller lika med 2, kommer vi att spawna blockaden. Sätt dess # av levande objekt till 999 och flytta det objektet till samma punkt som den blå plattan som vi spawna tidigare, och även med en varaktighet av 0.
Nästa är att spara informationen att denna koordinat var upptagen av en blockad, om den spawna. Vi gör detta genom att flagga den koordinaten med ett värde av 1. Först är det att få värdet vid index 'x rad loop' av 'Gitter' array. Detta värde ger oss en array av en 'y rad'. Vi kommer att modifiera denna 'y rad' genom att ersätta sitt värde vid index 'y rad loop' med värde 1, vilket är det flaggade värdet. Eftersom denna värdemodifiering endast gäller det värdet, och inte för 'Gitter själv', måste vi fortfarande modifiera 'Gitter' array. Ersätt värdet vid index 'x rad loop' av 'Gitter' array med ett värde av 'modifiera y rad - array'.
När den spelas, borde det resultera i denna typ av form.
III. På platta tryck
För att kunna interagera med gitteret självt, behöver vi ett paketbeteende när vi trycker på en blå platta. Det första trycket kommer att resultera i att vår avatar dyker upp i vårt gitter, och eventuella efterföljande tryck efter den händelsen kommer att påbörja dess vägförfinding.
Inuti det blå objektet finns ett beteendepaket som har 3 huvudpunkter: att återställa den tidigare plattan för vår avatar, ställa in dess på platta/ställ in dess måltavleplatta, och sedan sätta en färganimation för att visualisera tryckhändelsen på skärmen.
Först är det att få 'på platta'-attributen av platt objektet. Sätt attributet 'tidigare platta' för vår avatar till 0. Vår avatar kommer att sättas för att undvika att gå tillbaka till en 'tidigare platta' därför att vi återställer 'tidigare plattan' vid varje platt tryck.
Nästa är att få 'på platta'-attributet för vår avatar. Det första om-villkoret är om 'på platta'-värdet är lika med noll. Detta betyder att om avataren ännu inte har dykt upp, kommer detta att resultera i sant. Om det är sant, sätter vi dess 'på platta'-attribut med ett värde av platt objektets 'på platta'-attribut. Flytta sedan vår avatar till positionen genom att hämta positionen för platt objektet, peka dess x- och y-värden till den punkten med en varaktighet av 0.
Om 'på platta'-värdet inte är lika med noll. så sätter vi 'målplatta'-attributet för vår avatar med platt objektets 'på platta'-attributvärde. Detta betyder att vår avatar redan är i vårt gitter, och då kan vi exekvera beteendepaketet 'hitta väg'. Vi har fortfarande inte detta beteende ännu men vi kommer att åtgärda detta igen efter att ha gjort senare delen av denna handledning för 'hitta väg'-paketet.
Nu när vi har ordentligt ställt in vår avatar i vårt gitter, behöver vi bara visualisera denna tryckhändelse. Först är det att ha ett rotbeteende 'hämta färg' för att få dess ursprungliga färg. Sedan efter tryckhändelsen, kommer vi att sätta färgen på platt objektet till svart med en varaktighet av 0, och sedan sätta dess färg tillbaka igen till sitt ursprungliga värde med en varaktighet av 0.2.
Att trycka på en blå platta borde resultera i detta.
IV. Utför hitta väg paketet
För denna sista del av vår handledning kommer vi att göra algoritmen som tillåter oss att hitta den närmaste plattan som vår avatar kan ta för att nå sitt mål. Detta paket kommer att exekveras upprepade gånger för varje plattsteg som vår avatar rör sig på vårt gitter.
Vi kommer att ställa in algoritmen inuti vårt avatar-objekt och det kommer att ha tre huvudpunkter: att hitta angränsande plattor, hitta den närmaste angränsande plattan och rörelsen till den angränsande plattan.
Hitta de angränsande plattorna
I denna del kommer vi att samla alla angränsande plattor som vår avatar skulle kunna förflytta sig till. Vi kommer att kontrollera dess fyra riktningar angränsande plattor och se om de plattorna har en blockad ovanpå den eller om den har trampats tidigare.
Först är det att lägga till vår 'Angränsande plattor' array. En 'Riktning' array med 2 tomma värden, och de fyra riktade arrayerna som har 2 värden för varje: N (0,1), S (0,-1), E (1,0), V ( -1,0).
Det första beteendet i vårt paket är att rensa våra angränsande plattor. Eftersom vi kommer att göra detta paket flera gånger, behöver vi ha våra insamlade 'angränsande plattor' återställas varje gång. De nästa fyra beteendena är modifieringar till 'Riktning'-arrayen. Vi sätter arrayerna att 'Riktning'-arrayen fyra gånger med de fyra riktade arrayerna, och sedan exekverar paketet nedan. Vi gör detta för att skapa en loop med olika 'Riktning' arrayvärden varje gång.
Nu när vi har riktningen, behöver vi bara kombinera deras x- och y-värden med 'på platta'-attributet för vår avatar. Sedan kommer vi att kunna få vårt målvärde i 'Gitter'-arrayen för att veta om den plattan var flaggad med en blockad.
'Riktning x' är värdet av 'Riktning'-arrayen vid index 0, 'hämta på platta' x är värdet av 'hämta på platta' vid index 0. Målet x är de adderande värdena av 'riktning x' och 'hämta på platta x'. Detsamma gäller för y-värden men med ett målvärde på index 1.
'Mål y rad' är arrayvärdet i 'Gitter'-arrayen vid index 'Mål x'. Och sedan kommer 'Målindex i y rad' att vara värdet av 'Mål y rad' array vid index för 'Mål y'. Det är koordinaten i vårt gitter som kan berätta för oss om den flaggades med en blockad.
Om värdet i 'Målindex i y rad' är 1, då flaggades den måltavleplattan som blockerad. Men om värdet inte är lika med 1, kan vi fortsätta i vårt paket.
Eftersom vår mål x och y passerade vårt villkor, har vi lagt till en ny tom platta array som heter 'Ny angränsande platta'. Detta kommer att lagra värdena för mål x och y som en platta array. Vi kommer att sätta värdet av mål x till index 0 i 'Ny angränsande platta' och mål y till dess index 1.
Nu hämta 'tidigare platta'-attributen för vår avatar. Om 'tidigare platta' inte är lika med 'ny angränsande platta', skulle det innebära att den nya plattan inte trampats tidigare. Då kan vi tryggt lägga till 'Ny angränsande platta' i 'Angränsande plattor'-arrayen genom att bifoga den. Vi kommer att ställa värdet av den 'tidigare plattan' senare efter att ha flyttat vår avatar till en annan platta.
"Du kan utöka detta paket genom att göra en 8 riktad arrayer vilket tillåter din avatar att röra sig i diagonal riktning."
Hitta den närmaste angränsande plattan
Nu när vi har samlat våra pålitliga angränsande plattor, behöver vi bara få den angränsande plattan som är närmast vår avatars måltavleplatta. Vi kommer att göra beräkningen genom att använda en avståndsformel som tillhandahålls av x och y-värdena för vår måltavleplatta och de angränsande plattorna.
Det finns två viktiga punkter i detta paket: initialiseringen av variabler för beräkning och beräkningen av plattors avstånd inuti en loop.
a. Initialisering av variabler
Först är det att få arrayantalet av våra angränsande plattor. Sedan får vi 'målplatta'-attributet för vår avatar och får dess x- och y-värden. Vi kommer att lägga till 2 nya boxbehållare: 'Min avstånd' och 'Målplattaindex'. Vi sätter det initiala värdet av 'Min avstånd' till 9999, och värdet av 'Målplattaindex' till 0. Min avståndet sätts till ett högt nummer eftersom vi behöver den minsta avståndet från start. Målplattaindex är vårt referensindex i 'Angränsande plattor'-arrayen som har den minsta avståndet till vår 'måltavleplatta'.
Vårt huvudmål här är att få indexet för plattan inuti vår 'Angränsande plattor'-array som är närmast vår 'målplatta'.
b. Beräkning av plattors avstånd
I detta paket kommer vi att göra beräkningen inuti en loop som vi kommer att göra för varje angränsande platta. Loopen upprepas av 'antal angränsande plattor' och vi kommer att få plattvärdet av 'Angränsande plattor'-arrayen genom att använda indexet för den loopen.
Hämta x- och y-värdena för den angränsande plattan och sedan får vi avståndet mellan vår 'målplatta' och den 'angränsande plattan' med hjälp av denna formel:
avstånd = sqrt((x2 - x1)^2+(y2 - y1)^2)
x1 = Mål x
x2 = Angränsande x
y1 = Mål y
y2 = Angränsande y
Vi subtraherar först deras x- och y-värden, multiplicerar det med sig själv för att få deras exponentiella värden, lägger till dessa värden och tar kvadratroten av de tillagda värdena för att få avståndsvärdet.
Om 'Avstånd'-värdet är mindre än 'Min avstånd'-boxbehållarens värde, kommer vi då att sätta värdet 'målplattaindex' till det aktuella indexet i loopen, vilket är indexet av vår hämtade platta inuti 'Angränsande plattor'-arrayen. Vi sätter också 'Min avstånd'-boxbehållarens värde till 'Avstånd'-värdet för att jämföra detta med nästa platta av vår loop.
Efter loopens slut har vi jämfört var och en av våra angränsande plattor och vi har fått indexvärdet för den angränsande plattan som är närmast vår 'målplatta'.
Rörelse till den angränsande plattan
I detta sista paket av vår handledning, kommer vi att flytta vår avatar till den närmaste angränsande plattan och göra om hela 'Hitta väg'-paketet om vi inte redan har flyttat till vår 'målplatta'.
Det första som ska göras är att kontrollera om vår 'Antal angränsande plattor' är större än 0. Detta är för att säkerställa att vi bara flyttar om vi har hämtat minst en pålitlig angränsande platta.
Då 'Hämta den närmaste plattan' genom att använda vårt 'Målplattaindex'-värde från det föregående paketet för att få arrayvärdet av 'Angränsande plattor'-arrayen.
För att få exakt den punkt där vår avatar kommer att flytta till, behöver vi x- och y-plattvärdena för den plattan, och också få 'start x' och 'start y'-attributvärdena av vår 'Gitter'-etikett. Vi lägger sedan till x-värdet av vår 'närmaste platta' och 'start x'-värdet, och även detsamma med y-värdena. Dessa tillagda värden är våra mål x- och y-punkter där vår avatar kommer att flytta till.
Innan vi flyttar till den punkten, sätter vi vår avatars 'tidigare platta' med dess aktuella 'på platta'-attributvärde. Vi kan få detta 'på platta'-värde från de tidigare paketen. Vi flyttar sedan vår avatar till våra målpunkter, med en varaktighet av 0.2.
Efter slutförandet av 'Flytta till punkt'-beteendet sätter vi nu 'på platta'-attributvärdet för vår avatar med värdet från 'Hämta närmaste platta'-arrayen. Om 'Hämta närmaste platta'-arrayen inte är lika med vår 'målplatta', kommer vi att exekvera 'Hitta väg'-paketet, och således göra om hela paketet igen. 'Målplatta'-attributvärdet kan hämtas från det föregående paketet.
Genom att trycka på vilken blå platta som helst, och efter att vår avatar har dykt upp i gitteret, kommer 'Hitta väg'-paketet att exekveras. Detta kommer att trigga avatarens rörelse från platta till platta.
Slutsats
I denna handledning har vi lärt oss att göra en vägförfindande aktivitet med ett objekt med hjälp av en array som vi kallade 'Gitter', som används för att lagra information om huruvida den plattan var upptagen eller inte. Du kan utvidga denna idé genom att använda objekts-id som informationslagring istället för bara ett siffervärde för vår 'Gitter'-array. Detta kommer att ge oss mer pålitlig information som vi kan använda när vi gör vägförfinding. Till exempel kan vi få attributen för det objekt-id:t för att veta om det är levande eller inte, huruvida det kommer att tillåta oss att gå på dess platta eller inte.
Denna handledning gav endast den grundläggande idén bakom vägförfinding. En nackdel med detta är att det inte skapar den kortaste vägen till en måltavleplatta, och endast kontrollerar dess nuvarande angränsande platta. Detta kan resultera i en rörelse-loop som inte når någonstans.
Men detta kan lösas genom att utöka vår vägförfindande algoritm. Vi kan göra detta genom att återkomma till våra hämtade angränsande plattor för att få deras angränsande plattor också tills vi hittar vår måltavleplatta. Varje hittad närmaste angränsande platta kommer att läggas till en lista. För att förhindra en oändlig loop, lägg till en villkor som om den angränsande plattan redan har kontrollerats, så kommer den plattan inte att läggas till vår lista. Lägg också till en maximal gräns på iterationsantalet för att förhindra en oändlig loop vilket orsakas av måltavleplattan om den är för långt borta eller inte går att hitta. När iterationen hittar måltavleplattan, avslutar vi sedan den iterationen och börjar flytta avatar från platta till platta med hjälp av plattlistan.

