Hvordan blåse ting opp med Corona SDK Fysikkmotor Del 2

Velkommen til del to av Hvordan blåse ting opp med Corona SDK opplæringsserie. I denne opplæringen vil vi forbedre vår demo-app fra del I ved å la brukeren plassere en faktisk bombe grafisk på skjermen med en tidsforsinket eksplosjon. Vi vil også endre eksplosjonseffekten til å få kasser til å eksplodere i stedet for å bare fly av skjermen.

I del I av denne serien fikk vi en følelse for hvordan du oppretter et dynamisk miljø med Corona er brukervennlig fysikkbibliotek. Miljøet inneholdt statiske objekter, som gulvet, og programmatisk genererte dynamiske objekter som kasser. En brukertrykkshendelse vil da generere en eksplosiv kraft som vil sende kasser som flyr. Hvis du ikke har lest del I ennå, foreslår jeg at du gjør det før du fortsetter. Leseren bør ha en viss forståelse av de essensielle fysikkbegrepene som er forklart i del I for å kunne forstå del II.

repetisjons~~POS=TRUNC

La oss starte med en liten oppdatering på hvordan vi setter opp vårt fysikkmiljø i del I. Vi vil inkludere vårt programmatisk genererte sett med kasser som er stablet og sitter på gulvet vårt:

 lokal fysikk = krever (fysikk) fysikk.start () physics.setScale (40) display.setStatusBar (display.HiddenStatusBar) - Den endelige "sanne" parameteren overstyrer Coronas automatisk skalering av store bilder lokal bakgrunn = display.newImage ("bricks.png", 0, 0, true) background.x = display.contentWidth / 2 background.y = display.contentHeight / 2 lokal etasje = display.newImage ("floor.png", 0, 280, true) fysikk.addBody (gulv, "statisk", friksjon = 0,5) lokale kasser =  for i = 1, 5 gjør for j = 1, 5 kasser [i] = display.newImage ("crate.png" 140 + (i * 50), 220 - (j * 50)) fysikk.addBody (kasser [i], tetthet = 0,2, friksjon = 0,1, sprett = 0,5) endeenden

Alle arbeidene til ovennevnte kode er fullstendig forklart i del I i opplæringen, så sjekk det om noe virker forvirrende.

Sett bomben!

For vårt første skritt skal vi legge til en liten grafisk oppdatering til vår setBomb-metode. I stedet for en berøringshendelse som umiddelbart genererer eksplosjonen, kommer vi til å plassere en bombe på skjermen som sin egen fysikkobjekt:

 lokal funksjon setBomb (event) hvis (event.phase == "startet") så lokal bombe = display.newImage ("bomb.png", event.x, event.y) physics.addBody (bombe, tetthet = 0,2, friksjon = 0,1, sprette = 0,5) sluttendebakgrunn: addEventListener ("touch", setBomb)

Akkurat som før legger vi til en hendelseslytter i bakgrunnen for å se etter eventuelle berøringshendelser og brann settBomb-metoden når en oppstår. Innenfor metoden isolerer vi enhver aktivitet til "startet" fasen av arrangementet. Hvis vi ikke isolerte denne fasen, ville det føre til at koden blir utført flere ganger, da berøringshendelser har mange faser.

SetBomb-metoden som den står nå gjør svært lite. Den laster en fin utseende bombe grafikk og legger den til skjermen som et dynamisk fysikkobjekt. Nå integrerer vi vår eksplosjonsmetode tilbake i koden som en lokal funksjon som heter blast:

 lokal sirkel = "" lokal eksplosjon = "" lokal funksjon blast (hendelse) sirkel = display.newCircle (bomb.x, bomb.y, 80) eksplosjon = display.newImage ("explosion.png", bomb.x, bombe. y) sirkel: setFillColor (0,0,0, 0) physics.addBody (sirkel, "statisk", isSensor = true) circle.myName = "sirkel" circle.collision = onLocalCollision sirkel: addEventListener ("kollisjon" sirkel) ende blast ()

