En introduksjon til GameplayKit: Part 1

An Introduksjon til GameplayKit: Part 1
27
Del
11
Del
Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av
Dette innlegget er en del av en serie som heter An Introduction to GameplayKit.An Introduksjon til GameplayKit. Del 2
Innledning

I tillegg til alle de nye funksjonene og rammeverk i iOS 9 Hotell og OS X El Capitan
, med årets utgivelser Apple også skapt en helt ny ramme vartet spillutviklere, GameplayKit
. Med eksisterende grafikk-APIer (SpriteKit, SceneKit og Metal) gjør det lett å lage flotte spill på iOS og OS X, har Apple nå lansert GameplayKit å gjøre det enkelt å lage spill som spille
godt. Denne nye rammeverket inneholder mange klasser og funksjoner som kan brukes til å enkelt legge kompleks logikk til spill

I denne første opplæringen, vil jeg lære deg om to viktige aspekter av GameplayKt rammeverket.


enheter og komponenter

tilstandsmaskiner

Forutsetninger

Denne opplæringen forutsetter at du kjører Xcode 7
på OS X Yosemite eller senere. Selv om ikke nødvendig, anbefales det at du har en fysisk enhet som kjører iOS 9
som du vil få mye bedre ytelse når du tester den SpriteKit-basert spill som brukes i denne opplæringen.

1. Komme i gang

Du vil først må laste ned starter prosjektet for denne serien av tutorials fra GitHub. Når du har gjort dette, åpne prosjektet i Xcode og kjøre den på enten iOS Simulator eller enheten din.

Du vil se at det er en helt grunnleggende spill der du styrer en blå prikk og navigere rundt kartet. Når du kolliderer med en rød prikk, mister du to poeng. Når du kolliderer med en grønn prikk, får du ett poeng. Når du kolliderer med en gul prikk, blir frosset i et par sekunder din egen prikk.

På dette stadiet, er det en veldig grunnleggende spillet, men i løpet av denne opplæringen serien, og med hjelp av GameplayKit, vi kommer til å legge inn mye mer funksjonalitet og spillelementer.

2. Enheter og komponenter

Den første store aspekt av den nye GameplayKit rammeverket er en kode-strukturering konsept basert på enheter og komponenter. Det fungerer ved at du, utvikleren, for å skrive felles kode som brukes av mange forskjellige objekttyper i spillet ditt mens du holder den godt organisert og håndterlig. Konseptet med enheter og komponenter er ment å eliminere felles arv basert tilnærming for å dele felles funksjonalitet mellom objekttyper. Den enkleste måten å forstå dette konseptet er med noen eksempler så tenk på følgende scenario:

Du bygger et tårn Defense spill med tre hovedtyper av tårnene, Fire, Ice og Heal. De tre typer tårn ville dele noen vanlige data, som for eksempel helse, størrelse og styrke. Dine ild og is tårn må være i stand til å målrette innkommende fiender å skyte på mens din Heal tårnet ikke. Alt for at din Heal tårnet trenger å gjøre er å reparere andre tårnene innenfor en viss radius som de får skader

Med denne grunnleggende spillet modell i tankene, la oss se hvordan koden din kan bli organisert ved hjelp av en arv struktur. < .no>
En forelder Tower klasse som inneholder felles data som helse, størrelse og styrke.

firetower, IceTower, og HealTower klasser som vil arve fra tårnet klassen.

I HealTower klassen, har du logikken ansvarlig for healing dine andre tårnene innenfor en viss radius.

Så langt er denne strukturen greit, men et problem nå oppstår når du trenger å implementere Brann og istårn 'målretting evne. Har du bare kopiere og lime inn den samme koden på begge din firetower og IceTower klasser? Hvis du trenger å gjøre noen endringer, vil du da trenger å endre koden i mer enn ett sted, noe som er kjedelig og utsatt for feil. På toppen av dette, hva skjer hvis du ønsker å legge inn en ny tårn type som også trenger denne målretting funksjonalitet. Har du kopiere og lime det en tredje gang?

