Construiește un joc fără sfârșit de la zero Interacțiune Sprite

Bine ați venit la cel de-al patrulea tutorial din seria noastră de construire a unui joc de funcționare de la zero cu SDK Corona. În această secțiune, vom adăuga gravitatea, detectarea coliziunilor și abilitatea de a sări la jocul sprite. Sa mergem!

Sperăm că tutorialele de până acum au fost utile și ușor de urmărit. Ca întotdeauna, dacă aveți întrebări, asigurați-vă că lăsați un comentariu! Ultima oară când am trecut peste modul de a crea spritesc frumos din foile de sprite. Astăzi, vom lua ceea ce am învățat în ultimul tutorial și vom obține acel monstru sprite în jocul nostru real. Odată ce a intrat, vom învăța cum să-l controlam și să facem jocul nostru interactiv. Modul în care intenționez să fac acest lucru este să ia codul sursă pe care l-am avut din tutorialul cu mișcarea de fundal și să adăugăm mai întâi lucrurile despre animația de monstru. Dacă descărcați fișierele pentru tutorial, veți observa că există 2 dosare numite "vechi" și "noi". Veche conține toate fișierele din tutorialul de mișcare de fundal de care aveți nevoie pentru a începe să lucrați la acest tutorial. Noua conține tot codul și tot ce veți avea odată ce acest tutorial a fost finalizat. Deci, continuați și descărcați fișierele și deschideți fișierul principal.lua din dosarul vechi. Voi distruge tot ce facem în trei secțiuni. Primul va include organizarea jocului nostru, la care vom face câteva schimbări. Cel de-al doilea se va referi la luarea a ceea ce am învățat în utilizarea tutorialului sprite și la implementarea acestuia aici. Vom trece peste această secțiune destul de repede, deoarece detaliile despre ceea ce se întâmplă au fost deja acoperite. Cea de-a treia secțiune va oferi gravității micului nostru tip, detectarea coliziunilor și capacitatea de a sări!

Până acum am plasat imaginile în cod în ordinea în care vrem să apară pe ecran. Cu cât sunt numite mai devreme, cu atât mai mult vor apărea în straturile de pe ecran. Acest lucru funcționează, dar există o modalitate mai bună de a face acest lucru. Nu va fi întotdeauna realist să puneți fiecare imagine în ordinea exactă în care doriți să apară și, la un moment dat, doriți să schimbați ordinea în care apar obiectele pe ecran. Deci, deschideți fișierul principal.lua din dosarul vechi și vom începe să facem unele modificări.

Primul lucru pe care îl vom face este să adăugați următoarea linie în partea de sus a paginii chiar dedesubtul display.setStatusBar linia.

 Sprite local = necesită ("sprite")

Apoi, adăugați următoarele două linii chiar dedesubtul locului în care am creat grupul de afișare blocuri:

 player local = display.newGroup () ecran local = display.newGrup ()

Playerul de grup de afișare va fi grupul de afișare care deține eroul nostru erou și grupul de ecran va fi un grup de afișare care deține orice altceva. Să mai punem codul și apoi voi termina să explic.

Introduceți codul de mai jos sub buclă pentru unde ne instanțiăm blocurile noastre de bază:

 --creați spriteSheet = sprite.newSpriteSheet ("monsterSpriteSheet.png", 100, 100) local monsterSet = sprite.newSpriteSet (spriteSheet, 1, 7) sprite.add (monsterSet, 0) sprite.add (monsterSet, "jumping", 7, 7, 1, 1) - setarea diferitelor variabile pe care le vom folosi pentru sprite-ul nostru monstru - de asemenea, seturi și începe prima animație pentru monstru local monstru = sprite. Monster: monster.x = 110 monster.y = 200 - acestea sunt două variabile care vor controla căderea și săriturile monstruului monstru. gravitatea = -6 monstru .accel = 0 - dreptunghi folosit pentru detectarea coliziunilor - va fi întotdeauna în fața sprite-ului monstru - așa știm dacă monstrul a lovit în orice coliziune localăRect = display.newRect (monster.x + 36, monstru .1, 70) collisionRect.strokeWidth = 1 collisionRect: setFillColor (140, 140, 140) collisionRect: setStrokeColor (180, 180, 180) collisionRect.alpha = 0 - g pe ecran în grupul de ecran - aceasta ne va permite să schimbăm ordinea în care apare sprite - pe ecran dacă vrem. Mai intai este pus in grupul - inapoi inapoi pe ecran: inserati (backbackground) ecran: inserati (backgroundfar) ecran: inserati (backgroundnear1) ecran: inserati (backgroundnear2) ecran: inserati (blocuri) monstru) ecran: inserați (collisionRect)

