Bygg et Endless Runner-spill fra bunnen av Hindringer og fienden

Velkommen til den sjette delen i vår Endless Runner opplæringsserie! Vårt spill begynner å forme seg og føle seg mer polert. Etter å ha fullført dagens skritt, blir det mye mer interaktivt og morsomt å spille. Vi legger til to hendelser som vil skape noen spennende nye utfordringer for spillerne. Først vil vi legge til evnen til vår helt å brenne en liten bolt for å fjerne hindringer som kommer mot ham. Husk at det lille "blåaktig" bildet blir sparket fra vårt monster. Bildene vi jobber med, er ikke spesielt profesjonelle siden de bare er for øvelser. Etter at monsteret har evnen til å skyte noen bolter, vil vi også legge til hendelser som vil sende hindringer som kommer tilbake mot ham. Etter det vil vi skape to typer hindringer: den første er en spikemur som sitter på bakken og reiser i samme hastighet som bakken, og den andre er et spøkelse som vil fly inn fra øvre høyre side av skjermen mot spilleren.

Så, la oss komme i gang! Det første vi må gjøre er å sørge for at vi har alle eiendelene på rett sted. Last ned filen som er vedlagt denne opplæringen, og i den "nye" mappen finner du tre nye eiendeler. Du kan også bare høyreklikke på bildene og lagre dem i riktig mappe. Bildene skal bli kalt spikeBlock.png, ghost.png og blast.png.

Åpne din main.lua-fil som finnes i den "gamle" mappen i opplæringsdownloadene. Vi vil starte med å gi våre spillere muligheten til å brenne fordi vi ikke vil forlate dem forsvarsløse da de blir bombardert med nye utfordringer! Vi kan legge til denne evnen i tre trinn. Den første vil instantiere 5 bolter og sette dem i en gruppe. I stedet for å lage og ødelegge objekter hver gang vi vil bruke dem, kan vi være mer effektive ved å forberede dem og lagre dem på skjermen til vi trenger å bruke dem. Vi skal faktisk gjøre det samme for hver av de tre forskjellige bildene, så fortsett og legg til denne koden mellom hvor vi erklærer variabel hastighet og hvor vi lager våre blokker.

 --lage spøkelser og sett deres posisjon for å være utenfor skjermen for a = 1, 3, 1 gjør ghost = display.newImage ("ghost.png") ghost.name = ("spøkelse" ... a) ghost.id = et spøkelse. x = 800 ghost.y = 600 ghost.speed = 0 --variable brukes til å avgjøre om de er i spill eller ikke ghost.isAlive = false - gjør spøkelsene gjennomsiktige og mer ... ghostlike! ghost.alpha = .5 spøkelser: sett inn (spøkelse) ende - opprett spikes for a = 1, 3, 1 spike = display.newImage ("spikeBlock.png") spike.name = ("spike" ... a) spike .id = en spike.x = 900 spike.y = 500 spike.isAlive = falske pigger: sett inn (spike) ende - skape eksplosjoner for a = 1, 5, 1 do blast = display.newImage ("blast.png" ) blast.name = ("blast" ... a) blast.id = en blast.x = 800 blast.y = 500 blast.isAlive = falske blaster: sett inn (blast) end

Legg merke til at de alle har noen vanlige funksjoner. Vi må gå gjennom og nevne dem dersom vi noen gang vil referere dem individuelt. Vi gir dem et ID, og ​​gir oss også fremtidige referansemuligheter. Vi gir dem sine offscreen x og y koordinater (vi stable lignende bilder ovenpå hverandre). En annen ting vi gir dem alle er variabelen 'levende'. Dette er satt til false som standard som de vil sitte av skjermen. Å gi sprites denne variabelen vil tillate oss å raskt sjekke om sprite er i bruk eller ikke. Den eneste sprite som har noe annerledes er spøkelsespriten. For spøkelsessprites legger vi til en hastighetsvariabel slik at vi kan få spøkelser som beveger seg med tilfeldige hastigheter. Vi vil også sette spøkelsens alpha til .5 slik at de vises mer, skal vi si, spøkelsesaktig!