Den beste måten synes å være å sette dette målretting logikk i den overordnede Tower klassen. Dette vil tillate deg å bare ha én kopi av koden som bare må redigeres på ett sted. Legge denne koden her, men ville gjøre Tower klassen mye større og mer komplisert enn den trenger å være når ikke alle sine underklasser trenger den funksjonaliteten. Hvis du også lyst til å legge til mer felles funksjonalitet mellom tårn typer, ville Tower klasse gradvis blitt større og større, noe som ville gjøre det vanskelig å jobbe med.

Som du kan se, mens det er mulig å lage et spill modell basert på arv, kan det veldig fort og lett bli uorganisert og vanskelig å administrere

Nå, la oss se hvordan dette samme spillet modellen kan være strukturert ved hjelp av enheter og komponenter.
< li> Vi ville skape firetower, IceTower, og HealTower enheter. Flere enheter kan bli opprettet for noen flere tårn typer du vil legge til senere.

  • Vi vil også opprette en BasicTower komponent som ville inneholde helse-, størrelse, styrke, etc.

    For å håndtere helbredelse av tårnene innenfor en viss radius, vil vi legge til en Healing komponent.

    En komponent Targeting vil inneholde koden som trengs for å målrette innkommende fiender.

    Ved hjelp GameplayKit og denne strukturen ville du da ha en unik enhet type for hvert tårn type i spillet ditt. Til hver enkelt enhet, kan du legge de ønskede komponentene du vil. For eksempel:

    Dine firetower og IceTower enheter ville hver ha en BasicTower og komponent Targeting knyttet til det

    HealTower foretaket ville ha både en BasicTower og Healing komponent

    Som du kan se, ved hjelp av en virksomheten som helhet og komponentbasert struktur, er spillet modellen nå mye enklere og mer allsidig. Målrettingen logikk bare må skrives en gang og bare linker til enheter som det er behov for. Likeledes, de grunnleggende tårn data fortsatt kan enkelt deles mellom alle tårnene uten bulking opp alle dine andre felles funksjonalitet.

    En annen stor ting om denne virksomheten som helhet og komponentbasert struktur er at komponenter kan legges til og fjernes fra enhetene når du vil. For eksempel, hvis du ønsket å helbrede tårnene til å være deaktivert under visse vilkår, kan du bare fjerne Healing komponenten fra din enhet til de rette betingelsene er oppfylt. Likeledes, hvis du ønsker en av dine Brann tårnene for å få en midlertidig helbredende evner, kan du bare legge et Healing komponent til din firetower enhet for en bestemt tidsperiode.

    Nå som du er komfortabel med begrepet virksomheten som helhet og komponent-basert spill modellstruktur, la oss lage ett innenfor vårt eget spill. I Xcode Fil Inspector, finne de Entities mappe i prosjektet. For enkelhets skyld er det allerede tre foretakets klasser for deg, men du er nå kommer til å opprette en ny enhet fra scratch

    Velg Fil >.; New > Fil ... eller trykk Kommando-N for å opprette en ny klasse. Sørg for å velge Cocoa Touch Class mal fra iOS > Kilde delen. Navn klassen Player og gjøre det til en underklasse av GKEntity.

    Du vil se at umiddelbart etter åpning den nye filen Xcode vil vise en feilmelding. For å fikse dette, legger du til følgende import uttalelse under den eksisterende import UIKit uttalelse:
    import GameplayKit

    Gå tilbake til PlayerNode.swift og legge til følgende eiendom til PlayerNode Klasse:
    Var enhet = Player () < p> Deretter går du til komponenter mappen i Xcode prosjekt og lage en ny klasse akkurat som du gjorde før. Denne gangen nevne klassen FlashingComponent og gjøre det en underklasse av GKComponent som vist nedenfor.

    Komponenten du nettopp har opprettet kommer til å håndtere den visuelle blinkende av vår blå prikk når det blir truffet av en rød prikk og er i sin usårbar tilstand. Erstatte innholdet i FlashingComponent.swift med følgende:
    import UIKitimport SpriteKitimport GameplayKitclass FlashingComponent: GKComponent {var nodeToFlash: SKNode! func startFlashing () {la fadeAction = SKAction.sequence ([SKAction.fadeOutWithDuration (0,75), SKAction.fadeInWithDuration (0,75)]) nodeToFlash.runAction (SKAction.repeatActionForever (fadeAction), withKey: "flash")} deinit {nodeToFlash. removeActionForKey ("flash")}}

    Gjennomføringen bare holder en referanse til et SKNode objekt og gjentar fade inn og fade ut handlinger i rekkefølge så lenge komponenten er aktiv.

    Gå tilbake til GameScene. rask og legge til følgende kode eller annet sted innenfor didMoveToView (_ :) metode:
    //Legge Componentlet flash = FlashingComponent () flash.nodeToFlash = playerNodeflash.startFlashing () playerNode.entity.addComponent (flash)

    Vi skaper en FlashingComponent objekt og sette den opp til å utføre sin blinker på spillerens dot. Den siste linjen legger deretter komponenten for foretaket å holde den aktiv og gjennomføring.

    Bygg og kjøre programmet ditt. Du vil nå se at den blå prikken sakte fades inn og ut flere ganger.

    Før du går videre, slette koden som du nettopp har lagt fra didMoveToView (_ :) metoden. Senere, vil du være å legge denne koden tilbake, men bare når blå prikk går inn i sitt usårbar tilstand.

    3. State Machines

    I GameplayKit, tilstandsmaskiner gir en måte for deg å enkelt identifisere og utføre oppgaver basert på den nåværende tilstanden i et bestemt objekt. Tegning fra tidligere tårnet forsvaret eksempel kan noen mulige tilstander for hvert tårn inkluderer Active, Deaktivert, og ødelagt. En stor fordel med tilstandsmaskiner er at du kan angi som sier en annen stat kan flytte til. Med de tre eksempel landene nevnt ovenfor, ved hjelp av en tilstandsmaskin, kan du sette staten maskinen opp slik at:

    kan et tårn blir deaktivert når Aktiv og vice versa

    et tårn kan bli ødelagt når enten Aktiv eller Disabled

    et tårn kan ikke bli aktiv eller deaktivert når den har blitt ødelagt

    I spillet for denne opplæringen, skal vi holde det veldig enkelt og bare ha et normalt og usårbar tilstand.

    I prosjektets State Machine mappen oppretter to nye klasser. Navngi dem NormalState og InvulnerableState henholdsvis med både å være en underklasse av GKState klassen

    Erstatt innholdet NormalState.swift med følgende:.
    Import UIKitimport SpriteKitimport GameplayKitclass NormalState: GKState {var node: PlayerNode init (withNode: PlayerNode) {node = withNode} overstyring func isValidNextState (stateClass: AnyClass) - > Bool {bytte stateClass {saken InvulnerableState.Type: return true standard: return false}} overstyring func didEnterWithPreviousState (previousState:? GKState) {if la _ = previousState som? InvulnerableState {node.entity.removeComponentForClass (FlashingComponent) node.runAction (SKAction.fadeInWithDuration (0,5))}}}

    NormalState klassen inneholder følgende:

    Det implementerer en enkel initializer å holde en referanse til den aktuelle spillerens node.

    Den har en implementering for isValidNextState (_ :) metoden. Denne metoden implementering returnerer en boolsk verdi, noe som indikerer hvorvidt den nåværende tilstanden klassen kan flytte til staten klassen levert av metoden parameter.

  • Klassen inneholder også en implementering for didEnterWithPreviousState (_ :) tilbakeringing metoden. I metoden implementering, sjekker vi om tidligere tilstand var InvulnerableState staten og, hvis sant, fjerne blinkende komponent fra spillerens enhet.

    Nå åpner InvulnerableState.swift og erstatte innholdet med følgende :
    importere UIKitimport GameplayKitclass InvulnerableState: GKState {var node: PlayerNode init (withNode: PlayerNode) {node = withNode} overstyring func isValidNextState (stateClass: AnyClass) - > Bool {bytte stateClass {saken NormalState.Type: return true standard: return false}} overstyring func didEnterWithPreviousState (previousState:? GKState) {if la _ = previousState som? NormalState {//Legger Component la flash = FlashingComponent () flash.nodeToFlash = node flash.startFlashing () node.entity.addComponent (flash)}}}

    InvulnerableState klassen er svært lik den NormalState klassen. Den viktigste forskjellen er at ved å delta i denne tilstanden du legge den blinkende komponent til spillerens enhet i stedet for å fjerne den.

    Nå som statlige klasser er både komplett, åpen PlayerNode.swift igjen og legge til følgende linjer til PlayerNode Klasse:
    Var State: GKStateMachine func enterNormalState () {self.stateMachine.enterState (NormalState)}

    Dette kodebiten legger til en ny eiendom til PlayerNode klasse og implementerer en praktisk metode for å gå tilbake til normal . state

    Nå åpner GameScene.swift, og på slutten av didMoveToView (_ :) metoden, legge til følgende to linjer:
    playerNode.stateMachine = GKStateMachine (heter det: [NormalState (withNode: playerNode ), InvulnerableState (withNode: playerNode)]) playerNode.stateMachine.enterState (NormalState)

    I disse to linjer med kode, skaper vi en ny GKStateMachine med de to statene og fortelle det å gå inn i NormalState
    Til slutt erstatte gjennomføringen av handleContactWithNode (_ :) metoden i GameScene klassen med følgende gjennomføring:
    func handleContactWithNode (kontakt:. ContactNode) {if kontakt er PointsNode {NSNotificationCenter.defaultCenter () postNotificationName ("updateScore" , objekt: selvtillit, Userinfo: ["score": 1])} else if kontakt er RedEnemyNode & & playerNode.stateMachine.currentState! er NormalState {NSNotificationCenter.defaultCenter () postNotificationName. ("updateScore", objekt: selvtillit, Userinfo: ["score": -2]) playerNode.stateMachine.enterState (InvulnerableState) playerNode.performSelector ("enterNormalState", withObject: null, afterDelay: 5,0)} else hvis kontakten er YellowEnemyNode & & playerNode.stateMachine.currentState! er NormalState {self.playerNode.enabled = false} contact.removeFromParent ()}

    Når spillerens blå prikk kolliderer med en rød fiende prikk, vil spilleren gå inn i InvulnerableState staten i fem sekunder og deretter gå tilbake til den NormalState staten . Vi sjekker også hva den nåværende tilstanden i spilleren er, og bare utføre noen fiende relaterte logikk hvis det er NormalState staten.

    Bygg og kjøre programmet ditt en siste gang, og flytte rundt på kartet til du finner en red dot. Når du kolliderer med den røde prikken, vil du se at den blå prikken går inn i sitt usårbar staten og blinker i fem sekunder.

    Konklusjon

    I denne opplæringen, jeg introduserte deg til to av de store aspekter av GameplayKit ramme, enheter og komponenter, og tilstandsmaskiner. Jeg viste deg hvordan du kan bruke enheter og komponenter for å strukturere spillet modell og holde alt organisert. Ved hjelp av komponenter er en veldig enkel måte å dele funksjonalitet mellom objekter i spillene dine.

    Jeg viste også deg det grunnleggende tilstandsmaskiner, inkludert hvordan du kan angi som sier en bestemt tilstand kan overgangen til samt gjennomføring kode når en bestemt tilstand er angitt.

    Følg med for den andre delen av denne serien hvor vi kommer til å ta dette spillet til et annet nivå ved å legge på noen kunstig intelligens, bedre kjent som AI. AI vil gjøre det mulig fiendtlige prikker å målrette spilleren og finne den beste veien til å nå spilleren.

    Som alltid, hvis du har noen kommentarer eller spørsmål, la dem i kommentarfeltet nedenfor.