Een eenvoudig basketbalspel maken met Corona Game Edition

De physics-engine die bij Corona Game Edition wordt geleverd, is een ongelooflijk krachtige en gebruiksvriendelijke tool. In deze tutorial behandelen we de voltooiing van een rudimentair basketbalspel met behulp van deze opwindende technologie.

Stap 1: De Physics Engine instellen

 display.setStatusBar (display.HiddenStatusBar) local physics = vereisen "fysica" physics.start () physics.setGravity (9.81, 0) - 9.81 m / s * s in de positieve x-richting physics.setScale (80) - 80 pixels per meter physics.setDrawMode ("normaal")

Het eerste dat we doen (zoals in veel programma's) is om de statusbalk bovenaan het scherm te verwijderen. Vervolgens maken we de nodige vereistenverklaring voor het gebruik van fysica en slaan we het resultaat op in de toepasselijk genaamde "fysica" -variabele. Dingen worden interessanter in de volgende paar regels. In regel vijf zetten we de zwaartekrachtversnelling in. Doorgaans wordt de zwaartekracht ingesteld op 9,8 m / s * s in de positieve y-richting, maar in dit geval willen we de zwaartekracht trekken in de positieve x-richting, omdat de toepassing een liggende oriëntatie zal hebben. Verder stellen we de schaal in op 80 pixels per meter. Dit aantal kan nogal variëren, afhankelijk van de grootte van de objecten in je applicatie, en je moet er misschien mee spelen om je spel het juiste gevoel te geven. Ik heb 80 px / m gekozen omdat ik ongeveer 15 voet verticale ruimte op het scherm wil passen. Wetende dat, het is gewoon een kwestie van eenheidsconversie om een ​​waarde te krijgen.

Opmerking: het is belangrijk om alles te proberen vast te binden aan objecten uit de echte wereld in toepassingen met natuurkunde. Hoe meer echte metingen u gebruikt, hoe minder giswerk er zal zijn en hoe realistischer uw toepassing zal lijken.

We vervolledigen deze paar regels door de tekenmodus op normaal in te stellen. Deze regel maakt het later gemakkelijker om naar de foutopsporingsmodus te gaan als we ongewild gedrag met botsingen zouden moeten verhelpen. Dit standaard instellen is het standaardgedrag en tekent de vormen zoals de gebruiker ze in het laatste spel zal zien.


Stap 2: De arena maken

 local background = display.newImage ("CourtBackground.png") local score = display.newText ("Score: 0", 50, 300) score: setTextColor (0, 0, 0) score.rotation = -90 score.size = 36 local floor = display.newRect (320, 0, 1, 480) local lWall = display.newRect (0, 480, 320, 1) local rWall = display.newRect (0, -1, 320, 1) lokaal plafond = display.newRect (-1, 0, 1, 480) staticMaterial = density = 2, friction = .3, bounce = .4 physics.addBody (floor, "static", staticMaterial) physics.addBody (lWall, "static ", staticMaterial) physics.addBody (rWall," static ", staticMaterial) physics.addBody (ceiling," static ", staticMaterial)

Dit blok bepaalt de grenzen van de arena en de eigenschappen van alle statische objecten in de toepassing. We beginnen met het toevoegen van een eenvoudige afbeelding aan de achtergrond. Binnen in de witte rechthoek op de achtergrond plaatsen we wat tekst om de huidige score weer te geven. Omdat de toepassing in liggende modus wordt weergegeven, maken we hier ook de benodigde rotatieaanpassingen. De arena moet de bal vangen binnen het zichtbare gedeelte van het scherm. We bereiken dit met vier statische rechthoeken (vloer, lWall, rWall, plafond) die net uit het zicht zijn geplaatst.

Vervolgens brengen we natuurkunde terug in de vergelijking. In plaats van de tabel opnieuw te typen voor de fysieke eigenschappen van elk object, maken we een tabelnaam staticMaterial die opnieuw moet worden gebruikt voor elk van de muren en het doel zelf. Ik heb vrij standaardwaarden voor deze eigenschappen gekozen, hoewel ik je aanmoedig om met ze te spelen. Er is nog een stap die we moeten nemen, en dat is om Corona te vertellen dat deze objecten moeten deelnemen aan natuurkundige berekeningen. We doen dit door de addBody-functie van het physics-object aan te roepen. Deze functie neemt drie argumenten:

  1. Het object
  2. Een optionele modifier
  3. Een tabel met fysieke eigenschappen

We hebben de eigenschappen en de objecten al bepaald, dus het enige dat overblijft, is de optionele modifier. We gebruiken "statisch" om te voorkomen dat de zwaartekracht, of welke kracht dan ook, onze muren verplaatst!


Stap 3: Een bal en een doel toevoegen

 -- Maak het doel local vertPost = display.newRect (110, 5, 210, 10) vertPost: setFillColor (33, 33, 33) local horizPost = display.newRect (110, 10, 10, 40) horizPost: setFillColor (33, 33 , 33) lokaal bord = display.newRect (55, 50, 85, 5) bord: setFillColor (33, 33, 33) physics.addBody (vertPost, "static", staticMaterial) physics.addBody (horizPost, "static", staticMaterial) physics.addBody (bord, "statisch", staticMaterial) - Maak de bal lokale bal = display.newCircle (50, 200, 10) bal: setFillColor (192, 99, 55) physics.addBody (bal, dichtheid  = .8, wrijving = .3, bounce = .6, radius = 10)

In één klap creëren we de rest van de visuele elementen van onze app. Dit zou allemaal heel bekend moeten voorkomen. Er zijn slechts twee dingen die ik zou willen wijzen. Ten eerste kunnen sommige waarden voor het positioneren van het doel er niet uitzien. Dit is om rekening te houden met de oriëntatie van het landschap. Het doel verschijnt rechtop wanneer het apparaat op zijn kant wordt gedraaid. Zorg er ook voor dat u de eigenschap radius in de eigenschappentabel van de bal opneemt, zodat deze zich correct gedraagt.


Stap 4: Drag-ondersteuning voor de bal creëren

 lokale functie slepen (gebeurtenis) lokale bal = event.target lokale fase = event.phase als "begonnen" == fase dan display.getCurrentStage (): setFocus (bal) - beginpositie opslaan ball.x0 = event.x - bal .x ball.y0 = event.y - ball.y - Vermijd gravitatiekrachten event.target.bodyType = "kinematic" - stop huidige beweging, indien aanwezig event.target:setLinearVelocity (0, 0) event.target.angularVelocity = 0 anders als "verplaatst" == fase dan ball.x = event.x - ball.x0 ball.y = event.y - ball.y0 elseif "ended" == phase of "cancelled" == phase then display. getCurrentStage (): setFocus (nihil) event.target.bodyType = "dynamisch" einde end return true end ball: addEventListener ("aanraken", slepen)

Deze functie biedt ons een zeer eenvoudige ondersteuning voor slepen. Enkele van de hoogtepunten zijn het body-type van de bal kinematisch instellen, zodat de zwaartekracht de bal niet uit de handen van de gebruiker trekt (Opmerking: zorg ervoor dat u dit weer instelt op dynamisch nadat de aanraking is beëindigd). De regels erna zijn net zo belangrijk. Daar stoppen we de beweging van de bal als deze wordt aangeraakt om hetzelfde probleem te voorkomen dat we hadden met de zwaartekracht.

Als u de app uitvoert zoals deze nu is, zult u waarschijnlijk merken dat de bal al zijn momentum verliest zodra u hem niet meer aanraakt. Om dit te verhelpen, moeten we een functie maken om de snelheid van de bal te volgen en vervolgens de snelheid van de bal op de juiste manier instellen nadat de aanraking is beëindigd.

 local speedX = 0 local speedY = 0 local prevTime = 0 local prevX = 0 local prevY = 0 function trackVelocity (event) local timePassed = event.time - prevTime prevTime = prevTime + timePassed speedX = (ball.x - prevX) / (timePassed / 1000) speedY = (ball.y - vorige) / (timePassed / 1000) prevX = ball.x prevY = ball.y end Runtime: addEventListener ("enterFrame", trackVelocity)

We creëren trackVelocity als een luisteraar van de gebeurtenis enterFrame, dus deze wordt elke keer dat het scherm opnieuw getekend wordt genoemd. Wat het doet is de verandering in snelheid vinden over de verandering in de tijd om de snelheid van de bal in pixels per seconde te vinden. Er is echt niet veel aan. Voeg de volgende regel toe aan de sleepfunctie om de lineaire snelheid van de bal correct in te stellen.

 ball: setLinearVelocity (speedX, speedY)

Stap 5: Het borduurring- en scoremechanisme maken

We beginnen met wat meer visueel werk, maar nu zou je een professional moeten zijn bij rechthoeken, dus het zou pijnloos moeten zijn. De volgende code maakt de rand. Merk op dat het middelste gedeelte van de rand geen deel zal uitmaken van het fysieke systeem, omdat we willen dat de bal vrij doorloopt.

 local rimBack = display.newRect (110, 55, 5, 7) rimBack: setFillColor (207, 67, 4) local rimFront = display.newRect (110, 92, 5, 3) rimFront: setFillColor (207, 67, 4) local rimMiddle = display.newRect (110, 62, 5, 30) rimMiddle: setFillColor (207, 67, 4) physics.addBody (rimBack, "static", staticMaterial) physics.addBody (rimFront, "static", staticMaterial)

Vervolgens hebben we een manier nodig om te weten wanneer de bal het doel heeft gepasseerd. De eenvoudigste manier om dit te bereiken, is door een klein stukje van het scherm nabij de rand als een "scorezone" aan te wijzen. Wanneer de bal zich in deze zone bevindt, kunnen we de score verhogen. Om te voorkomen dat de score misplaatst wanneer de bal aan de rand blijft hangen, houden we de tijd bij van het laatste doelpunt en zorgen we voor een adequate scheiding tussen elk volgend doel. Een vertraging van één seconde zou goed moeten werken.

 ScoreCtr = 0 local lastGoalTime = 1000 functie monitorScore (event) als event.time - lastGoalTime> 1000 dan als ball.x> 103 en ball.x < 117 and ball.y > 62 en ball.y < 92 then scoreCtr = scoreCtr + 1 print(score) lastGoalTime = event.time score.text = "Score: "… scoreCtr end end end Runtime:addEventListener("enterFrame", monitorScore)

Conclusie

Hoewel deze app zou kunnen zijn gemaakt met de standaardversie van de Corona SDK, zou het bergen meer werk zijn geweest om botsingen, wrijving, zwaartekracht enz. Bij te houden. Corona Game Edition zorgt voor de moeilijkere taken van de natuurkunde, waardoor je hebt meer tijd om je te concentreren op de inhoud en gameplay van je game.