De to neste tingene vi må gjøre er å opprette sine respektive visningsgrupper, og legg deretter til de gruppene i skjermbildesgruppen slik at vi kan se dem i spillet. Legg til disse rett under de andre skjermgruppenees instantiering.

 lokale spøkelser = display.newGroup () lokale spikes = display.newGroup () local blasts = display.newGroup ()

Deretter går du ned til delen der vi legger til alt på skjermen. Legg til disse skjermgruppene med resten. Jeg ville få den nye bestillingen til å se noe ut som dette:

 --mesteparten av bestillingen her er ikke noe som helst så lenge bakgrunnene er - i baksiden og spøkelsene og monsteret er på slutten skjermen: sett inn (backbackground) skjerm: sett inn (backgroundfar) skjerm: sett inn (backgroundnear1) skjerm: sett inn (backgroundnear2) ) skjerm: sett inn (blokker) skjerm: sett inn (spikes) skjerm: sett inn (blasts) skjerm: sett inn (spøkelser) skjerm: sett inn (monster) skjerm: sett inn (collisionRect)

Når du har alt der inne, bør det se slik ut om du skulle kjøre det i iPhone 4-perspektivet:

Etter å ha fått det på plass, legger vi til funksjonen som oppdaterer alle boltene som vårt monster skyter. Legg til følgende funksjon under funksjonen checkCollisions ().

 funksjon updateBlasts () - for hver eksplosjon som vi instanser, sjekk for å se hva det gjør for a = 1, blasts.numChildren, 1 gjør - hvis blast ikke er i spill, trenger vi ikke å sjekke noe annet hvis blasts [a] .isAlive == true) da (blasts [a]): translate (5, 0) - hvis blastet har flyttet av skjermen, drep det og returner det til det opprinnelige stedet hvis a] .x> 550) så blaster [a] .x = 800 blaster [a] .y = 500 blaster [a] .isAlive = falsk ende ende - kontroller for kollisjoner mellom blastene og pigger for b = 1, spikes.numChildren, 1 gjør hvis (pigger [b] .isAlive == true) så hvis (blasts [a] .y - 25> pigger [b] .y - 120 og blasts [a] .y + 25 < spikes[b].y + 120 and spikes[b].x - 40 < blasts[a].x + 25 and spikes[b].x + 40 > blaster [a] .x - 25) så blaster [a] .x = 800 blaster [a] .y = 500 blaster [a] .isAlive = falske pigger [b] .x = 900 pigger [b] .y = 500 spikes [b] .isAlive = falsk ende ende ende - kontroller for kollisjoner mellom blastene og spøkelsene for b = 1, ghosts.numChildren, 1 gjør hvis (spøkelser [b] .isAlive == true) så hvis (blasts [ a] .y - 25> spøkelser [b] .y - 120 og blasts [a] .y + 25 < ghosts[b].y + 120 and ghosts[b].x - 40 < blasts[a].x + 25 and ghosts[b].x + 40 > blaster [a] .x - 25) så blaster [a] .x = 800 blasts [a] .y = 500 blasts [a] .isAlive = falske spøkelser [b] .x = 800 spøkelser [b] .y = 600 spøkelser [b] .isAlive = falske spøkelser [b] .speed = 0 endeendens ende ende

Ovennevnte funksjon skal ha to hovedansvar. Den første er å oppdatere posisjonen til eksplosjonen og se om den kolliderte med noe. Du kan se at når det kolliderer med noe, er måten vi ødelegger det å bare flytte det fra skjermbildet og sett til å falle. Dette vil få bolten klar til bruk igjen. Noe annet som du kanskje har lagt merke til er at vi bare oppretter fem bolter. Så, hva skjer hvis alle fem bolter allerede er i spill og brukeren prøver å brenne en annen blast? Ingenting! Med måten den er satt opp akkurat nå, er brukeren begrenset til å bare ha fem aktive blaster på en gang. Dette er lett å endre ved å instantiere mer i begynnelsen av spillet, men det viser deg hvordan du setter grenser til spillere. Dette er også en metode vi vil bruke for å sikre at 50 spøkelser ikke tilfeldigvis genererer alt på en gang på skjermen, og dreper spilleren umiddelbart.

