Bouw een eindeloos runnerspel tegen krassen Sprite-interactie

Welkom bij de vierde zelfstudie in onze serie over het bouwen van een compleet nieuw spel met de Corona SDK. In dit gedeelte gaan we zwaartekracht, botsingsdetectie en de mogelijkheid om naar de sprite van het spel te springen toevoegen. Laten we gaan!

Hopelijk zijn de tutorials tot nu toe nuttig en gemakkelijk te volgen geweest. Zoals altijd, als je vragen hebt, laat dan een reactie achter! De laatste keer hebben we besproken hoe je mooie sprites kunt maken van spritesheets. Vandaag gaan we nemen wat we hebben geleerd in de laatste tutorial en dat sprite-monster in onze eigenlijke game krijgen. Als hij er eenmaal is, leren we hem te beheersen en onze game interactief te maken. De manier waarop ik dit ga doen is door de broncode die we hadden van de achtergrondbewegingszelfstudie te nemen en eerst onze monsters met animaties toe te voegen. Als u de bestanden downloadt voor de zelfstudie, zult u zien dat er twee mappen zijn, genaamd "oud" en "nieuw". Oud bevat alle bestanden van de achtergrondbewegingszelfstudie die u nodig hebt om aan de slag te gaan met deze zelfstudie. Nieuw bevat alle code en alles wat u krijgt nadat deze zelfstudie is voltooid. Dus, ga je gang en download de bestanden en open het main.lua-bestand uit de oude map. Ik ga alles wat we doen opsplitsen in drie secties. De eerste gaat de organisatie van onze game behandelen, waarop we een paar wijzigingen zullen aanbrengen. De tweede omvat het nemen van wat we hebben geleerd in de tutorial sprites gebruiken en hier implementeren. We zullen dat gedeelte vrij snel bespreken omdat de details van wat er gebeurt al zijn behandeld. Het derde deel zal de zwaartekracht van onze kleine kerel, botsingsdetectie en het vermogen om te springen geven!

Tot nu toe hebben we onze afbeeldingen in de code geplaatst in de volgorde waarin we ze op het scherm willen laten verschijnen. Hoe eerder ze worden genoemd, hoe verder ze terug in de lagen op het scherm verschijnen. Dit werkt, maar er is een betere manier om dit te doen. Het is niet altijd realistisch om elke afbeelding exact in de volgorde te plaatsen waarin u deze wilt laten verschijnen, en u wilt op een gegeven moment de volgorde wijzigen waarin objecten op het scherm worden weergegeven. Dus open het bestand main.lua uit de oude map en we zullen enkele wijzigingen aanbrengen.

Het eerste wat we gaan doen is de volgende regel toevoegen aan de bovenkant van de pagina, direct onder de display.setStatusBar lijn.

 lokale sprite = vereisen ("sprite")

Voeg vervolgens de volgende twee regels toe precies onder waar we de weergavegroep hebben gemaakt blokken:

 lokale speler = display.newGroup () lokaal scherm = display.newGroup ()

De displaygroepspeler wordt de weergavegroep die onze heldensprite bevat en de schermgroep is een weergavegroep die al het andere bevat. Laten we wat meer code invoeren en dan zal ik het uitleggen beëindigen.

Voeg de volgende code onder de for-lus in waar we onze grondblokken instantiëren:

 --maak onze sprite sheet local spriteSheet = sprite.newSpriteSheet ("monsterSpriteSheet.png", 100, 100) local monsterSet = sprite.newSpriteSet (spriteSheet, 1, 7) sprite.add (monsterSet, "running", 1, 6, 600, 0) sprite.add (monsterSet, "jumping", 7, 7, 1, 1) - stel de verschillende variabelen in die we zullen gebruiken voor onze monstersprite - ook sets en start de eerste animatie voor het monster local monster = sprite. newSprite (monsterSet) monster: prepare ("running") monster: play () monster.x = 110 monster.y = 200 - dit zijn 2 variabelen die het vallen en springen van het monstermonster bepalen. gravity = -6 monster .accel = 0 - rechthoek gebruikt voor onze botsingsdetectie - het zal altijd voor de monstersprite staan ​​- op die manier weten we of het monster in een lokale botsing is geraaktRect = display.newRect (monster.x + 36, monster .y, 1, 70) collisionRect.strokeWidth = 1 collisionRect: setFillColor (140, 140, 140) botsingRect: setStrokeColor (180, 180, 180) botsingRect.alpha = 0 - gebruikt om alles in te zetten g op het scherm in de schermgroep - dit laat ons de volgorde veranderen waarin sprites verschijnen op - het scherm als we dat willen. Hoe eerder het in de groep wordt geplaatst - verder wordt het scherm geopend: scherm invoegen (achtergrondachtergronden): scherm (achtergrond) invoegen: invoegen (achtergrondneer1) scherm: invoegen (achtergrondneer2) scherm: invoegen (blokken) scherm: invoegen ( monster) scherm: insert (collisionRect)