Acum, hai să trecem peste acel imens bloc de cod.

Primele două secțiuni pe care le vom trece peste. Aceste secțiuni creează doar sprite de monstru de pe foaia noastră sprite. Dacă aveți întrebări cu privire la ceea ce se întâmplă, faceți o scurtă trecere în revistă a ultimului tutorial în care ne-am îndreptat spre crearea de sprite din foi de sprite. În secțiunea următoare, am creat o formă de dreptunghi de bază numită collisionRect, așa vom face detectarea coliziunilor, astfel încât monstrul nostru poate interacționa cu lumea. În esență, ceea ce se întâmplă este că noi creăm un pătrat invizibil care merge în fața monstrului nostru. Dacă faceți dreptunghiul vizibil (adică modificați doar alfa la 100), veți vedea că acesta se află chiar în fața monstruului și plutește puțin peste pământ.

Motivul pentru care facem acest lucru este că ne va da un sistem de coliziune ușor de gestionat. Pentru că facem un joc fără sfârșit, suntem în primul rând preocupați de ceea ce se întâmplă chiar în fața monstruului (în mod normal, ceea ce vine în spatele lui nu îl va ucide). De asemenea, îl ridicăm puțin de la sol astfel încât caseta să nu se ciocnească niciodată cu solul de sub monstru, numai lucrurile în fața acestuia. Monstrul însuși se va ocupa de coliziunile cu solul, avem nevoie doar de ceva pentru a face față coliziunilor cu obiecte externe care l-ar putea lovi în față. Acest lucru va face chiar mai multă sens în următoarele câteva tutoriale, pe măsură ce adăugăm lucruri pentru ca un monstru să intre în joc.

Secțiunea după aceea este locul în care inserăm totul în ecran. Deci, ecranul este doar un grup de afișare - nu este nimic magic despre asta. Cu toate acestea, prin acest lucru ne oferă un avantaj imens față de modul în care punem lucrurile pe ecran înainte și astfel avem controlul asupra modului în care sunt ordonate lucrurile. Acum, indiferent de momentul în care am creat spritele, acestea vor apărea acum în ordinea în care le-am pus în grupul de afișare ecran. Deci, dacă am fi decis că monstrul ar trebui să meargă în spatele obiectelor de fundal, ar fi pur și simplu nevoie să le inserăm în grupul de ecran după ce am inserat monstrul.

Apoi, modificați funcția de actualizare () pentru a arăta ca aceasta:

 actualizarea funcției locale (event) updateBackgrounds () updateSpeed ​​() updateMonster () updateBlocks () checkCollisions () sfârșit

Aceasta va numi restul funcțiilor pe care trebuie să le executăm pentru a ne asigura că totul este bine actualizat. Un lucru de remarcat în timp ce lucrați cu funcția de actualizare este că ordinea contează. Pentru jocul nostru de alergare mic, ordinea nu este așa de importantă, așa cum se numește de treizeci de ori pe secundă, deci tot ceea ce este actualizat va fi prins foarte repede. De asemenea, nu există date cruciale în care funcțiile să fie ruinate una pentru cealaltă. Cu toate acestea, vor exista momente când trebuie să fiți atenți la ce ordine veți pune lucrurile înăuntru. Acest lucru este valabil mai ales când aveți mai multe funcții care actualizează aceleași variabile în moduri diferite. De obicei, deși acest lucru este într-adevăr doar o chestiune de folosire a bunului simț și totuși veți fi în stare să mergeți logic prin care lucrurile ar trebui tratate mai întâi.

