Creați un joc de combatere a avioanelor în Corona mai mult gameplay

Ce veți crea

Introducere

În tutorialul precedent al acestei serii, am început să implementăm gameplay-ul jocului și deja am reușit să ajungem în avion pe ecran. În acest tutorial vom continua implementarea gameplay-ului. Hai să ne aruncăm cu ochii startTimers funcţie.

1. startTimers

După cum indică și numele, startTimers Funcția pornește cronometrele. Adăugați următorul cod la gamelevel.lua.

funcția startTimers () sfârșit

Invocați această funcție în enterScene așa cum se arată mai jos.

Functia scena: enterScene (eveniment) planul localSound = audio.loadStream (planesound.mp3) planeSoundChannel = audio.play (planeSound, loops = -1) Runtime: endEndList (endFrame, gameLoop)

2. firePlayerBullet

firePlayerBullet funcția creează un glonț pentru player.

funcția firePlayerBullet () local tempBullet = display.newImage ("bullet.png", (player.x + playerWidth / 2) - bulletWidth, player.y-bulletHeight) table.insert (playerBullets, tempBullet); planeGroup: introduceți (tempBullet) sfârșitul 

Aici folosim Obiectul de afișare imagine noua metodă pentru a crea gloanțele. Poziționăm-o astfel încât să se afle în centrul planului pe axa x și chiar în partea superioară a planului pe axa y. Glonțul este apoi introdus în playerBullets tabel pentru referință ulterioară și, de asemenea, în planeGroup.

3. Apelarea firePlayerBullet

Trebuie să sunăm firePlayerBullet funcția periodică pentru a vă asigura că avionul jucătorului trage automat gloanțele. Adăugați următorul fragment de cod în startTimers funcţie.

funcția startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) sfârșit

După cum indică numele său, cronometrele performWithDelay metoda solicită o funcție specificată după o perioadă de timp. Timpul este în milisecunde, deci sunăm aici firePlayerBullet funcționează la fiecare două secunde. Trecând -1 ca al treilea argument, cronometrul se va repeta pentru totdeauna.

Dacă încercați acum jocul, ar trebui să vedeți că la fiecare două secunde apare un glonț. Cu toate acestea, încă nu se mișcă. Vom avea grijă de asta în următorii pași.

4. movePlayerBullets

În movePlayerBullets, ne bucle prin playerBullets și schimbați tabelul y coordonează fiecare glonț. Mai întâi verificăm să vă asigurați că playerBullets tabelul conține gloanțe în el. # inainte de playerBullets este numit lungime operator și returnează lungimea obiectului la care este chemat. Este util să știți că # operatorul funcționează și pe șiruri de caractere.

