Primêre Hernuwing vir die Skep van die Isometriese Wêreld, Deel 2
Aan die einde van hierdie tutoriaalreeks bou ons die eerste tutoriaal en leer oor die aanwending van bakkie, sneller, vlakskakelaar, padsoektog, volg pad, vlakrol, isometriese hoogte en isometriese projektiele.
Pickup is 'n item wat op vlakke versamel kan word, gewoonlik deur net daarop te stap - byvoorbeeld, munte, juwele, kontant, ammunisie, ens.
Afhaaldata kan direk by ons vlak data ingesluit word soos hieronder:
In hierdie vlak data gebruik ons ​​8 om 'n bakkie op 'n grasveld te noem (1 en 0 verteenwoordig mure en loopbare teëls onderskeidelik, soos voorheen). Dit kan 'n enkele teëlbeeld wees met 'n grasveld wat oor die bakkie oorgelaat word. Deur hierdie logika te gaan, benodig ons twee verskillende teëlstate vir elke teël wat 'n bakkie het, dit wil sê een met bakkie en een sonder om getoon te word nadat die bakkie versamel is.
Tipiese isometriese kuns sal veelvoudige loopbare teëls hê - dink ons ​​het 30. Bogenoemde benadering beteken dat as ons N bakkies het, benodig ons N x 30 teëls bykomend tot die 30 oorspronklike teëls, aangesien elke teël een weergawe moet hê met bakkies en een sonder. Dit is nie baie doeltreffend nie; In plaas daarvan moet ons probeer om hierdie kombinasies dinamies te skep.
Om dit op te los, kan ons dieselfde metode gebruik om die held in die eerste handleiding te plaas. Wanneer ons 'n bakkie teëkom, plaas ons eers 'n grasveld en plaas dan die bakkie bo-op die grasveld. Op hierdie manier benodig ons net N bakkie teëls bykomend tot 30 loopbare teëls, maar ons benodig getalwaardes om elke kombinasie in die vlakdata te verteenwoordig. Om die behoefte aan 'n N x 30-verteenwoordigingswaarde aan te spreek, kan ons 'n aparte pickupArray hou om uitsluitlik data vir die herwinning van die vlakdata op te slaan. Die levelData.met die bakkie voltooi is, word hieronder getoon:
Vir ons voorbeeld, ek hou dinge eenvoudig en gebruik nie ekstra skikkings vir bakkies nie.
Opsporing van bakkies word op dieselfde manier gedoen as om botsings teëls vas te stel, maar na die karakters te beweeg.
In die funksie onPickupTile () controleert ons of die waarde van die levelData skikking in heroMapTile koördinate 'n bakkie is of nie. Die getalle in die vlakData skikking op die teëlkoördinate dui op die tipe oprit. Ons het die botsing nagegaan voordat ons die karakters verhuis het, maar daarna moet ons die bakkie nagaan. In geval van botsing moet die karakter nie die plek beset as dit deur die botsingstene beset word nie, maar in die geval van bakkie beweeg die vrye karakter meer as dit.
Nog 'n ding om daarop te let, is dat botsingsdata gewoonlik nooit verander nie, maar die data-optel verander elke keer as ons 'n item optel. (Dit behels gewoonlik net om die waarde in 'n vlakdata skikking te verander van, sê 8 tot 0.)
Dit lei tot 'n probleem: wat gebeur wanneer ons die vlak moet herlaai en sodoende alle bakkies terugstel na hul oorspronklike posisies? Ons het geen inligting om dit te doen nie, omdat die levelData skikking verander is wanneer die speler die item herwin. Die oplossing is om 'n duplikaat skikking te gebruik om te vlak terwyl jou speel, en om die oorspronklike levelDataskikking intact te hou. Byvoorbeeld, ons gebruik levelData en levelDataLive , kloneer laasgenoemde van die voormalige aan die begin van die vlak en verander slegs levelDataLive  tydens die spel.
Vir die voorbeeld maak ek 'n ewekansige bakkie op 'n oop grasseël na elke bakkie en verhoog die pickupCount. Die pickupItem funksie lyk soos volg.
Jou moet oplet dat ons die bakkie nagaan wanneer die karakter in die teël is. Dit kan verskeie kere in een sekonde gebeur (ons kyk net na wanneer die gebruiker beweeg, maar ons kan in die teël draai), maar die logika hierbo sal nie misluk nie. Omdat ons die data array levelData op 0 stel wanneer ons die afhaalproses eers opspoor, sal alle daaropvolgende tjeks opPickupTile () vals na daardie teël terugkeer. Check out the interactive example below:
Soos die naam aandui, veroorsaak 'n teël-sneller iets om te gebeur wanneer 'n speler daaraan stamp of 'n knoppie druk wanneer dit daarop staan. Hulle mag spelers verskuif na verskillende plekke, oop hekke, of kuit vyande, om voorbeelde te gee. Op 'n sekere manier, bakkies is net 'n spesiale vorm van sneller teëls: wanneer die speler op 'n teël stamp wat 'n muntstuk bevat, verdwyn die munt en die muntentoonbank verhoog.
Kom ons kyk hoe ons 'n deur kan implementeer wat die speler na 'n ander vlak neem. Die teël langs die deur sal 'n trekkers wees; wanneer die speler die x sleutel druk, sal hulle voortgaan na die volgende vlak.
Om vlakke te verander, moet ons net die huidige levelData skikking ruil met die van die nuwe vlak en stel die nuwe heroMapTile posisie en rigting vir die held karakter neer. Gestel daar is twee vlakke met 'n deur om tussen hulle te laat slaag. Aangesien die grond teël langs die deur die snyer sal wees op beide vlakke, kan ons dit as 'n nuwe posisie vir die karakter gebruik wanneer dit op die vlak voorkom.
Die implementeringslogika hier is dieselfde as vir bakkies, en weer gebruik ons ​​die levelData array om snellerwaardes te stoor. Vir ons voorbeeld, dui 2 'n deurteël aan, en die waarde daaraan is die sneller. Ek het 101 en 102 gebruik met die basiese konvensie dat elke teël met 'n waarde groter as 100 'n snellerteël is en 'n waarde van minus 100 kan 'n vlak wees wat lei tot:
Die kode om na sneller gebeurtenisse te kyk word hieronder getoon:
Die funksie triggerListener () kontroleer of die waardes van die sneller data in die gegewe koördinate groter as 100 is. Indien wel, vind ons watter vlak ons ​​moet herlei deur 100 van die plotwaarde af te trek. Hierdie funksie vind 'n sneller plot in die nuwe levelData, wat die plek sal wees om te sproei vir ons held. Ek het 'n sneller geskep om te brand wanneer x vrygestel word; As ons net luister na die sleutel wat gedruk word, sal ons eindig in 'n lus waar ons tussen vlakke wissel, solank as wat die sleutel gedruk word, omdat die karakter altyd op 'n nuwe vlak bo die snellerpaneel verhoog.
Hier is 'n werkende demo. Probeer om items op te tel deur oor hulle te loop en vlakke te wissel deur langs deure te staan ​​en x te slaan.
'N Projektiel is iets wat met 'n bepaalde spoed in 'n bepaalde rigting beweeg, soos 'n koeël, 'n magiese spel, 'n bal, ens. Alles oor die projektiel is dieselfde as die held karakter, afgesien van die hoogte: In plaas daarvan om op die grond te rol, dryf die projektiele dikwels op 'n sekere hoogte. 'N Koeël sal bo die middellyf van die karakter beweeg, en selfs 'n bal moet dalk rondbons.
Een interessante ding om daarop te let, is dat die isometriese hoogte gelyk is aan die hoogte van die 2D kant, hoewel dit kleiner in waarde is. Geen ingewikkelde omskakelings betrokke nie. As 'n bal 10 karakters bo die grond in Cartesiese koördinate is, kan dit 10 of 6 pixels bo die grond in isometriese koördinate wees. (In ons geval is die betrokke as die y-axis.)
Kom ons probeer om 'n weerkaatsbal in ons ommuurde wei toe te pas. As 'n aanraking van realisme, sal ons 'n skaduwee by die bal voeg. Al wat ons moet doen, is 'n hoë waarde van die refleksie van ons bal isometriese Y waarde. Die spring hoogte waarde sal verander van raam tot raam afhangende van die swaartekrag, en sodra die bal die grond tref, sal ons die huidige snelheid langs die y-axis flip.
Voordat ons die weiering in die isometriese stelsel oorwin, sal ons sien hoe ons dit in die Cartesiese 2D-stelsel kan toepas. Kom ons verteenwoordig die springkrag van die bal met 'n veranderlike zValue. Stel jou voor dat die bal eers 'n sprongkrag van 100 het, dus zValue = 100.
Ons sal nog twee veranderlikes gebruik: incrementValue, wat by 0 begin en gravitasie, wat 'n waarde van -1 het. Elke raam, ons trek incrementValue uit zValue, en trek swaartekrag uit incrementValue om 'n demper effek te skep. Wanneer zValue 0 bereik, beteken dit dat die bal die grond bereik het; Op hierdie punt flip ons die teken van incrementValue deur dit te vermenigvuldig met -1, om dit in 'n positiewe getal te maak. Dit beteken die bal sal van die volgende raam opwaarts beweeg, so dit stuit.
Hier is wat jou in die kode sien:
Die kode bly dieselfde vir isometriese aansigte, met min verskil dat jou 'n laer waarde kan gebruik vir die opstel van zValue. Kyk hieronder hoe zValue bygevoeg word aan die isometriese ywaarde van die bal tydens die lewering.
Kyk na die interaktiewe voorbeeld hieronder:
Verstaan ​​dat die rol wat die skaduwee speel, 'n baie belangrike ding is wat by die realisme van hierdie illusie voeg. Ook, let op dat ons nou twee skermkoördinate gebruik (x en y) om die drie dimensies in die isometriese koördinate te verteenwoordig - die y-axis by die skermkoördinate sowel as die z-as in die isometriese koördinate. Dit kan verwarrend wees!
4. Vind en Volg diePad
Pad vind en pad volg is 'n ingewikkelde proses. Daar is verskillende benaderings wat verskillende algoritmes gebruik om paaie tussen twee punte te vind, maar omdat ons levelData 'n 2D-skikking is, is alles makliker as wat dit mag wees. Ons het goed gedefinieerde en unieke nodusse wat die speler kan beset, en ons kan maklik kyk of hulle loopbaar is.
A * Pathfinder vir Beginners
Doelge-Baseerde Vektor Veldopvoering
Spoed 'n * Pathfinding Met die Spring Point Soek Algoritme
Die "Padvolgende" Bestuursgedrag
Die gedetailleerde beskrywing van die paaieindelingsalgoritme val buite die omvang van hierdie artikel, maar ek sal probeer om die mees algemene manier van werk te verduidelik: die kortste padalgoritme, waar die A * en Dijkstra algoritmes bekende implementerings is.
Ons poog om 'n nodus te vind wat die aanvanklike nodus en die finale nodus verbind. Van die aanvanklike nodus het ons die agt aangrensende nodusse besoek en almal gemerk soos dit besoek is; hierdie kernproses word herhaal vir elke nuutbesoekte node,rekursief.
Elke draad volg die besoekende nodus. Wanneer daar na die naburige nodusse gespring word, word nodes oorgeslaan (rekursiestop); Anders gaan die proses voort totdat ons die finale nodus bereik, waar die rekursie eindig en die volledige pad gevolg word, word teruggegee as 'n nodusreëling. Soms word die einde van die node nooit bereik nie, in welke geval die padpaadjie misluk. Ons eindig gewoonlik met verskeie paaie tussen twee nodusse, in welke geval ons een neem met die kleinste aantal nodusse.
Aangesien ons levelData slegs 0 en 1 het, kan ons dit direk as die nodus skikking inskryf. Ons stel die waarde van 0 as die loopbare nodus in. Ons aktiveer diagonale loopvermoë, maar skakel dit uit as u naby die hoeke van nie-loopbare teëls loop.
Dit is omdat, indien geaktiveer, die held dalk in die nie-loopbare teël kan sny terwyl hy 'n diagonale loop doen. In so 'n geval sal ons botsingsopsporing nie die held toelaat om deur te gaan nie. Let ook daarop dat ek in my voorbeeld die botsingsdeteksie heeltemal uitgevee het omdat dit nie meer benodig word vir 'n AI-gebaseerde lopende instansie nie.
Sodra ons die pad as 'n nodus skikking het, moet ons die karakters daarop volg.
Kom ons sê ons wil die karakter loop na die teël waarop ons gekliek het. Eerstens moet ons die pad vind tussen die nodus wat die karakter tans beset en die nodus waar ons geklik het. If a successful path is found, then we need to move the character to the first node in the node array by setting it as the destination. Sodra ons by die bestemmingsknoppie kom, maak ons ​​seker of daar meer nodusse in die skikkingsknoppie is en stel ons die volgende knoppie as die bestemming in - totdat ons die laaste nodus bereik.
Ons sal ook die rigting van die speler verander op grond van die huidige nodus en die nuwe bestemmingsnodus elke keer as ons die nodus bereik. Onder die knope, Ons loop net in die verlangde rigting totdat ons die bestemmingsknop bereik. Dit is 'n baie eenvoudige AI, en in hierdie voorbeeld word dit gedoen in die aiWalk metode wat gedeeltelik hieronder getoon word.
Ons doen moet geldige klikpunte filter deur te bepaal of ons in 'n loopbare area gekliek het, eerder as 'n muurkruip of 'n ongekakte teël
Nog 'n interessante punt vir AI-kodering: ons wil nie hê dat die karakter die volgende teël in die knooppunt moet sien sodra dit by die huidige een kom nie, want 'n onmiddellike beurt lei tot ons karakters op die teëlgrens loop. In plaas daarvan moet ons wag totdat die karakter 'n paar tree in die teël is voordat ons die volgende bestemming soek. Dit is ook beter om die held in die middel van die huidige teël hand te plaas net voor ons omdraai, om alles perfek te laat voel.
Kyk na die werk demo hieronder:
5. Isometriese Scrolling
Wanneer die vlakarea baie groter is as die beskikbare skermarea, moet ons dit maak boek.
Die sigbare skermarea kan beskou word as 'n kleiner reghoek binne die groter reghoek van die volledige vlakarea. Scrolling beweeg in wese net die binneste reghoek in die groter een. Gewoonlik, wanneer sulke blaai gebeur, bly die posisie van die held dieselfde met betrekking tot die skerm reghoek, gewoonlik by die skermsentrum. Interessant genoeg, al wat ons nodig het om te blaai, is om die binneste reghoekige hoekpunt te spoor.
Hierdie hoekpunt, wat ons in Cartesiese koördinate verteenwoordig, val binne 'n teël in die vlakdata. Om te rol, verhoog ons die posisie van x en y vanaf die hoekpunt in Cartesiese koördinate. Nou kan ons hierdie punt omskakel in isometriese koördinate en gebruik dit om die skerm te teken.
Die nuut omskakelde waardes, in die isometriese ruimte, moet ook ons ​​hoek van die skerm wees, wat beteken dat hulle nuut is (0, 0). So, wanneer ons die vlak data ontsyfer en teken, trek ons ​​hierdie waarde af van die isometriese posisie van elke teël, en kan bepaal of die nuwe posisie van die teël binne die skerm is.
Alternatiewelik kan ons besluit dat ons slegs die xxY isometriese teëls op die skerm teken om die beeldkringe doeltreffend te maak.
Ons kan dit openbaar in stappe soos:
Werk die x en y koördinate van Cartesiese by.
Verander dit in 'n isometriese ruimte.
Trek hierdie waarde af van die isometriese trekposisie van elke teël.
Teken slegs die aantal vooraf gedefinieerde teëls op die skerm wat vanaf hierdie nuwe hoek begin.
Opsioneel: Teken slegs 'n teël as die nuwe isometriese posisie binne die skerm val.
Let asseblief daarop dat die puntpunt by in die teenoorgestelde rigting deur die held se posisie te vernuwe terwyl hy beweeg. Dit verseker dat die held op die skerm bly. Kyk na hierdie voorbeeld (gebruik die pyltjies om te blaai, tik om die sigbare rooster te verhoog).
Terwyl ons blaai, moet ons dalk ekstra teëls op die skermgrens trek, of ons kan sien dat die teëls verdwyn en op die uiterste skerm verskyn.
As jy teëls het wat meer as een spasie opneem, moet jy meer teëls op die grens teken. Byvoorbeeld, as die grootste teël in alle stelle X-grootte deur Y, dan moet jy X meer teëls na links en regs teken en Y meer teëls op en af. Dit verseker dat 'n groter teëlhoek sigbaar bly wanneer jou in of uit die skerm blaai.
Ons moet steeds seker maak dat ons nie 'n leë area op die skerm het nie, aangesien ons die vlakgrens nader. of gaan uit van die skerm.
Die vlak moet net skuif totdat die mees ekstreme teëls op die betrokke skerm geteken word. Daarna moet die karakter in die skermspasie beweeg sonder om die vlak te skuif. Vir hardie, kita perlu melacak keempat sudut layar dalam persegi panjang, dan mencekik gerakan bergulir dan logika gerakan yang sesuai. Apakah Anda siap menghadapi tantangan untuk mencoba menerapkan itu untuk diri Anda sendiri?
Hierdie reeks is hoofsaaklik bedoel vir beginners wat probeer om die wêreld van isometriese speletjies te verken. Baie van die konsepte wat beskryf word, het 'n effens meer komplekse alternatiewe benadering, en ek het doelbewus die maklikste gekies.
Hulle sal dalk nie die meeste van die scenario's wat jy mag ondervind ontmoet nie, maar die kennis wat verkry word, kan gebruik word om hierdie konsepte te bou om meer komplekse oplossings te skep. Byvoorbeeld, die eenvoudige diepte sortering wat geïmplementeer word, sal breek as ons meervlakvlakke het en platformtegels beweeg van een storie na 'n ander.