Laten we nu eens kijken naar dat enorme blok code.

De eerste twee secties die we gaan overslaan. Die secties maken gewoon onze monstersprite van onze sprite-sheet. Als je vragen hebt over wat er aan de hand is, doe dan een korte bespreking van de laatste tutorial waar we heen gingen om sprites te maken van sprite sheets. In het volgende gedeelte heb ik een basisrechthoekvorm gemaakt, collisionRect genaamd, dit is hoe we onze botsingsdetectie gaan doen, zodat ons monster interactie met de wereld kan hebben. Wat er in wezen gebeurt, is dat we een onzichtbaar vierkant creëren dat voor ons monster gaat. Als je de rechthoek zichtbaar maakt (dat wil zeggen, je verandert gewoon de alpha naar 100), dan zie je dat hij recht voor het monster zit en iets boven de grond zweeft..

De reden dat we dit doen, is dat het ons een botsingssysteem geeft dat gemakkelijk te beheren is. Omdat we een eindeloze running game doen, zijn we vooral bezig met wat er precies gebeurt voor het monster (normaal gesproken zal wat achter hem komt hem niet doden). Ook heffen we het een beetje van de grond, zodat de box nooit botst met de grond onder het monster, alleen dingen ervoor. Het monster zal de botsingen met de grond zelf opvangen, we hebben alleen iets nodig om de botsingen met externe objecten die hem in de voorkant kunnen raken te verwerken. Dit zal nog logischer zijn in de volgende paar tutorials terwijl we dingen toevoegen om het monster tegen te komen.

In het gedeelte hierna plaatsen we alles in het scherm. Het scherm is dus gewoon een displaygroep - er is niets magisch aan. Door dit te doen, geeft het ons echter een enorm voordeel ten opzichte van hoe we dingen eerder op het scherm hebben geplaatst, en zo hebben we controle over hoe dingen worden geordend. Nu, ongeacht wanneer we de sprites hebben gemaakt, verschijnen ze nu in de volgorde waarin we ze in de displaygroep plaatsen scherm. Dus als we besloten dat het monster achter de achtergrond moet gaan staan, moeten we ze gewoon in een schermgroep invoegen nadat we het monster hebben geplaatst.

Pas vervolgens je update () -functie aan om er als volgt uit te zien:

 update van de lokale functie (gebeurtenis) updateAchtergronden () updateSpeed ​​() updateMonster () updateBlocks () checkCollisions () end

Dit roept de rest van de functies op die we moeten uitvoeren om te zorgen dat alles goed wordt bijgewerkt. Een ding om op te letten tijdens het werken met uw updatefunctie, is dat de volgorde ertoe doet. Voor ons kleine hardloopspel is de volgorde niet zo belangrijk, omdat deze dertig keer per seconde wordt genoemd, dus alles wat wordt bijgewerkt, zal zeer snel worden gevangen. Er zijn ook geen cruciale gegevens die de functies voor elkaar in de war sturen. Er zullen echter momenten zijn waarop u voorzichtig moet zijn met de volgorde waarin u de dingen plaatst. Dit geldt vooral als u meerdere functies hebt die dezelfde variabelen op verschillende manieren bijwerken. Meestal is dit echter gewoon een kwestie van gezond verstand gebruiken en kun je logischerwijs doorlopen om dingen eerst te behandelen.