Iată restul funcțiilor care vor face munca pe care tocmai am sunat-o din funcția de actualizare. Puneți-le sub funcția de actualizare. Asigurați-vă că citiți comentariile, pe măsură ce le voi folosi pentru a descrie ce se întâmplă.

 funcția checkCollisions () a fostOnGround = onGround - verifică dacă collisionRect s-a ciocnit cu ceva. Acesta este motivul pentru care este ridicat de la sol - un pic, dacă atinge pământul, ceea ce înseamnă că am intrat într-un zid. Verificăm acest lucru prin ciclism prin toate piesele de sol din grupul de blocuri și comparând coordonatele lor x și y cu cele ale coliziuniiRect pentru a = 1, blocs.numChildren, 1 do if (collisionRect.y - 10> blochează [ a] .y - 170 și blochează [a] .x - 40 < collisionRect.x and blocks[a].x + 40 > collisionRect.x), apoi viteza = 0 sfarsitul sfarsit - acesta este locul unde verificam daca monstrul se afla pe pamant sau in aer, daca el este in aer, atunci el nu poate sari (imi pare rau nici dublu - jumping pentru micul nostru monstru, cu toate acestea, dacă ați fi vrut să se poată dubla sari ca Mario, atunci ar fi nevoie doar de a face o mică ajustare aici, adăugând oa doua variabilă numită something likeJumped. o dată când s-a făcut saltul dublu, așa că el este limitat la 2 hamei pe sare - Încă o dată ne străbatem grupul de blocuri și comparăm valorile x și y ale fiecăruia dintre ele pentru a = 1, blochează .numChildren, 1 do if (monster.y> = blochează [a] .y - 170 și blochează [a] .x < monster.x + 60 and blocks[a].x > monster.x - 60), apoi monster.y = blochează [a] .y - 171 onGround = adevărat rupe altceva onGround = false final sfârșitul funcției endMonster () - dacă monstrul nostru este sărituri apoi treceți la animația de sărituri - nu continuați să jucați animația în desfășurare dacă (onGround) - dacă suntem alread pe teren nu avem nevoie să pregătim ceva nou dacă (wasOnGround) atunci altceva monstru: pregăti ("running") monstru: play () monstru: pregăti ("jumping") monstru: play () sfârșitul dacă (monster.accel> 0) atunci monster.accel = monster.accel - 1 end --update pozitia monștrilor accel este folosit pentru saltul nostru și - monstrul care coboară. Puteți juca cu acele 2 variabile - pentru a face o mulțime de combinații interesante de gameplay, cum ar fi situațiile de "gravitate scăzută" monster.y = monster.y - monster.accel monster.y = monster.y - monster.gravity - actualizați coliziuneaRect pentru a rămâne în fața coliziunii monstruRect.y = sfârșitul monster.y - aceasta este funcția care gestionează evenimentele de salt. Dacă ecranul este atins în partea stângă - atunci facem ca funcția de salt monstru să fie atinsă (eveniment) dacă (event.phase == "a început") și apoi dacă (event.x < 241) then if(onGround) then monster.accel = monster.accel + 20 end end end end

Observați că funcția atinsă nu este chemată niciodată. În partea de jos a codului de mai jos unde utilizați cronometrul care apelează funcția de actualizare, puneți acest cod:

 Durata de execuție: addEventListener ("atingeți", atingeți, -1)

Să analizăm câteva lucruri din codul pe care tocmai l-am pus. Funcția atinsă trece printr-un eveniment. Fiecare "eveniment" are proprietăți proprii. Când spunem event.phase == "a început" îi spunem lui Corona că vrem să fim avertizați de îndată ce utilizatorul atinge ecranul. Dimpotrivă, dacă am fi spus că "sa încheiat" în loc să începem, i-am fi spus lui Corona să nu ne notifice până când utilizatorul nu și-a ridicat degetul de pe ecran. De asemenea, stocate în eveniment sunt coordonatele atingerii. De aceea, folosirea a început și sa încheiat este importantă. Doriți locația când primul utilizator atinge ecranul sau când îl lasă? În majoritatea situațiilor de joc pe care doriți să le cunoașteți de îndată ce utilizatorul atinge ecranul, dar nu întotdeauna. Pentru o referire completă la evenimentele de atingere, puteți accesa aici (https://developer.anscamobile.com/reference/index/events/touch).

Deci, când executați acest lucru veți observa că sari doar dacă atingeți partea stângă a ecranului. Motivul pentru care facem asta este pentru că vrem să rezervăm partea dreaptă a ecranului pentru alte lucruri, cum ar fi împușcăturile de foc. Asta nu intră sub incidența acestui proiect, dar vom ajunge destul de curând! Cu toate acestea, ar fi bine să mergem acum.

Cu totul în locul ei trebuie să ai un monstru care să poată alerga și să sară pe pământ! Încet, tutorialul nostru mic începe să se simtă ca un joc! Ca întotdeauna, dacă aveți întrebări, anunțați-ne în secțiunea de comentarii de mai jos și vă mulțumim că ați urmat!

Cod