An Introduksjon til GameplayKit: Del 3
18
Del
5
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
Dette er den tredje delen av An Introduction to GameplayKit. Hvis du ennå ikke har gått gjennom den første delen og den andre delen, så anbefaler jeg å lese disse tutorials først før du fortsetter med denne.
Innledning
I denne tredje og siste tutorial, jeg kommer til å lære deg om to flere funksjoner du kan bruke i dine egne spill:
tilfeldig verdi generatorer
regelsystemer
I denne opplæringen, vil vi først bruke en av GameplayKit er tilfeldig verdi generatorer for å optimalisere vår første fiende gyting algoritme. Vi vil deretter gjennomføre en grunnleggende regel system i kombinasjon med en annen tilfeldig fordeling til å håndtere restartet oppførsel av fiender.
For denne opplæringen, kan du bruke ditt eksemplar av det ferdige prosjektet fra andre tutorial eller laste ned en ny kopi av kildekoden fra GitHub.
1. Random Verdi Generatorer
Tilfeldige verdier kan genereres i GameplayKit ved hjelp av noen klasse som samsvarer med GKRandom protokollen. GameplayKit gir fem klasser som samsvarer med denne protokollen. Disse klassene inneholder tre tilfeldige kilder og to tilfeldige utdelinger. Den største forskjellen mellom tilfeldige kilder og tilfeldige utdelinger er at distribusjoner bruker en tilfeldig kilde til å produsere verdier innenfor et bestemt område, og kan manipulere tilfeldig verdi utgang på ulike andre måter.
De nevnte klasser er levert av rammen så at du kan finne den rette balansen mellom ytelse og tilfeldig for spillet ditt. Noen tilfeldig verdi generer algoritmer er mer komplekse enn andre og dermed påvirker resultatene.
For eksempel, hvis du trenger et tilfeldig tall genereres hver ramme (seksti ganger per sekund), så det ville være best å bruke en av de raskere algoritmer. I kontrast, hvis du bare sjelden genererer en tilfeldig verdi, kan du bruke en mer kompleks algoritme for å gi bedre resultater.
De tre tilfeldige kilde klasser tilbys av GameplayKit rammeverket er GKARC4RandomSource, GKLinearCongruentialRandomSource, og GKMersenneTwisterRandomSource .
GKARC4RandomSource
Denne klassen bruker ARC4 algoritme og er egnet for de fleste formål. Denne algoritmen virker ved å frembringe en rekke tilfeldige tall basert på et frø. Du kan initialisere en GKARC4RandomSource med en bestemt frø hvis du trenger å replikere tilfeldig oppførsel fra en annen del av spillet. En eksisterende kilde sæd kan hentes fra sine frø beskyttet eiendom.
GKLinearCongruentialRandomSource
Dette tilfeldig kilde klassen bruker den grunnleggende lineær kongruentrekursjonssekvens generator algoritme. Denne algoritmen er mer effektiv og gir bedre resultater enn den ARC4 algoritmen, men det frembringer også verdier som er mindre tilfeldig. Du kan hente en GKLinearCongruentialRandomSource objektets frø og lage en ny kilde med det på samme måte som en GKARC4RandomSource objekt.
GKMersenneTwisterRandomSource
Denne klassen bruker Mersenne Twister algoritme og genererer mest tilfeldige resultater, men det er også den minst effektive. Akkurat som de andre to tilfeldige kilde klasser, kan du hente en GKMersenneTwisterRandomSource objektets frø og bruke den til å lage en ny kilde.
De to tilfeldige distribusjons klasser i GameplayKit er GKGaussianDistribution og GKShuffledDistribution.
< h3> GKGaussianDistribution
sikrer Denne fordelingen type som de genererte tilfeldige verdier følge en gaussfordeling-også kjent som en normalfordeling. Dette betyr at flertallet av de genererte verdiene vil falle i midten av intervallet du angir.
For eksempel, hvis du setter opp en GKGaussianDistribution objekt med en minimumsverdi på 1, en maksimal verdi på 10, og standardavvik på 1, vil om lag 69% av resultatene være enten 4, 5 eller 6. Jeg vil forklare denne fordelingen i mer detalj når vi legger en til vårt spill senere i denne opplæringen.
GKShuffledDistribution
Denne klassen kan brukes til å sørge for at tilfeldige verdier er jevnt fordelt over det angitte området. For eksempel, hvis du generere verdier mellom 1 og 10, og en 4 genereres, en annen 4 vil ikke bli generert før alle de andre tall mellom 1 og 10 har også blitt generert.
Det er nå på tide å sette alt dette i praksis. Vi kommer til å legge to tilfeldige utdelinger til spillet vårt. Åpne prosjektet i Xcode og gå til GameScene.swift. Den første tilfeldig fordeling vil vi legge til en GKGaussianDistribution. Senere vil vi også legge til en GKShuffledDistribution. . Legge til følgende to eiendommer til GameScene klassen
Var initialSpawnDistribution = GKGaussianDistribution (randomSource: GKARC4RandomSource (), lowestValue: 0, highestValue: 2) Var respawnDistribution = GKShuffledDistribution (randomSource: GKARC4RandomSource (), lowestValue: 0, highestValue: 2 )
I denne tekstutdrag, skaper vi to fordelinger med en minimumsverdi på 0 og en maksimal verdi av 2. For GKGaussianDistribution, midlere og avvik blir automatisk beregnet etter følgende ligninger:
mener = (maksimum - minimum) /2
avvik = (maksimum - minimum) /6
Gjennomsnittet av en Gaussisk fordeling er midtpunktet og avviket brukes til å beregne hvor mange prosent av verdiene bør være innenfor et visst område fra middelverdien. Prosentandelen av verdier innenfor en viss rekkevidde er:
68,27% innen ett avvik fra gjennomsnittet
95% innen 2 avvik fra gjennomsnittet
100% innen 3 avvik fra gjennomsnittet
Dette betyr at ca 69% av de genererte verdiene skal være lik 1. Dette vil resultere i flere røde prikker i forhold til grønne og gule prikker. For å gjøre dette arbeidet, må vi oppdatere initialSpawn metoden
I for loop, erstatte følgende linje:.
La respawnFactor = arc4random ()% 3 //Vil produsere en verdi mellom 0 og 2 (inkluderende)
med følgende:
la respawnFactor = self.initialSpawnDistribution.nextInt ()
nextInt metoden kan kalles på et objekt som er i samsvar med GKRandom protokollen og vil returnere en tilfeldig verdi basert på kilde og eventuelt fordeling som du bruker.
Bygg og kjøre programmet ditt, og flytte rundt på kartet. Du skal se mye mer røde prikker i forhold til både grønne og gule prikker.
Den andre tilfeldig fordeling som vi skal bruke i spillet vil komme inn i bildet når du håndterer regelen systembasert respawn atferd.
2. Regel Systems
GameplayKit regel systemer brukes til å bedre organisere betinget logikk i spillet, og også innføre fuzzy logikk. Ved å innføre fuzzy logikk, kan du lage enheter i spillet ditt ta avgjørelser basert på et utvalg av ulike regler og variabler som spiller helse, nåværende fiende teller, og avstanden til fienden. Dette kan være svært fordelaktig i forhold til enkel hvis og slå uttalelser
Regel systemer, representert ved GKRuleSystem klasse, har tre sentrale deler til dem:.
Regler seg selv, representert ved GKRule klasse, har to hovedkomponenter:.
La oss se hvordan alt dette fungerer i praksis. For vår regel system, skal vi lage tre regler som ser på:
avstanden fra spawn punkt til spilleren. Hvis denne verdien er relativt liten, vil vi gjøre spillet mer sannsynlig å gyte røde fiender.
Først legger følgende eiendom til GameScene klassen.
Var ruleSystem = GKRuleSystem ()
Neste legger du til følgende kode til didMoveToView (_ :) metode:
la playerDistanceRule = GKRule (blockPredicate: {(system: GKRuleSystem) - > Bool inn hvis la value = system.state ["spawnPoint"] som? NSValue {la punkt = value.CGPointValue () la xDistance = abs (point.x - self.playerNode.position.x) la yDistance = abs (point.y - self.playerNode.position.y) la totaldistanse = sqrt (( xDistance * xDistance) + (yDistance * yDistance)) hvis totaldistanse < = 200 {return true} else {return false}} else {return false}}) {(system: GKRuleSystem) - > Void i system.assertFact ("spawnEnemy")} la nodeCountRule = GKRule (blockPredicate: {(system: GKRuleSystem) - > Bool inn hvis self.children.count < = 50 {return true} else {return false}}) {(system: GKRuleSystem) - > Void i system.assertFact ("shouldSpawn", Karakter: 0,5)} la nodePresentRule = GKRule (blockPredicate: {(system: GKRuleSystem) - > Bool inn hvis la value = system.state ["spawnPoint"] som NSValue der selv? . .nodesAtPoint (value.CGPointValue ()) teller == 0 {return true} else {return false}}) {(system: GKRuleSystem) - > Ugyldig i utleid klasse = system.gradeForFact ("shouldSpawn") system.assertFact ("shouldSpawn", klasse: (klasse + 0,5))} self.ruleSystem.addRulesFromArray ([playerDistanceRule, nodeCountRule, nodePresentRule])
Med denne koden skaper vi tre GKRule gjenstander og legge dem til regelen system. Reglene hevde en bestemt faktum innenfor sine handlinger blokk. Hvis du ikke oppgir en karakter verdi og bare ringe assertFact (_ :) metode, som vi gjør med playerDistanceRule, er det faktum gitt et standardkarakter på 1,0.
Du vil merke at for nodeCountRule vi bare hevde at "shouldSpawn" faktisk med karakteren 0,5. Den nodePresentRule hevder så er dette samme faktum og legger på en karakter verdi på 0,5. Dette er gjort slik at når vi sjekker det faktum senere, betyr en karakter verdi på 1,0 som begge regler er oppfylt.
Du vil også se at både playerDistanceRule og nodePresentRule tilgang til "spawnPoint" verdien av Regelen systemets tilstand ordbok. Vi vil tildele denne verdien før du evaluerer regel system
Til slutt, finne og erstatte respawn metoden i GameScene klassen med følgende gjennomføringen.
Func respawn () {la endNode = GKGraphNode2D (punkt: float2 (x: 2048,0, y: 2048,0)) self.graph.connectNodeUsingObstacles (endNode) for punkt i self.spawnPoints {self.ruleSystem.reset () self.ruleSystem.state ["spawnPoint"] = NSValue (CGPoint: punkt) selv .ruleSystem.evaluate () hvis self.ruleSystem.gradeForFact ("shouldSpawn") == 1,0 {var respawnFactor = self.respawnDistribution.nextInt () hvis self.ruleSystem.gradeForFact ("spawnEnemy") == 1,0 {respawnFactor = selvtillit. initialSpawnDistribution.nextInt ()} Var node: SKShapeNode? = Nil slå respawnFactor {case 0: node = PointsNode (circleOfRadius: 25)! Node .physicsBody = SKPhysicsBody (circleOfRadius: 25) node .fillColor = UIColor.greenColor () case 1: node = RedEnemyNode (circleOfRadius: 75) node! .physicsBody = SKPhysicsBody (circleOfRadius: 75)! node .fillColor = UIColor.redColor () case 2: node = YellowEnemyNode (circleOfRadius: 50)! node .physicsBody = SKPhysicsBody (circleOfRadius: 50) node .fillColor = UIColor.yellowColor (! ) standard: break} hvis la enhet = node .valueForKey ("enhet") som? GKEntity, la agenten = node? .valueForKey ("Agent") som? GKAgent2D hvor respawnFactor! = 0 {entity.addComponent (agent) agent.delegate = node som? ContactNode agent.position = float2 (x: Float (point.x), y: Float (point.y)) agents.append (nestleder) la startNode = GKGraphNode2D (punkt: agent.position) self.graph.connectNodeUsingObstacles (startNode) la pathNodes = self.graph.findPathFromNode (startNode, toNode: endNode) som! [GKGraphNode2D] hvis pathNodes.isEmpty {la path = GKPath (graphNodes: pathNodes, radius: 1,0)! La followPath = GKGoal (toFollowPath: bane, maxPredictionTime: 1,0, fremover: true) la stayOnPath = GKGoal (toStayOnPath: bane, maxPredictionTime: 1.0) la atferd = GKBehavior (mål: [followPath, stayOnPath]) agent.behavior = atferd} self.graph.removeNodes ([startNode]) agent.mass = 0.01 agent.maxSpeed = 50 agent.maxAcceleration = tusen} node !. stilling = punktet node! .strokeColor = UIColor.clearColor () node! .physicsBody! .contactTestBitMask = 1 self.addChild (! node)}} self.graph.removeNodes ([endNode])}
Denne metoden vil bli kalt en gang hvert sekund, og er meget lik den initialSpawn metoden. Det finnes en rekke viktige forskjeller i for loop skjønt.
Resten av respawn metoden er den samme som initialSpawn metoden. Bygge og drive din spillet en siste gang. Selv uten å flytte rundt, vil du se nye prikker gyte når de nødvendige betingelsene er oppfylt.
Konklusjon
I denne serien på GameplayKit, har du lært mye. La oss kort oppsummere hva vi har dekket.
State Machines
Agents, mål, og Behaviors
pathfinding
Tilfeldige Verdi Generatorer
Rule Systems
GameplayKit er et viktig tillegg til iOS 9 og OS X El Capitan. Det eliminerer mye av kompleksiteten i spillutvikling. Jeg håper at denne serien har motivert deg til å eksperimentere mer med rammen og oppdage hva det er i stand til.
Som alltid må du huske å legge inn kommentarer og tilbakemeldinger under.