funcția movePlayerBullets () dacă (#playerBullets> 0) atunci pentru i = 1, # playerBullets face playerBullets [i]. y = playerBullets [i] .y - 7 end end end

Trebuie să invocăm movePlayerBullets în gameLoop după cum se arată mai jos.

funcția gameLoop () --SNIP-- numberOfTicks = numărOfTicks + 1 movePlayer () movePlayerBullets () end

5. checkPlayerBulletsOutOfBounds

Atunci când un glonț scade din ecran, acesta nu mai este relevant pentru joc. Cu toate acestea, ei încă fac parte din playerBullets și continuați să vă deplasați ca orice alt glonț din tabel. Aceasta este o risipă de resurse și, dacă jocul urma să dureze mult timp, ar avea ca rezultat sute sau mii de obiecte neutilizate.

Pentru a depăși acest lucru, monitorizăm gloanțele și, odată ce se îndepărtează de pe ecran, le eliminăm din playerBullets precum și de pe afișaj. Aruncați o privire la punerea în aplicare a checkPlayerBulletsOutOfBounds.

funcția checkPlayerBulletsOutOfBounds () dacă (#playerBullets> 0) atunci pentru i = # playerBullets, 1, -1 do if (playerBullets [i] .y < -18) then playerBullets[i]:removeSelf() playerBullets[i] = nil table.remove(playerBullets,i) end end end end

Este important să rețineți că ne întoarcem prin playerBullets masa înapoi. Dacă vom bifa masa înainte, atunci când vom elimina unul dintre gloanțe, vom arunca indicele de bucle și vom cauza o eroare. Prin rularea peste masă în ordine inversă, ultimul glonț este deja procesat. removeSelf metoda elimină obiectul afișat și își eliberează memoria. Ca o bună practică, ar trebui să setați orice obiecte zero după ce a sunat removeSelf.

Invocăm această funcție în gameLoop funcţie.

funcția gameLoop () --SNIP - movePlayer () movePlayerBullets () checkPlayerBulletsOutOfBounds () sfârșit

Dacă doriți să vedeți dacă această funcție funcționează corect, puteți introduce temporar a print ("Scoaterea Bullet") imediat după ce ați setat obiectul de afișare la zero.

6. generateIsland

Pentru a face jocul mai interesant, generăm o insulă atât de des și o mutați pe ecran pentru a da aspectul avionului care zboară peste insule. Adăugați următorul fragment de cod pentru generateIsland funcţie.

funcția generateIsland () local tempIsland = display.newImage ("island1.png", math.random (0, display.contentWidth - islandWidth), - islandHeight) table.insert (insulă, tempIsland) islandGroup:

Folosim imagine noua din nou, și poziționați insula stabilind o valoare negativă pentru islandHeight. Pentru X poziție, vom folosi math.random pentru a genera un număr între 0 si afişa„s contentWidth minus islandWidth. Motivul pentru care scădem lățimea insulei este să ne asigurăm că insula este complet pe ecran. Dacă nu am scădea lățimea insulei, ar fi o șansă ca o parte a insulei să nu fie pe ecran.

Trebuie să începem un cronometru pentru a genera o insulă atât de des. Adăugați fragmentul următor în startTimers pe care am creat-o mai devreme. După cum puteți vedea, noi generăm o insulă în fiecarecinci secunde. În pasul următor, vom face ca insulele să se miște.

Funcția startTimers () firePlayerBulletTimer = Timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = Timer.performWithDelay (5000, generateIsland, -1) Sfârșit

7. moveIslands

Implementarea sistemului moveIslands este aproape identică cu movePlayerBullets funcţie. Verificăm dacă Insulele tabelul conține orice insulă și, dacă se întâmplă, o facem prin ea și o mutăm pe fiecare insulă.

funcția moveIslands () dacă (#islands> 0) atunci pentru i = 1, #islands do inslands [i] .y = insule [i] .y + 3 end end end

8. checkIslandsOutOfBounds

Așa cum verificăm dacă gloanțele jucătorului s-au mutat off-screen, verificăm dacă vreunul dintre insule sa mutat off-screen. Implementarea sistemului checkIslandsOutOfBounds ar trebui, prin urmare, să vă arătați familiar. Verificăm dacă insulele y poziția este mai mare decât display.contentHeight și dacă este, știm că insula sa mutat off-screen și, prin urmare, poate fi eliminată.

funcția checkIslandsOutOfBounds () dacă (#islands> 0), atunci pentru i = # insule, 1, -1 dacă (insulele [i] .y> display.contentHeight), apoi insulele [i]: removeSelf () nil table.remove (insule, i) end end end end

9. generateFreeLife

Atât de des, jucătorul are șansa de a obține o viață liberă. Mai întâi generăm o imagine a vieții libere și, dacă jucătorul se ciocnește cu imaginea, primește o viață suplimentară. Jucătorul poate avea maximum șase vieți.

funcția generateFreeLife () dacă (numberOfLives> = 6) apoi returnați sfârșitul localului freeLife = display.newImage ("newlife.png", math.random (0, display.contentWidth - 40), 0); table.insert (freeLifes, freeLife) planGroup: introduceți (freeLife) sfârșitul 

Dacă jucătorul are deja șase vieți, nu facem nimic returnându-ne devreme din funcție. Dacă nu, vom crea o nouă imagine de viață și o vom adăuga pe ecran. Similar cu modul în care am poziționat insulele mai devreme, am stabilit imaginea negativă y poziția și generează o valoare aleatorie pentru imaginea respectivă X poziţie. Apoi îl inserăm în freeLifes tabel pentru a putea face referire mai târziu.

Trebuie să numim această funcție atât de des. Adăugați fragmentul următor în startTimers funcţie.

Funcția startTimers () FirePlayerBulletTimer = Timer.performWithDelay (2000, FirePlayerBullet, -1) generateIslandTimer = Timer.performWithDelay (5000, generateIsland, -1) generateFreeLifeTimer = Timer.performWithDelay (7000, generateFreeLife,

10. moveFreeLives

Implementarea sistemului moveFreeLifes ar trebui să arate familiar. Ne întoarcem prin freeLifes și mutați fiecare imagine în ea.

funcția moveFreeLifes () dacă (#freeLifes> 0) atunci pentru i = 1, # freeLifes do freeLifes [i] .y = freeLifes [i] .y +5 end end end

Tot ce trebuie să facem este să sunăm moveFreeLifes în gameLoop funcţie.

funcția gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () end

11. checkFreeLifesOutOfBounds

Următorul fragment de cod ar trebui, de asemenea, să vă pară cunoscut până acum. Verificăm dacă oricare dintre imaginile din freeLifes masa s-au mutat off-screen și eliminați cele care au.

funcția checkFreeLifesOutOfBounds () dacă (#freeLifes> 0), atunci pentru i = # freeLifes, 1, -1 face dacă (freeLifes [i] .y> display.contentHeight) apoi freeLifes [i]: removeSelf nil table.remove (freeLifes, i) sfârșitul capătului final 

Noi numim această funcție în gameLoop funcţie.

funcția gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () checkFreeLifesOutOfBounds () sfârșit

12. hasCollided

Trebuie să putem spune când obiectele jocului se ciocnesc unul cu celălalt, cum ar fi avionul jucătorului și imaginile de viață liberă, gloanțele și avioanele etc. În timp ce Corona oferă un motor de fizică foarte robust, care poate manipula cu ușurință coliziunile dintre obiectele afișate pentru noi, acest lucru adaugă un pic de overhead cu calculele motorul trebuie să facă fiecare cadru.

În scopul acestui joc, vom folosi un sistem simplu de detectare a coliziunii caseta delimitată. Ce face această funcție este să vă asigurați că dreptunghiurile sau casetele de margine din jurul a două obiecte nu se suprapun. Dacă o fac, obiectele se ciocnesc. Această logică este implementată în hasCollided funcţie.

funcția hasCollided (obj1, obj2) dacă (obj1 == nil), apoi întoarceți capătul false dacă (obj2 == nil) apoi întoarceți false end local local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin drept local = obj1.contentBounds.xMin> = obj2.contentBounds.xMin și obj1.contentBounds.xMin <= obj2.contentBounds.xMax local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin local down = obj1.contentBounds.yMin> = obj2.contentBounds.yMin și obj1.contentBounds.yMin <= obj2.contentBounds.yMax return (left or right) and (up or down) end

Am găsit acest fragment de cod pe site-ul CoronaLabs. Funcționează foarte bine, deoarece obiectele de joc din jocul nostru sunt rectangulare. Dacă lucrați cu obiect care nu este dreptunghiular, atunci ar fi bine să profitați de motorul de fizică al Corona, deoarece detectarea coliziunii sale este foarte bine optimizată pentru aceasta.

13. checkPlayerCollidesWithFreeLife

Vrem să verificăm dacă avionul jucătorului sa ciocnit cu un obiect de viață liberă. Dacă are, atunci îi acordăm jucătorului o viață liberă.

()), dacă pentru (i) = freeLifes, 1, -1, dacă (aCollided (freeLifes [i], player)) freeLifes [i]: removeSelf table.remove (freeLifes, i) numberOfLives = numărOfLivi + 1 hideLives () showLives () end end end end

În checkPlayerCollidesWithFreeLife funcția, ne bucle prin freeLives tabelul înapoi din același motiv pe care l-am descris mai devreme. Noi numim hasCollided funcția și treceți în imaginea curentă și în planul jucătorului. Dacă ambele obiecte se ciocnesc, eliminăm imaginea de viață liberă, incrementăm numberOfLives variabilă și apelați hideLives și showLives funcţie.

Invocăm această funcție în gameLoop funcţie.

funcția gameLoop () --SNIP - moveFreeLifes () checkFreeLifesOutOfBounds () checkPlayerCollidesWithFreeLife () sfârșit

14. hideLives

hideLives funcționează prin livesImages tabel și stabilește este vizibil proprietății fiecărei imagini de viață fals.

funcția hideLives () pentru i = 1, 6 face lives_mages [i] .isvisible = end end false 

15. showLives

showLives funcționează prin livesImages tabel și stabilește fiecare imagine este vizibil proprietate la Adevărat.

funcția showLives () pentru i = 1, numberOfLives livesImages [i] .isVisible = true; sfârșitul final

Concluzie

Aceasta aduce la sfârșit oa treia parte a acestei serii. În următoarea și ultima tranșă a acestei serii, vom crea avioane inamice și vom finaliza gameplay-ul jocului. Mulțumesc că ai citit și te-am văzut acolo.

Cod