Deretter må vi gå ned til berørt funksjon for å gi spilleren muligheten til å skyte. Endre berørt funksjon for å matche følgende:

 --Den eneste forskjellen i berørt funksjon er nå hvis du berører den høyre siden av skjermen, vil monsteret brenne av en liten blå bolt-funksjon berørt (hendelse) hvis (event.phase == "startet") så hvis (hendelse. x < 241) then if(onGround) then monster.accel = monster.accel + 20 end else for a=1, blasts.numChildren, 1 do if(blasts[a].isAlive == false) then blasts[a].isAlive = true blasts[a].x = monster.x + 50 blasts[a].y = monster.y break end end end end end

Til slutt, må du legge til updateBlasts () til hovedoppdateringsfunksjonen, og du bør være klar til å gå. Gi det et forsøk og se den fantastiske kraften som vårt monster har nå! Etter å ha kjørt det, bør du se noe slikt:

Nå som spillerne kan forsvare seg, la oss gå videre og gi dem noen utfordringer. Begge disse neste hendelsene vil bli overvunnet ved å bare skyte dem en gang. Etter at de er på plass, vil det imidlertid være enkelt for deg å endre dem slik at de passer til ditt eget prosjekt. Vi begynner med spikedommen.

Den spikede veggen vil ganske enkelt plasseres på toppen av dagens bakke og bevege seg med samme konstante hastighet som bakken rundt den. Første ting å gjøre er å legge til UpdateSpikes-funksjonen. Rett under funksjonen updateBlasts () legger du til følgende kode:

 --sjekk for å se om pigger er i live eller ikke, hvis de er - oppdatere dem på riktig måte, updateSpikes () for a = 1, spikes.numChildren, 1 gjør hvis (pigger [a] .isAlive == true) da [a]): oversett (hastighet * -1, 0) hvis (pigger [a] .x < -80) then spikes[a].x = 900 spikes[a].y = 500 spikes[a].isAlive = false end end end end

Dette vil gjøre det samme som vår updateBlast-funksjon. Det vil ganske enkelt oppdatere posisjonen til spikedemuren og se om den gikk ut av skjermen (som den for øyeblikket ikke kan gjøre fordi den ville slå spilleren først). Bare i tilfelle, skjønt, vi vil sjekke for å være sikker på. Det siste vi må gjøre er å lage en begivenhet for det. I sjekkEvent () nedenfor legger du til følgende andre sjekker:

 --Jo oftere du vil at hendelser skal skje da - greater du bør sjekke om (se> 72 og sjekk < 81) then inEvent = 12 eventRun = 1 end

Vi skal faktisk legge til vår vegg i UpdateBlocks () -funksjonen. På den måten er vi sikre på å ha den nåværende groundLevel. Rett før du ringer til checkEvent () legger du inn følgende:

 --ved å sette opp pigger på denne måten, er vi garantert å - bare ha 3 pigger ut maksimalt av gangen. hvis (inEvent == 12) så for a = 1, spikes.numChildren, gjør 1 hvis (pigger [a] .isAlive == true) deretter - gjør ikke noe annet pigger [a] .isAlive = true pigger [a]. y = groundLevel - 200 pigger [a] .x = newX break ende ende ende

Den siste tingen å gjøre for å få dette oppe, er å legge til kollisjonsdeteksjon for å se om spilleren kjørte inn i det eller ikke. Sett dette rett under delen i kontrollkollisjoner () der vi kontrollerer sammenstøtene mellom blokkene og monsteret.

 --stopp spillet hvis monsteret går inn i en spike vegg for a = 1, spikes.numChildren, 1 gjør hvis (pigger [a] .isAlive == true) så hvis (collisionRect.y - 10> pigger [a] .y - 170 og pigger [a] .x - 40 < collisionRect.x and spikes[a].x + 40 > kollisjonRect.x) deretter - stopp monsterhastigheten = 0 endeendens ende

