Deze tutorial geeft een overzicht van de nieuwe functies van het SpriteKit-framework die werden geïntroduceerd in iOS 8. De nieuwe functies zijn ontworpen om het gemakkelijker te maken om geavanceerde game-effecten te ondersteunen en omvatten ondersteuning voor aangepaste OpenGL ES fragment shaders, belichting, schaduwen, geavanceerde nieuwe fysica-effecten en -animaties en integratie met SceneKit. In deze zelfstudie leert u hoe u deze nieuwe functies implementeert.
Voordat ik de tutorial start, wil ik graag Mélodie Deschans (Wicked Cat) bedanken voor het leveren van de game-art die in deze serie is gebruikt.
Deze tutorial gaat ervan uit dat je bekend bent met zowel SpriteKit en Objective-C. Om zonder shankuplag te werken met de arcering en de scène-editor, raad ik aan om Xcode 6.1 of hoger te downloaden en te installeren. Download het Xcode-project van GitHub, als je mee wilt gaan.
Deze serie is opgesplitst in twee tutorials en behandelt de belangrijkste nieuwe functies van het SpriteKit-framework. In het eerste deel bekijken we shaders, belichting en schaduwen. In het tweede deel zal ik het hebben over fysica en SceneKit-integratie.
Hoewel elk deel van deze serie op zichzelf staat, adviseer ik om stap voor stap de nieuwe functies van het SpriteKit-framework goed te begrijpen. Na het lezen van beide delen, kunt u zowel eenvoudige als geavanceerdere games maken met behulp van de nieuwe functies van het SpriteKit-framework.
SpriteKit biedt een renderingpijplijn die kan worden gebruikt om sprites te animeren. De renderingpijplijn bevat een rendering-lus die wisselt tussen het bepalen van de inhoud en rendering-frames. De ontwikkelaar bepaalt de inhoud van elk frame en hoe deze verandert. SpriteKit gebruikt de GPU van het apparaat om elk frame efficiënt weer te geven.
Het SpriteKit-framework is beschikbaar op zowel iOS als OS X en het ondersteunt veel verschillende soorten content, waaronder sprites, tekst, vormen en video.
De nieuwe SpriteKit-functies geïntroduceerd in iOS 8 zijn:
SKSpriteNode
, SKShapeNode
, SKEmitterNode
, SKEffectNode
, en SKScene
.SKNode
instances. Het maakt 3D-inhoud direct in de SpriteKit-renderingpijplijn. U kunt bestaande .dae- of .abc-bestanden importeren naar SKScene
.Ik heb een Xcode-project gemaakt om ons op weg te helpen. Hiermee kunnen we meteen de nieuwe SpriteKit-functies gaan gebruiken. Er zijn echter een paar dingen om op te letten.
SKScene
object met een SpriteKit-scènebestand, u zult altijd het unarchiveFromFile:
methode. Het is echter verplicht om voor elk SpriteKit-scènes-bestand het overeenkomstige toe te voegen SKScene
klasse.SKScene
object zonder een scènebestand van SpriteKit te gebruiken, moet u de initWithSize:
methode zoals vroeger in oudere versies van iOS.GameViewController
en GameScene
klassen bevatten een methode genaamd unarchiveFromFile:
. Deze methode transformeert grafische objecten die zijn gedefinieerd in een SpriteKit-scène en verandert ze in een SKScene
voorwerp. De methode gebruikt de InstanceType
sleutelwoord, omdat het een instantie van de klasse teruggeeft die het aanroept, in dit geval het SKScene
klasse.Download het project en neem even de tijd om door de mappen, klassen en bronnen te bladeren. Bouw en run het project op een fysiek apparaat of in de iOS-simulator. Als de applicatie zonder problemen draait, is het tijd om de nieuwe iOS 8 SpriteKit-functies te verkennen.
Voeg in het Xcode-project een nieuw toe SpriteKit-scène het dossier. Kiezen het dossier > nieuwe > Het dossier… en, van de hulpbron sectie, kies SpriteKit-scène. Noem maar op ShaderSceneEditor
en klik creëren. Er zou een grijze interface moeten verschijnen.
In de SKNode Inspector aan de rechterkant, zou u twee eigenschappen moeten zien, Grootte en Zwaartekracht. Stel de Grootte eigenschap rekening houdend met de schermresolutie van uw apparaat en ingesteld Zwaartekracht naar 0.0
.
Je zult zien dat de grootte van de gele rechthoek verandert om de veranderingen die je hebt aangebracht te weerspiegelen. De gele rechthoek is uw virtuele apparaatinterface. Het laat zien hoe objecten worden weergegeven op uw apparaat.
Binnen in de Objectbibliotheek aan de rechterkant, selecteer de Kleur Sprite en sleep het naar de gele rechthoek.
Selecteer de kleursprite en open de SKNode Inspector aan de rechterkant om de eigenschappen te zien.
U kunt in realtime met het object communiceren. Alle wijzigingen die u aanbrengt, worden weergegeven in de editor. Je kunt spelen met Positie, Grootte, Kleur, of Schaal, maar wat je echt wilt, is het Aangepaste Shader keuze. U zult echter merken dat er nog geen arcering beschikbaar is.
Voeg een nieuw leeg bronbestand toe (het dossier > Nieuw> Het dossier… ), Kiezen anders > Empty van de iOS sectie en noem deze Shader01.fsh. Voeg de volgende code toe aan het bestand dat u zojuist hebt gemaakt.
void main () float currTime = u_time; vec2 uv = v_tex_coord; vec2 circleCenter = vec2 (0,5, 0,5); vec3 circleColor = vec3 (0,8, 0,5, 0,7); vec3 posColor = vec3 (uv, 0.5 + 0.5 * sin (currTime)) * circleColor; float illu = pow (1 - afstand (uv, circleCenter), 4.) * 1.2; illu * = (2. + abs (0.4 + cos (currTime * -20. + 50. * distance (uv, circleCenter)) / 1.5)); gl_FragColor = vec4 (posColor * illu * 2., illu * 2.) * v_color_mix.a;
Het bovenstaande codeblok genereert een fusie van kleuren, rekening houdend met het midden van een cirkel en de rand ervan. Apple toonde deze shader in hun SpriteKit-sessie tijdens WWDC 2014.
Keer terug naar de editor, selecteer het sprite-object in kleur en in de Aangepaste Shader selecteer de shader die u zojuist hebt gemaakt. Je zou nu de shader in actie moeten zien.
Het programmeren van shaders met Xcode en SpriteKit is eenvoudig, omdat je realtime feedback krijgt. Open de Assistent redacteur en configureer het zodat zowel de SpriteKit-scène als de shader die u zojuist hebt gemaakt, worden weergegeven.
Laten we kijken hoe dit werkt. Voer een runtime-fout in de arcering in, bijvoorbeeld door de naam van een variabele te wijzigen en de wijzigingen op te slaan om het resultaat te bekijken.
Zoals u kunt zien, biedt Xcode een snelle en gemakkelijke manier om de ontwikkelaar te waarschuwen voor mogelijke arceringsfouten. Het voordeel is dat u uw applicatie niet hoeft te bouwen of implementeren op uw apparaat of de iOS Simulator om te zien of alles goed werkt.
Het is nu tijd om een andere arcering toe te voegen en deze handmatig te programmeren.
In deze stap leert u hoe u:
In deze stap voegt u een aangepast toe SKSpriteNode
op de positie van de gebruiker tikken en dan gebruik je een arcering om de textuurkleur van de SKSpriteNode
.
De eerste stap is om een andere arcering toe te voegen. Geef de nieuwe arcering een naam shader02.fsh en voeg het volgende codeblok toe aan het bestand van de arcering:
void main () gl_FragColor = texture2D (myTexture, v_tex_coord) * vec4 (1, 0.2, 0.2, 1);
Open het implementatiebestand van de ShaderScene
klasse. De eerste stap is om te detecteren of de gebruiker op het scherm tikt en de locatie van de tik te vinden. Daarvoor moeten we het touchesBegan: withEvent:
methode. Voeg binnen deze methode een toe SKSpriteNode
bijvoorbeeld op de locatie van de kraan. Je kunt elke gewenste sprite gebruiken. Ik heb gebruikt Spaceship.png, die al in het project is opgenomen.
- (ongeldig) raaktBegan: (NSSet *) raakt aan metEvent: (UIEvent *) -gebeurtenis voor (UITouch * touch in touch) CGPoint location = [touch locationInNode: self]; // Maak het knooppunt SKSpriteNode * space = [SKSpriteNode spriteNodeWithImageNamed: @ "Spaceship.png"]; space.position = CGPointMake (location.x, location.y); [self addChild: spatie];
We maken vervolgens een SKShader
object en initialiseer het met behulp van de shader02.fsh het dossier:
SKShader * shader = [SKShader shaderWithFileNamed: @ "shader02.fsh"];
U hebt misschien gemerkt dat het bronbestand van de arcering verwijst naar a myTexture
voorwerp. Dit is geen voorgedefinieerde shader-eigenschap, maar een referentie die uw toepassing moet doorgeven aan de arcering. Het volgende codefragment illustreert hoe dit moet.
shader.uniforms = @ [[SKU-uniform uniformWithName: @ "myTexture" texture: [SKTexture textureWithImageNamed: @ "Spaceship.png"]]];
Vervolgens voegen we de arcering toe aan de SKSpriteNode
voorwerp.
space.shader = shader;
Dit is wat de touchesBegan: withEvent:
methode moet er als volgt uitzien:
- (ongeldig) raaktBegan: (NSSet *) raakt aan metEvent: (UIEvent *) -gebeurtenis voor (UITouch * touch in touch) CGPoint location = [touch locationInNode: self]; // Maak het knooppunt SKSpriteNode * space = [SKSpriteNode spriteNodeWithImageNamed: @ "Spaceship.png"]; space.position = CGPointMake (location.x, location.y); [self addChild: spatie]; SKShader * shader = [SKShader shaderWithFileNamed: @ "shader02.fsh"]; shader.uniforms = @ [[SKU-uniform uniformWithName: @ "myTexture" texture: [SKTexture textureWithImageNamed: @ "Spaceship.png"]]]; space.shader = shader;
Bouw en run uw project. Druk op Shaders (initWithSize) knop en tik op het scherm. Elke keer dat je op het scherm tikt, wordt een ruimteschipsprite toegevoegd met een gewijzigde textuur.
Met deze optie ziet u dat de eerste arcering niet op het scherm wordt weergegeven. Dit gebeurt omdat de arcering is gemaakt en geconfigureerd in de SpriteKit-scène-editor. Om het te zien, moet je de ShaderScene
klasse met behulp van de unarchiveFromFile:
methode.
In GameScene.m, u zou een sectie moeten zien die de tikken van de gebruiker detecteert en parseert touchesBegan: withEvent:
. In de seconde als
clausule, initialiseren we a ShaderScene
bijvoorbeeld zoals hieronder getoond.
if ([node.name isEqualToString: @ "buttonShaderCoder"]) ShaderScene * scene = [ShaderScene unarchiveFromFile: @ "ShaderSceneEditor"]; [self.scene.view presentScene: scene];
Bouw je project opnieuw en voer het uit, tik op de Shaders (initWithCoder) knop en tik op het scherm. Beide shaders zijn nu actief in een enkele SpriteKit-scène.
Verlichting en schaduwen zijn twee eigenschappen die samen spelen. Het doel van deze sectie is om verschillende lichtpunten en sprites toe te voegen en met hun eigenschappen te spelen.
Open LightingSceneEditor.sks en blader door de objecten binnen de Mediatheek aan de rechterkant. In de Mediatheek, je kunt de bronnen zien die in het project zijn opgenomen.
Selecteer en sleep background.jpg naar de gele rechthoek. Als u de standaard scènresolutie niet hebt gewijzigd, moet de afbeelding in de rechthoek passen.
Wanneer u de sprite selecteert, merkt u dat deze verschillende eigenschappen heeft zoals Positie, Grootte, Z Positie, Verlichtingsmasker, Shadow Casting Mask, Definitie van natuurkunde, en vele anderen.
Voel je vrij om met deze eigenschappen te spelen. Voor nu is het echter belangrijk dat u de eigenschappen op hun standaardwaarden laat staan. Sleep een Licht object van de Objectbibliotheek aan de rechterkant op de achtergrondsprite. De positie van het licht is niet belangrijk, maar de andere eigenschappen van het licht zijn dat wel.
U kunt het configureren Kleur, Schaduw, en omringend kleur om het licht en de schaduw te configureren. De Z positie is de hoogte van het knooppunt ten opzichte van het bovenliggende knooppunt. Zet het op 1. De Verlichtingsmasker definieert tot welke categorieën dit licht behoort. Wanneer een scène wordt weergegeven, is er een lamp categoryBitMask
eigenschap wordt vergeleken met elke sprite knooppunt lightingBitMask
, shadowCastBitMask
, en shadowedBitMask
eigenschappen. Als de waarden overeenkomen, interageert die sprite met het licht. Hiermee kunt u meerdere lichten definiëren en gebruiken die communiceren met een of meer objecten.
Je hebt waarschijnlijk gemerkt dat de achtergrond niet is veranderd na het toevoegen van het licht. Dat gebeurt omdat het verlichtingsmasker van het licht en de achtergrond anders zijn. U moet het verlichtingsmasker op de achtergrond instellen op dat van het licht, dat is 1 in ons voorbeeld.
Werk de achtergrond bij in de SKNode Inspector en druk op enter. Het effect van deze verandering is onmiddellijk. Het licht verlicht nu de achtergrond op basis van zijn positie. U kunt de positie van het licht wijzigen om de interactie tussen de achtergrond en lichtpunten in realtime te bekijken.
Als u het realisme van de achtergrond wilt vergroten of de nadruk wilt leggen op een van de functies, speelt u met de Gladheid en Contrast eigenschappen. Speel met de waarden om de wijzigingen in realtime te bekijken.
Het is nu tijd om een paar objecten toe te voegen die interactie hebben met het lichtknooppunt. In de Mediatheek, vind de kroket-o.png en kroket-x.png sprites en voeg ze toe aan de scène.
Elke sprite moet afzonderlijk worden geconfigureerd. Selecteer elke sprite en stel de Verlichtingsmasker, Shadow Cast Mask, ende Z positie naar 1. Het verlichtingsmasker zorgt ervoor dat de sprite wordt beïnvloed door het lichtknooppunt, terwijl het schaduwmasker een realtime schaduw creëert op basis van de positie van het lichtknooppunt. Stel tot slot de Lichaamstype (Definitie van natuurkunde) naar Geen. Doe dit voor beide sprites.
Je had moeten opmerken dat, zelfs na het instellen van de eigenschappen van licht en schaduw, je de interactie tussen het licht en de knooppunten niet kunt zien. Daarvoor moet je het project bouwen en uitvoeren op een fysiek apparaat of in de Simulator.
Je weet al hoe je lichten kunt toevoegen met de scène-editor. Laten we eens kijken hoe we een licht kunnen toevoegen zonder de scène-editor te gebruiken.
Open de LightingScene.m en in de didMoveToView:
methode die we creëren SKSpriteNode
object en een SKLightNode
voorwerp.
Voor de SKSpriteNode
object, we gebruiken de Wicked-Cat.png sprite. De positie van het knooppunt is niet zo belangrijk, maar de waarden van zPosition
, shadowCastBitMask
, en lightingBitMask
zijn. Omdat SpriteKit de gegevens achter elkaar parseert, moet u de knooppunten instellen zPosition
naar 1
om deze sprite zichtbaar te maken, bovenop de achtergrondsprite. We gaan zitten shadowCastBitMask
en lightingBitMask
naar 1
.
Dit is wat de didMoveToView:
methode ziet er als volgt uit:
- (void) didMoveToView: (SKView *) view SKSpriteNode * sprite = [SKSpriteNode spriteNodeWithImageNamed: @ "Wicked-Cat.png"]; [sprite setPosition: CGPointMake (self.frame.size.width / 2, self.frame.size.height / 2)]; [sprite setScale: 0,6]; [sprite setZPosition: 1]; [sprite setShadowCastBitMask: 1]; [sprite setLightingBitMask: 1]; [self addChild: sprite];
Laten we de volgende toevoegen SKLightNode
voorwerp. U moet speciale aandacht besteden aan de categoryBitMask
eigendom. Als je het instelt op 1
, dit licht zal interactie hebben met elke sprite. Noem maar op licht
En instellen zPosition
naar 1
.
Het volledige fragment voor de SKLightNode
zou er als volgt uit moeten zien:
SKLightNode * light = [[SKLightNode alloc] init]; [light setName: @ "light"]; [light setPosition: CGPointMake (100, 100)]; [light setCategoryBitMask: 1]; [licht setFalloff: 1,5]; [lichtsetZPosition: 1]; [light setAmbientColor: [UIColor whiteColor]]; [light setLightColor: [[UIColor alloc] initWithRed: 1.0 groen: 0.0 blue: 0.0 alpha: .5]]; [light setShadowColor: [[UIColor alloc] initWithRed: 0.9 green: 0.25 blue: 0.0 alpha: .5]]; [self addChild: light];
Op dit punt heb je een tweede licht. Maar laten we wat gebruikersinteractie toevoegen. Daarvoor zou je het moeten toevoegen touchesMoved: withEvent:
methode en verander de lichtpositie, rekening houdend met de locatie van de tik.
-(void) raakt aanMoved: (NSSet *) raakt aan metEvent: (UIEvent *) -gebeurtenis voor (UITouch * touch in aanraking) CGPoint location = [touch locationInNode: self]; [self childNodeWithName: @ "light"]. position = CGPointMake (location.x, location.y);
Tenslotte,bouw en run uw applicatie. Druk op Verlichting knop en je zou iets moeten zien dat lijkt op het screenshot hieronder:
Dit is de eerste tutorial in onze tweedelige serie over de nieuwe functies van het SpriteKit-framework die werden geïntroduceerd in iOS 8. In dit deel heb je geleerd om aangepaste shaders en lichteffecten te maken met behulp van zowel de SpriteKit Scene-editor als via code. Als u vragen of opmerkingen heeft, kunt u zoals altijd een regel in de opmerkingen plaatsen.