Sirkelobjektet her hjelper oss med å beregne vår blastradius. Vi legger til en kollisjonshendelselytter for å oppdage hvilken av kasser som faller innenfor blastsonen. I tillegg legger vi også en eksplosjonsgrafikk til skjermen i samme posisjon som bombe grafikken når blasten går av.

Timing the Blast

Hvis du prøver koden ut på dette tidspunktet, vil du legge merke til at alt skjer veldig raskt, og noen artefaktgrafikk er igjen. For å gjøre det mer spenstig, skal vi erstatte vår "blast ()" funksjonssamtale med en tidtaker som vil forsinke eksplosjonen av bomben med 3 sekunder:

 timer.performWithDelay (3000, blast)

Så enkelt som det! Timerklassen har en funksjon kalt performWithDelay () med to parametere: antall millisekunder å vente og metoden for å ringe. Så, i dette tilfellet, er 3000 millisekunder lik 3 helt sekunders forsinkelse.

Fjerning av artefakter

Siden bomben eksploderer etter 3 sekunders forsinkelse, må vi fjerne dette objektet fra skjermen når sprengningen oppstår. Dette kan gjøres veldig enkelt. Alle objekter som er til stede på skjermen, kommer med en praktisk removeSelf () funksjon. Når et objekt fjerner seg fra skjermen, er Fysikkmotoren smart nok til å søppel samle og fjerne den fra alle fysikkberegninger også. Vi kan legge til følgende linje til bunnen av blastfunksjonen:

 bombe: removeSelf ()

I tillegg til å fjerne bomben, skal vi fjerne vår sirkelblastradiusobjekt, samt eksplosjonsgrafikken vi la til for effekt. Siden vi må gi vår blastradius sirkel litt tid for å skape kollisjoner med våre kasser, skal vi fjerne den 1 / 10th av et sekund etter at vi kaller blastfunksjonen. Dette kan oppnås ved å erstatte vår tidsbestemt blastfunksjonssamtale med følgende kode:

 lokal funksjon removeStuff (event) sirkel: removeSelf () eksplosjon: removeSelf () end timer.performWithDelay (3000, blast) timer.performWithDelay (3100, removeStuff)

Som du kan se, ringer vi blastfunksjonen etter en 3 sekunders forsinkelse fra å berøre skjermen på samme måte som før. Vi har nå lagt til en annen forsinket samtale som utføres 3,1 sekunder etter å ha berørt skjermen som rydder opp våre gjenværende objekter med funksjonen removeSelf ().

Hele funksjonen vi opprettet nå ser slik ut:

 lokal funksjon setBomb (event) hvis (event.phase == "startet") og deretter lokal bombe = display.newImage ("bomb.png", event.x, event.y) physics.addBody (bombe, tetthet = 0,2, friksjon = 0,1, sprette = 0,5) lokal sirkel = "" lokal eksplosjon = "" lokalfunksjonsblast (hendelse) media.playEventSound (eksplosjonssound) sirkel = display.newCircle (bomb.x, bomb.y, 80) eksplosjon = display .newImage ("explosion.png", bomb.x, bomb.y) bombe: removeSelf () sirkel: setFillColor (0,0,0, 0) physics.addBody (sirkel, "statisk", isSensor = true) circle.myName = "circle" circle.collision = onLocalCollision sirkel: addEventListener ("kollisjon", sirkel) avslutte lokal funksjon removeStuff (event) sirkel: removeSelf () eksplosjon: removeSelf () end timer.performWithDelay (3000, blast) timer. performWithDelay (3100, removeStuff) slutten av bakgrunnen: addEventListener ("touch", setBomb)

Opprette en destruksjonsgrense