Sørg for å legge til oppdateringsspikes () til hovedoppdateringsfunksjonen igjen og gi den et løp! Du bør nå ha disse pigger i monsterets sti.

Gi det en virvel og trene dem ned. Husk å teste for å forsikre deg om at kollisjonene fungerer riktig med blastene. Pass også på at kjører inn i veggene faktisk dreper spilleren. Når du har testet det og er klar for mer, må du begynne å sette koden på plass for spøkelset.

Å sette spøkelset i er ganske mye identisk med å sette veggen inn. Den største forskjellen mellom de to er at for spøkelset skal vi randomisere hvor det kommer inn i, så vel som hvor raskt det reiser. Vi vil også gjøre spøkelsene flytte opp og ned slik at de alltid beveger seg til hvor brukeren er. Spesielle detaljer som dette vil få hindringene til å føle seg helt annerledes enn brukeren, selv om de jobber på en slik måte.

La oss starte igjen ved å legge til updateGhosts () -funksjonen. Mens du er i det, gå videre og legg til updateGhosts () til hovedoppdateringsfunksjonen også.

 --oppdatere spøkelsene hvis de er i live funksjonoppdateringGhosts () for a = 1, ghosts.numChildren, 1 gjør hvis (spøkelser [a] .isAlive == true) da (spøkelser [a]): translate (speed * -1, 0 ) hvis (spøkelser [a] .y> monster.y) så spøkelser [a] .y = spøkelser [a] .y - 1 ende hvis (spøkelser [a] .y < monster.y) then ghosts[a].y = ghosts[a].y + 1 end if(ghosts[a].x < -80) then ghosts[a].x = 800 ghosts[a].y = 600 ghosts[a].speed = 0 ghosts[a].isAlive = false; end end end end

Deretter går du tilbake til funksjonen checkEvent () og legger til dette under forrige sjekker:

 --ghost event hvis (sjekk> 60 og sjekk < 73) then inEvent = 13 eventRun = 1 end

Denne gangen i stedet for å få spøkelsene å flytte fra UpdateBlocks-funksjonen, vil vi gjøre det i runEvent () -funksjonen. Legg til dette under den andre hvis uttalelser:

 --Dette vil være litt annerledes som vi vil at dette skal virkelig - gjøre spillet føler enda mer tilfeldig. endre hvor spøkelsene spretter og hvor fort de kommer til monsteret. hvis (inEvent == 13) så for a = 1, ghosts.numChildren, 1 gjør hvis (spøkelser [a] .isAlive == false) deretter spøkelser [a] .isAlive = sanne spøkelser [a] .x = 500 spøkelser [ a] .y = math.random (-50, 400) spøkelser [a] .speed = math.random (2,4) bryte endeendens ende

Når det er der inne, må vi sjekke for sammenstøt mellom monsteret og spøkelsene. Legg til dette for å sjekke Kollisjoner () rett etter at vi har gjort arbeidet for de spikede veggene:

 --sørg for at spilleren ikke ble rammet av et spøkelse! for a = 1, ghosts.numChildren, 1 gjør hvis (spøkelser [a] .isAlive == true) så hvis ((((monster.y-spøkelser [a] .y))<70) and ((monster.y - ghosts[a].y) > -70)) og (spøkelser [a] .x - 40 < collisionRect.x and ghosts[a].x + 40 > kollisjonRect.x)) deretter - stopp monsterhastigheten = 0 endeendens ende

Du bør nå ha alt på plass, inkludert spøkelsene å unnslippe!

Spillet bør nå være mye morsomt og utfordrende for brukerne. I neste veiledning legger vi til to ting som vil gjøre vårt spill føler mer komplett: (1) et scoring system og (2) monster død! Vi dekket mye i denne opplæringen, så hvis du har noen spørsmål, vennligst hør av i kommentarene nedenfor. Takk for at du leste!