Welkom bij het derde deel van onze eindeloze runner game! Deze tutorial gaat behandelen hoe je sprites kunt maken via sprite sheets en de animatie van ons gamekarakter. Tot dusverre moeten we in ons spel een mooi beeld hebben met drie lagen afbeeldingen die met verschillende snelheden scrollen, wat zorgt voor een aantal geweldige parrallax-scrolling-ness! De volgende logische stap voor ons is om onze held aan het spel toe te voegen. We gaan dit in twee stappen doen. Deze tutorial behandelt de eerste stap. De volgende zelfstudie gaat over het feitelijk toevoegen van de held aan ons bestaande spel en het toevoegen van knoppen zodat hij onze opdracht volgt.
Laten we nu, voordat we aan de game beginnen, snel praten over sprites, sprite sheets en animaties in algemene termen. Als u ervaring hebt met het ontwikkelen van afbeeldingen, animaties of games, is dit waarschijnlijk een bekend onderwerp voor u. In onze discussie gaan we er echter van uit dat u geen ervaring hebt met een van de bovengenoemde onderwerpen. Laten we beginnen met animatie. Animatie in games gebeurt op exact dezelfde manier als in cartoons en films. Denk aan wat er gebeurt als je naar de film gaat en ze beginnen de film. Wanneer je naar de film kijkt, kijk je niet echt naar mensen die bewegen en praten, maar kijk je naar een reeks flitsende beelden met tegelijkertijd geluid langs de spoel, waardoor je de illusie krijgt dat je naar iets kijkt dat leeft en ademen. Dit is hetzelfde als bij onze spellen. We creëren de illusie van "leven" door snel knipperende beelden op het scherm. Wanneer dit snel genoeg wordt gedaan, wordt het een vloeiende animatie. Dus, de vraag is hoe we deze vloeiende animaties in ons spel krijgen. Het antwoord is om sprites te gebruiken. De Corona SDK biedt de functionaliteit van sprites voor ons, dus het enige waar we ons zorgen over moeten maken is het maken van onze sprites en het toewijzen van onze animaties aan hen. Bekijk het geanimeerde gif hieronder:
Als je die animatie ziet, lijkt het erop dat er een klein monster loopt en zijn armen in de lucht zwaait. Waar je echt naar kijkt, is een reeks afbeeldingen, genomen van één enkele sprite sheet, steeds opnieuw knipperend. Merk op dat de laatste afbeelding in de reeks niet is opgenomen in de animatie. Dit is een eenvoudig sprite-blad en het is ook hoe je de afbeeldingen voor je spel instelt.
Dus de vraag waarom we spritebladen gebruiken, is waarschijnlijk in je opgekomen. Het antwoord is tweeledig en vrij eenvoudig: geheugen en eenvoud. Ik wil dat je de vier afbeeldingen hieronder bekijkt. Heel eenvoudig, geruit bordontwerp (hoewel de sprites erg klein zijn, dus dat lijken ze niet te zijn, maar open ze in elk programma en zoom in en je ziet het dambord: D), met maten van 8x8 helemaal tot 256x256.
De eerste reden, het geheugen, zal heel duidelijk worden als je de afbeeldingen downloadt en naar hun grootte kijkt. Let op het verschil in grootte tussen 8x8 helemaal tot 256x256. Als je ze niet wilt downloaden, zal ik je de 30 seconden besparen die het zou hebben gekost.
Laten we aannemen dat al onze afbeeldingen 16x16 pixels in dimensie zullen zijn (dit is natuurlijk niet realistisch, maar ons voorbeeld geldt ook voor veel grotere afbeeldingen). De afbeeldingen zijn 16x16 en nemen maar liefst 2.74KB op. Laten we zeggen dat we 256 sprites hebben die ons karakter vormen. Deze afbeeldingen kunnen bestaan uit het lopen in verschillende richtingen, springen, een wapen schieten of iets anders doen dat je misschien wilt dat je personages doen. Als we ze in afzonderlijke 16x16 PNG-bestanden zouden plaatsen (PNG is een veelgebruikt formaat voor mobiele games omdat ze een heel kleine geheugenvoetafdruk hebben), zou het maximaal 701.44KB duren om alle afbeeldingen te bevatten. Dat lijkt niet zo groot omdat de meeste apparaten veel geheugen hebben, toch? Ja, maar onthoud dat we waarschijnlijk honderden van dergelijke afbeeldingen in onze game zullen hebben. Toch is 701K voor een kleine afbeelding op een mobiel apparaat VEEL te groot. Op de iPhone proberen de meeste kleine games onder de 20 MB te blijven omdat het het grootste bestand is dat je via 3G kunt downloaden. Grotere bestanden moeten via WiFi worden gedownload of via iTunes worden gedownload. Als je denkt dat een limiet van 20 MB slecht is, was het 10 MB! Laten we nu kijken naar waarom het nuttig is om onze sprites te groeperen in spritebladen.
Stel dat u die 256 16x16 sprites op slechts één sprite-blad plaatst. Hoe groot denk je dat het resulterende bestand zou zijn? Als je de bestanden hebt gedownload en naar de formaten hebt gekeken, weet je dat de 256x256-afbeelding slechts 3,42 KB is! Dat is een besparing van 698.02KB! Maar hoe is dat mogelijk!?! Het antwoord heeft te maken met hoe afbeeldingen worden geschaald en gecomprimeerd en een heleboel andere technische dingen waar we niet op in zullen gaan. Het belangrijkste om mee te nemen is dat het verdubbelen van een afbeelding in grootte niet noodzakelijkerwijs het dubbele is in het geheugen. Als je de andere formaten van de afbeeldingen bekijkt, zul je merken dat de grootte van de afbeeldingen van 16x16 tot 128x128 sprite slechts 2.98KB kan bedragen en dat de 256x256 slechts 3,43KB kan verplaatsen! Ik weet het, geweldig toch!?!
De tweede reden waarom we dit doen, is omwille van de eenvoud. Sprite-bladen bieden een mooie manier om al onze afbeeldingen te ordenen. Als je ooit een spel hebt gespeeld op de Atari, NES, Sega Saturn, SNES, Gameboy of vrijwel alles wat 2D is, dan heb je sprite-sheets gezien op het werk. Sommige van die spellen bevatten duizenden en duizenden sprites. Neem een spel zoals Final Fantasy 3 op de Super Nintendo (waarvan we allemaal weten dat het echt Final Fantasy 6 is, toch?). Ze hebben tientallen personages, honderden vijanden, spreuken, items, terreintypen en waarschijnlijk enkele tientallen andere dingen die ik weglaat. Dus hoe houden ze al die individuele sprites bij? Nogmaals, het antwoord is sprite sheets. Stel je voor dat in plaats van tientallen sprites of sprite sheets voor elk personage, ze alle afbeeldingen voor elk personage op 1 vel hadden. Op die manier wisten ze altijd precies waarnaar ze moesten verwijzen. Het leven wordt exponentieel eenvoudiger bij het werken aan grote projecten. Als een snelle referentie, google afbeelding zoeken naar "Finaly Fantasy 6 Sprite Sheets" en bekijk enkele van de sprite sheets van Final Fantasy om een idee te krijgen van hoe ze worden gebruikt in grote games.
Het algehele proces van het maken van sprites met animaties is een vrij eenvoudig proces. Open een leeg bestand en noem dit main.lua. Het eerste dat we moeten doen, is onze sprite-handler instellen. Ga je gang en plaats de volgende code in:
--Dit zou er bekend uit moeten zien, verbergt de statusbalk van weergave display.setStatusBar (display.HiddenStatusBar) - 'sprite' is wat we zullen gebruiken om onze sprite sheets te maken - 'require' laat Corona weten dat we aan het bellen zijn reeds gevestigde functies in een ander bestand. "sprite" is al ingebouwd in - Corona, dus we hoeven hier niet meer aan te werken - we zullen sprite als een 'sprite handler' gebruiken om spritesheets te maken local sprite = require ("sprite")
Omdat Corona het meeste werk al voor ons heeft gedaan, blijven we met een vrij eenvoudig proces. Hier is wat je moet onthouden. Van onze sprite-handler maken we een sprite-sheet. Van onze sprite sheet maken we 'sets'. Van onze sets maken we animaties en sprite-objecten. Voor deze methode voor het maken van sprite-werkbladen, moet elke sprite dezelfde dimensie hebben. Dus elk frame van ons kleine monster is 100x100. In dit voorbeeld is er één lang blad met sprites. Om dit het best en het meest efficiënt te laten werken, moeten sprite-sheets altijd in machten van 2 worden gemaakt. 2x2, 4x4, 16x16, 32x32, 64x64, enz. Natuurlijk zult u nooit iets gebruiken dat klein is, maar dit klopt helemaal tot 1024x1024. Je kunt in theorie zelfs nog groter worden, maar elk apparaat heeft een maximale textuurgrootte en als je boven die texture-grootte gaat, kan je app de Sprite-sheets niet laden. Dus, voordat je spritebladen gaat toevoegen die 4096x4096 zijn, moet je je onderzoek doen om ervoor te zorgen dat je doelapparaat het aankan! Een ander ding om op te merken is dat wanneer je je afbeeldingen in een vierkant hebt, het ze op dezelfde manier zal lezen als je een boek zou lezen. Van boven naar beneden, van links naar rechts, zoals zo:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Dus als je je sprite laat kijken naar frames 6 tot 12, weet hij automatisch waar hij moet zijn.
Voeg deze code toe aan uw project onder de vereiste regel:
--door een nieuw spritesheet te maken, doorbreek je de afbeelding die je hebt geplaatst in even blokken die 100 - 100 zijn, verander die parameters in elke grootte van je afbeeldingen. Merk op dat deze methode - voor het maken van sprite alleen werkt voor sprites van dezelfde grootte. Er zijn andere methoden - om sprites van verschillende groottes te verwerken, maar dat valt buiten het bestek van deze tutorial. local spriteSheet = sprite.newSpriteSheet ("images / monsterSpriteSheet.png", 100, 100) - van ons spritesheet maken we een spriteSet, dit is hoe we hoe we verschillende sprites kunnen groeperen - samen voor organisatiedoeleinden. Stel dat we bijvoorbeeld 2 verschillende monsters hadden, dan konden we ze in dezelfde sprite plaatsen en 2 verschillende spritesets maken die elk de informatie bevatten voor hun respectievelijke frames. Deze sprite-set bevat alle zeven frames in onze afbeelding, gedefinieerd door 1 en 7. lokale monsterSet = sprite.newSpriteSet (spriteSheet, 1, 7) - daarna maken we animaties van onze sprite-sets. Om dit te doen, vertel je eenvoudig de --functie die voor ons ingesteld is, geef je de animatie een naam, geef je het startframe en het aantal frames in de animatie, het aantal milliseconden - we willen 1 animatie en uiteindelijk het aantal keren dat we de --animatie willen uitvoeren. 0 laat het lopen totdat we de animtion vertellen om te stoppen met sprite.add (monsterSet, "running", 1, 6, 600, 0) sprite.add (monsterSet, "jumping", 7, 7, 1, 1) - de laatste stap is om een sprite te maken van onze sprite-set die alle animaties bevat. local hero = sprite.newSprite (monsterSet)
Nu we onze sprite sheet hebben gemaakt en daar een sprite-object van hebben gemaakt, laten we een aantal basisbegrippen initialiseren die we voor hem nodig hebben.
Voeg dit toe onder het laatste stukje code dat je hebt ingevoerd:
--vindt het midden van het scherm x = display.contentWidth / 2 y = display.contentHeight / 2 - een booleaanse variabele die aangeeft in welke richting we naar rechts bewegen = true hero.x = x hero.y = y
Die code plaatst onze sprite in het midden van het scherm. Voeg vervolgens deze code toe:
--gebruik voorbereiden om de sprite te laten weten welke animatie het gaat gebruiken held: voorbereiden ("hardlopen") - een oproep starten start de geladen animatieheld: play ()
Voer deze code uit en we zouden ons kleine monster op zijn plaats moeten laten lopen in het midden van het scherm. Dat is echt alles wat er is om geanimeerde sprites te maken van Sprite-bladen. We zullen ze wat grondiger gebruiken in de volgende tutorials. Voor een volledige verwijzing naar Sprite-bladen, kunt u de Corona SDK-referentie bekijken. Dit is alles wat we nu over dit onderwerp gaan bespreken, dus hopelijk is het genoeg om je op weg te helpen! Voor een laatste effect voordat je ons monster over het scherm laat rennen, voeg je de volgende code toe aan de onderkant van je code:
functie-update () --als we rechts draaien, blijf dan naar rechts bewegen als (rechts) dan hero.x = hero.x + 3 - als we niet bewegen, ga dan naar links anders blijven hero.x = hero.x - 3 einde - als ons monster van het scherm is weggelopen, draai hem dan - en ren in de tegenovergestelde richting. hero.xScale = -1 - zal onze sprite horizontaal spiegelen als (hero.x> 380) en dan rechts = false hero.xScale = -1 end if (hero.x < -60) then right = true hero.xScale = 1 end end --call the update function timer.performWithDelay(1, update, -1)
Gemakkelijke dingen. Verwijder alle opmerkingen die ik in de code heb gemaakt om dingen uit te leggen en je zult zien hoe gemakkelijk Corona mooie geanimeerde sprites opzet. Laat het me weten als u vragen en opmerkingen heeft!