I del I av vår veiledning så vår kollisionsdeteksjonsfunksjon slik ut:

 lokal funksjon onLocalCollision (self, event) hvis (event.phase == "startet" og self.myName == "circle") og deretter local forcex = event.other.x-self.x local forcey = event.other.y- self.y hvis (forcex < 0) then forcex = 0-(80 + forcex)-12 else forcex = 80 - forcex+12 end event.other:applyForce( forcex, forcey, self.x, self.y ) end end

Det fant ganske enkelt alle kasser innenfor vår blastradius og påførte en kraft for å sprenge dem bort fra eksplosjonens epicenter. For å gjøre ting mer interessant, skal vi legge til en ødeleggelse terskel for kasser som vil få dem til å eksplodere hvis kraften som brukes på dem er høy nok. Det kan gjøres slik:

 hvis (math.abs (forcex)> 60 eller math.abs (forcey)> 60) og lokal eksplosjon = display.newImage ("explosion.png", event.other.x, event.other.y) event.other.other: removeSelf () lokal funksjon removeExplosion (event) eksplosjon: removeSelf () end timer.performWithDelay (100, removeExplosion) end

Vi må observere kraften som vi brukte på hver av kasser for å oppdage om den er høyere enn 60. 60 i dette tilfellet i et vilkårlig tall basert på vår kraftberegning. Vi bruker math.abs-funksjonen for å få absolutt verdien av kraften. I vårt eksempel kan styrker være positive eller negative avhengig av retningen av den påførte kraften. Vi er ikke bekymret for retning i dette tilfellet, vi vil bare vite om kraften overskrider terskelen på 60. Ta gjerne med dette terskelenummeret for å endre hvor svak eller sterk kasser er.

I del I ble vår eksplosjonsstyrke beregnet på en måte som forårsaker at den reduserer jo lenger en kasse er fra episkentralen til eksplosjonen. Så kasser som er nærmere epicenteret har en høyere sannsynlighet for å bli ødelagt, og de andre vil ganske enkelt fly av skjermen. Som vi gjorde tidligere med timerklassen, viser vi en eksplosjonsgrafikk i den tidligere posisjonen til en ødelagt kasse, og så fjerner vi den fra skjermen 1/10 av et sekund senere. Den endelige kollisionsdeteksjonsmetoden vil se slik ut:

 lokal funksjon onLocalCollision (self, event) hvis (event.phase == "startet" og self.myName == "circle") og deretter local forcex = event.other.x-self.x local forcey = event.other.y- self.y hvis (forcex < 0) then forcex = 0-(80 + forcex)-12 else forcex = 80 - forcex+12 end event.other:applyForce( forcex, forcey, self.x, self.y ) if(math.abs(forcex) > 60 eller math.abs (forcey)> 60) deretter lokal eksplosjon = display.newImage ("explosion.png", event.other.x, event.other.y) event.other: removeSelf () lokal funksjon removeExplosion (event) eksplosjon: removeSelf () end timer.performWithDelay (50, removeExplosion) endeendens ende

Lyd på!

Som et siste skritt i vår veiledning, skal vi spille en eksplosjonslydseffekt når bomben vår eksploderer. Som alt annet i Corona, er det overraskende enkelt å gjøre dette. Vi starter med å inkludere mediebiblioteket øverst i prosjektet og laster inn lydfilen vår:

 lokale medier = krever ("media") lokal eksplosjonSound = media.newEventSound ("explosion.mp3")

For å spille av lyden legger vi til følgende linje i vår blast () -funksjon som er inne i setBomb () -funksjonen vår:

 lokal funksjon blast (hendelse) media.playEventSound (eksplosjonSound)? slutt

Nå når blast () -funksjonen blir kalt, vil den bruke playEventSound-funksjonen fra mediebiblioteket til å spille vår "explosion.mp3" lydfil. Det kunne ikke vært enklere hvis vi prøvde!

Og der har vi det! Vi har nå et mer komplett eksempel på hvor lett det er å skape eksplosjoner i Corona-plattformen. Du er velkommen til å laste ned glidelåsene for både del I og II i opplæringen og spille rundt!