Hier zijn de rest van de functies die het werk zullen doen dat we zojuist hebben genoemd vanuit de updatefunctie. Leg ze onder de update-functie. Zorg ervoor dat u de opmerkingen leest, want ik zal ze gebruiken om te beschrijven wat er aan de hand is.

 function checkCollisions () wasOnGround = onGround - controleert of de collisionRect ergens mee in botsing is gekomen. Daarom wordt het van de grond getild - een klein beetje, als het de grond raakt, betekent dit dat we tegen een muur zijn aangelopen. We controleren dit door - door alle grondstukken in de blokkengroep heen te bladeren en hun x- en y-coördinaten te vergelijken met die van de collisionRect voor a = 1, blocks.numChildren, 1 do if (collisionRect.y - 10> blocks [ a] .y - 170 en blokkeert [a] .x - 40 < collisionRect.x and blocks[a].x + 40 > collisionRect.x) en dan speed = 0 end end - dit is waar we kijken of het monster op de grond of in de lucht is, als hij in de lucht is dan kan hij niet springen (sorry geen dubbele - springen voor ons kleine monster, maar als je wilde dat hij als Mario kon dubbelspringen, dan zou je alleen een kleine aanpassing nodig hebben, door een tweede variabele toe te voegen die zoiets als hasjumps heet. Zet het normaal op false, en verander het in --true zodra de dubbele sprong is gemaakt, op die manier is hij beperkt tot 2 hops per sprong. - We fietsen door de blokkengroep en vergelijken de x- en y-waarden van elke. voor a = 1, blokken .numChildren, 1 do if (monster.y> = blokkeert [a] .y - 170 en blokkeert [a] .x < monster.x + 60 and blocks[a].x > monster.x - 60) then monster.y = blocks [a] .y - 171 onGround = true break else onGround = false end end-end functie updateMonster () --als ons monster springt, schakel dan over naar de springende animatie - als blijf de lopende animatie niet spelen als (opgrond) dan - als we al op de grond zijn, hoeven we niets nieuws voor te bereiden als (wasOnGround) dan anders monster: prepareer ("running") monster: play () end else monster: prepareer ("springen") monster: speel () einde als (monster.accel> 0) dan monster.accel = monster.accel - 1 einde - update de monsters positie accel wordt gebruikt voor onze sprong en - zwaartekracht houdt het monster komt naar beneden. Je kunt met die 2 variabelen spelen - om veel interessante combinaties van gameplay te maken zoals 'lage zwaartekracht' situaties monster.y = monster.y - monster.accel monster.y = monster.y - monster.gravity - update de botsingRect om voor de monsterbotsing te blijvenRect.y = monster.y einde - dit is de functie die de springgebeurtenissen afhandelt. Als het scherm aan de linkerkant wordt aangeraakt - raak dan de monster jump-functie aangeraakt (event) aan als (event.phase == "started") then if (event.x < 241) then if(onGround) then monster.accel = monster.accel + 20 end end end end

Merk op dat de aangeraakte functie nooit wordt aangeroepen. Onderaan de code rechtsonder waar je de timer gebruikt die de update-functie oproept, plaats je deze code:

 Runtime: addEventListener ("aanraken", aangeraakt, -1)

Laten we een paar dingen bekijken uit de code die we zojuist hebben ingevoerd. De aangeraakte functie geeft een gebeurtenis door. Elke "gebeurtenis" heeft eigen eigenschappen. Wanneer we zeggen event.phase == "begon" we vertellen Corona dat we op de hoogte willen worden gesteld zodra de gebruiker het scherm aanraakt. Integendeel, als we 'afgelopen' hadden gezegd in plaats van begonnen, zouden we Corona vertellen ons niet op de hoogte te stellen voordat de gebruiker zijn vinger van het scherm had gehaald. Ook opgeslagen in het evenement zijn de coördinaten van het aanraken. Dit is de reden waarom het gebruik begon en eindigde is belangrijk. Wilt u de locatie van wanneer de gebruiker het scherm voor het eerst aanraakt, of wanneer hij loslaat? In de meeste spelsituaties wil je weten wanneer de gebruiker het scherm aanraakt, maar niet altijd. Voor een volledige referentie van de touch-evenementen kun je hier terecht (https://developer.anscamobile.com/reference/index/events/touch).

Dus wanneer je dit uitvoert, zul je merken dat je alleen springt als je de linkerkant van het scherm aanraakt. De reden waarom we dat doen is omdat we de rechterkant van het scherm willen reserveren voor andere dingen, zoals schieten met vuurballen. Dat valt niet onder de scope van dit project, maar we komen er snel genoeg aan! Met dat alles daarbinnen zouden we nu goed moeten zijn om te gaan.

Met alles op zijn plaats zou je nu een monster moeten hebben dat op de grond kan rennen en springen! Langzaam begint onze kleine tutorial zich als een spel te voelen! Zoals altijd, als je vragen hebt, laat het me dan weten in de comments hieronder en bedankt voor het volgen!