Stvorite svoju prvu iPhone igru ​​ispočetka, nije potrebno iskustvo kodiranja.

Uvod

Ovaj je vodič napisan za Swift 4.0 / XCode 9, sve buduće verzije mogu imati problema dok ne ažuriram članak.

Pa vas zanima izgradnja mobilnih igara? Možda je to privlačnost poletanja i kupnje novog automobila ili je jednostavno strast stvaranja vlastite igre. Bez obzira na motiv, ovaj će vas vodič uputiti kroz korake postavljanja računala na izradu aplikacija i kreiranje jednostavne igre ispočetka! Sav je kod igre uključen u udžbenik; za dovršenje ovog projekta nije potrebno prethodno poznavanje programa.

Po završetku ovog vodiča moći ćete pokrenuti IOS aplikaciju vlastite konstrukcije na svom uređaju ili simulator uređaja. Razumjet ćete osnove dizajniranja igre od početka, kako spremiti podatke na uređaj nakon što se aplikacija zatvori, kako prikazivati ​​sprite na ekranu i počet ćete razumjeti kako koristiti pokretački mehanizam SpriteKit. Također ću vas provesti kroz to kako sam dizajnirao igru ​​Snake i kako možete započeti izgradnju igre vlastitog dizajna!

Evo poveznice za preuzimanje na nešto izmijenjenu verziju ove igre koja je dostupna u App Storeu: https://itunes.apple.com/us/app/minimal-snake/id1355406338?mt=8 (potpuno besplatno, bez reklama).

Napomena: U čitavom članku koji sam koristio izraz copy / paste, čitatelj mi je istaknuo da je to loša praksa i s tim se potpuno slažem. Ako želite brzo kopirati kôd i stvoriti funkcionalni proizvod koji je sasvim u redu, vjerojatno ćete dobiti više od pisanja svakog retka rukom!

Gotov proizvod

Evo videozapisa koji pokazuje što ćete napraviti i instalirati na svoj telefon do kraja ovog vodiča!

Početak rada

Da biste slijedili ovaj vodič, trebat ćete postaviti račun programera Applea i preuzeti Xcode (program koji se koristi za izradu IOS-ovih aplikacija). Xcode je, nažalost, dostupan samo za Mac računala; ako imate Windows / Linux stroj, ovdje je web mjesto koje vam može pomoći pri postavljanju Xcode-a.

Sljedeći koraci opisuju registraciju besplatnog računa programera i instaliranje Xcode-a. Ako već imate račun i Xcode, možete preskočiti na sljedeći odjeljak. Da biste započeli prvo posjetite developer.apple.com i kliknite centar za članove, a zatim se prijavite sa svojim Apple ID-om. Idite na stranicu Apple Developers Agreement i prihvatite ugovor; sada imate besplatni račun programera! Za prijenos svojih projekata u trgovinu aplikacija morat ćete platiti 100 $ godišnje naknade.

Sada kada imate račun programera, morate instalirati Xcode. Xcode je dostupan putem Mac App Store-a. Nakon što instalirate Xcode pokrenite program i kliknite na Xcode -> Preferences -> Accounts -> + i odaberite Add Apple ID. Prijavite se Apple ID-om koji se koristio za registraciju računa programera. Čestitamo, sada možete testirati aplikacije u iPhone simulatoru ili ih pokrenuti na svom osobnom uređaju!

Početak projekta

Sada kada ste se registrirali za račun programera i instalirali Xcode, možete početi razvijati svoju prvu mobilnu igru!

Pokrenite Xcode i kliknite na "Create a new Xcode project".

Kliknite na predložak "Igra".

Unesite naziv "Snake" (ili što god želite) za vašu igru. Izaberite naziv organizacije, ako imate web mjesto možete ga unijeti unatrag (com.gavinshrader) ili možete jednostavno koristiti svoje ime kao identifikator. Osigurajte da je jezik postavljen na "Swift", a da je tehnologija igre "SpriteKit". Poništite 3 potvrdne okvire ako su odabrani.

Kliknite desnom tipkom "Actions.sks" i pređite u smeće. Idite na GameScene.sks i kliknite na "Hello World" tekst, a zatim ga izbrišite. Idite na GameScene.swift i uklonite sav unaprijed izgrađeni kod tako da se vaša datoteka podudara sa donjom slikom.

Stvorite novu datoteku Swift ili idite na Datoteka -> Nova datoteka i klikom na Swift datoteku, ili desnim klikom na projektnu mapu ("Snake") i odabirom nove datoteke. Pronađite ikonu Swift File koja je dolje istaknuta ako nije prisutna, na traci filtra upišite "Swift". Unesite ime "GameManager" i osigurajte da je vaš projekt ("Snake") odabran pod ciljevima, kliknite "Create" (Stvori) za stvaranje nove brze datoteke.

Izrada izbornika igre

Prije nego što počnemo s kodiranjem, provjerite da li se vaš projekt sastavlja nakon promjena koje ste izvršili u posljednjem odjeljku. Odaberite uređaj s popisa simulatora, kliknite gumb gdje je "iPhone 6", koji će vjerojatno biti označen kao "Generic iOS device". Ako želite testirati na fizičkom uređaju priključite svoj iPhone, dajte nekoliko trenutaka Xcode, a zatim kliknite svoj uređaj. Nakon što učinite ovaj klik na trokutni gumb za pokretanje. Ako odaberete simulirani uređaj, zaslon bi se trebao pojaviti:

Ako se na ekranu pojavi "Hello World", osigurajte da ste izbrisali naljepnicu tako što ćete otići na GameScene.sks, kliknuti na naljepnicu, a zatim odabrati delete.

Napokon smo spremni započeti izgradnju igre! Kada započnete s igrom, ona vam pomaže da unaprijed pripremite svoje zaslone. U ovoj igri započet ćemo s jednostavnim zaslonom izbornika koji prikazuje naslov / logotip igre. Gumb za pokretanje pokrenut će zaslon za igranje s područjem igre i dvije oznake za vaš trenutni rezultat i najbolji rezultat. Kad umrete, prikazat će se zaslon s krajnjom igrom s opcijom da se igra ponovo.

Da bi se naša igra pokrenula prvo moramo sastaviti izbornik za početak igre. Započet ćemo s pisanjem koda za inicijalizaciju izbornika dodavanjem naslova igre, oznake „najbolji rezultat“ i gumba za igranje. Otvorite datoteku GameScene.swift i kopirajte dolje sav kôd tako da se vaša datoteka podudara sa slikom (slika A).

// 1
var gameLogo: SKLabelNode!
var bestScore: SKLabelNode!
var playButton: SKShapeNode!
// 2
initializeMenu ()
// 3
private func InitializeMenu () {
    // Stvaranje naslova igre
    gameLogo = SKLabelNode (fontNamed: "ArialRoundedMTBold")
    gameLogo.zPosition = 1
    gameLogo.position = CGPoint (x: 0, y: (frame.size.height / 2) - 200)
    gameLogo.fontSize = 60
    gameLogo.text = "SNAKE"
    gameLogo.fontColor = SKColor.red
    self.addChild (gameLogo)
    // Stvaranje oznake najbolje ocjene
    bestScore = SKLabelNode (fontNamed: "ArialRoundedMTBold")
    bestScore.zPosition = 1
    bestScore.position = CGPoint (x: 0, y: gameLogo.position.y - 50)
    bestScore.fontSize = 40
    bestScore.text = "Najbolja ocjena: 0"
    bestScore.fontColor = SKColor.white
    self.addChild (bestScore)
    // Stvori gumb za reprodukciju
    playButton = SKShapeNode ()
    playButton.name = "play_button"
    playButton.zPosition = 1
    playButton.position = CGPoint (x: 0, y: (frame.size.height / -2) + 200)
    playButton.fillColor = SKColor.cyan
    neka topCorner = CGPoint (x: -50, y: 50)
    neka bottomCorner = CGPoint (x: -50, y: -50)
    neka je srednja = CGPoint (x: 50, y: 0)
    neka staza = CGMutablePath ()
    path.addLine (do: topCorner)
    path.addLines (između: [topCorner, bottomCorner, sredina])
    playButton.path = staza
    self.addChild (playButton)
}
Slika A

Sastavite svoj kôd i provjerite prikazuje li vaš uređaj sliku odozgo. Evo objašnjenja što se ovdje događa, ovo može izgledati kao kod koda, ali lako je shvatiti kada ga razbijete.

  • 1: Stvaramo varijable za logotipe / gumbe. "!" Nakon naziva varijable znači da moramo inicijalizirati varijable, one ne mogu biti prazne ili "nil".
  • 2: Nazivamo funkciju "InitializeMenu ()" nakon učitavanja prikaza igre. didMove (na: view: SKView) je funkcija koja se zove nakon što se naš GameScene učita.
  • 3: Ovo je funkcija intializeMenu () koju smo napisali za stvaranje objekata iz izbornika.
  • 4/5/6: Stvorite predmete i dodajte GameScene pozivom "self.addChild ()".
  • 7: Odlučio sam se za ovaj projekt koristiti SKShapeNodes zbog svoje jednostavnosti, ovo je alternativa stvaranju vaše grafike u uređivaču slika. Ova linija koda stvara stazu u obliku trokuta. Imajte na umu da ako planirate graditi i objavljivati ​​aplikaciju trebali biste koristiti SKSpriteNodes za učitavanje slike koju ste stvorili, ShapeNodes mogu izazvati probleme s izvedbom kada se koriste u velikim količinama, jer se dinamički crtaju jednom po kadru.
  • 8: Postavite trokutastu putanju koju smo stvorili do sprite playButton i dodajte GameScene.

Igranje igre

Sada kada imamo jednostavno postavljanje izbornika, pokrenimo gumb za reprodukciju. Prvo idite na svoju GameManager.swift datoteku i zamijenite sav kôd s ovim tako da se podudara sa slikom ispod (slika B).

uvoz SpriteKit
klasa GameManager {
}
Slika B

Kopirajte donji kôd u svoju GameScene.swift datoteku tako da se podudara sa slikom ispod (slika C).

// 1
var igra: GameManager!
// 2
igra = GameManager ()
// 3
nadjačati funkcijske dodireBegan (_ dodirne: Postaviti , s događajem: UIEvent?) {
    za dodir u dodirima {
        neka lokacija = touch.location (in: self)
        neka dodirivaNode = self.nodes (na: lokaciji)
        za čvor u dodirnutom čvoru {
            ako je node.name == "play_button" {
                početak igre()
            }
        }
    }
}
// 4
private func startGame () {
    ispis ("start igra")
}
Slika C
  • 1: Inicijalizirajte GameManager objekt. Kasnije o tome kasnije ... ovo će sadržavati podatke o rezultatima i upravljati kretanjem igrača.
  • 2: Postavite varijablu igre na novi GameManager () objekt.
  • 3: Igra se aktivira ovom funkcijom svaki put kada korisnik dodirne zaslon. Podsjetimo da gumb za reprodukciju koji smo stvorili ranije ima naziv "play_button". Korištenjem imena možemo provjeriti je li korisnik dotaknuo SpriteNode s imenom "play_button", nakon što se to dogodi, nazovimo funkciju startGame () iz točke 4 sa metkom.
  • 4: Ova funkcija pokreće igru.

Pobrinite se da vaš kôd ispravno radi pokretanjem aplikacije i klikom na trokutni gumb za reprodukciju. Ako se vaši dodiri pravilno mjere, tada bi na konzoli trebao biti prikazan "start game" kako je prikazano na slici ispod (slika D).

Slika D

Ako se vaša konzola ne prikazuje, idite na gornju traku i kliknite na "Pomoć", u traci za pretraživanje upišite "Konzola", a zatim kliknite na "Područje za uklanjanje pogrešaka> Aktiviraj konzolu". Sada imamo radni sustav izbornika i gumb za reprodukciju. Ovdje se stvarno možemo zabaviti.

Učitavanje prikaza igre

Dakle, sada imamo gumb za reprodukciju koji može pokrenuti funkciju, što trebamo učiniti? Da bismo prikazali prikaz igre, prvo moramo sakriti gumbe izbornika. Dodajte ovu liniju koda da biste sakrili gumbe izbornika pomoću jednostavne animacije. Vaš kôd trebao bi odgovarati donjoj slici (slika E).

//Započni igru
private func startGame () {
    ispis ("start igra")
    // 1
    gameLogo.run (SKAction.move (autor: CGVector (dx: -50, dy: 600), trajanje: 0,5)) {
    self.gameLogo.isHidden = istina
    }
    // 2
    playButton.run (SKAction.scale (do: 0, trajanje: 0,3)) {
        self.playButton.isHidden = istina
    }
    // 3
    neka bottomCorner = CGPoint (x: 0, y: (frame.size.height / -2) + 20)
    bestScore.run (SKAction.move (do: bottomCorner, trajanje: 0,4))
}
Slika ESlika F
  • 1: Pomaknite igruLogo s ekrana i zatim je sakrijte od pogleda. Zagrade nakon SKAction izvršavaju nakon što se akcija završi. Na primjer, ako izvodimo SKAction u trajanju od 10, kod unutar zagrade pokrenut će se nakon 10 sekundi. Evo primjera:
exampleNode.run (SKAction.move (autor: CGVector (dx: 0, boja: 0), trajanje: 10) {
    ispis ("Stigao sam nakon 10 sekundi")
}
  • 2: Smanjite veličinu gumba za reprodukciju na 0; ova radnja smanjuje gumb, a zatim ga skriva od pogleda.
  • 3: Pomaknite oznaku bestScore na dnu zaslona.

Vaš bi se izbornik sada trebao ponašati kao ovaj gif (slika F) kada kliknete gumb za reprodukciju!

Sada ćemo početi dizajnirati stvarni dio zmije ove igre, a započnite dodavanjem ovih redaka koda tako da vaš kôd odgovara slici ispod (slika G).

// 1
var trenutniScore: SKLabelNode!
var playerPositions: [(Int, Int)] = []
var gameBG: SKShapeNode!
var gameArray: [(čvor: SKShapeNode, x: Int, y: Int)] = []
// 2
initializeGameView ()
// 3
private func InitializeGameView () {
    // 4
    currentScore = SKLabelNode (fontNamed: "ArialRoundedMTBold")
    currentScore.zPosition = 1
    currentScore.position = CGPoint (x: 0, y: (frame.size.height / -2) + 60)
    currentScore.fontSize = 40
    currentScore.isHidden = istina
    currentScore.text = "Ocjena: 0"
    trenutniScore.fontColor = SKColor.white
    self.addChild (currentScore)
    // 5
    neka širina = frame.size.width - 200
    neka visina = frame.size.height - 300
    neka je rect = CGRect (x:-širina / 2, y:-visina / 2, širina: širina, visina: visina)
    gameBG = SKShapeNode (rect: rect, cornerRadius: 0,02)
    gameBG.fillColor = SKColor.darkGray
    gameBG.zPosition = 2
    gameBG.isHidden = istina
    self.addChild (gameBG)
    // 6
    createGameBoard (širina: širina, visina: visina)
}
Slika GSlika G
  • 1: Nove varijable! Stvaramo naljepnicu za prikaz trenutnog rezultata, niz svih pozicija koje zmija ili igrač trenutno ima, pozadinu za naš prikaz igre i niz za praćenje položaja svake ćelije u prikazu igre.
  • 2: Nazovite funkciju InitializeGameView ().
  • 3: Inicijalizira prikaz igre.
  • 4: Na ekranu dodajte trenutnu oznaku rezultata, to je skriveno dok ne napustimo naš izbornik.
  • 5: Izradite ShapeNode za predstavljanje područja za igru ​​naše igre. Ovdje će se zmija kretati.
  • 6: Napravite igraću ploču. Ova funkcija inicijalizira tonu kvadratnih ćelija i dodaje ih na ploču za igru.

Dalje želimo stvoriti niz ćelija koje ćemo koristiti za prikazivanje zmije i točaka na ekranu. Napravite funkciju createGameBoard iz donjeg koda tako da se podudara sa slikom H.

// stvoriti tablu za igru, inicijalizirati niz ćelija
private func createGameBoard (širina: Int, visina: Int) {
    neka je širina ćelije: CGFloat = 27.5
    neka numRows = 40
    neka numCols = 20
    var x = CGFloat (širina / -2) + (širina ćelije / 2)
    var y = CGFloat (visina / 2) - (širina ćelije / 2)
    // provući se kroz redove i stupce, stvoriti ćelije
    za i u 0 ... numRows - 1 {
        za j u 0 ... numCols - 1 {
            neka cellNode = SKShapeNode (rectOf: CGSize (širina: širina ćelije, visina: širina ćelije))
            cellNode.strokeColor = SKColor.black
            cellNode.zPosition = 2
            cellNode.position = CGPoint (x: x, y: y)
            // dodaj u niz ćelija - zatim dodaj u ploču s igrama
            gameArray.append ((čvor: cellNode, x: i, y: j))
            gameBG.addChild (cellNode)
            // ponovite x
            x + = širina ćelije
        }
        // resetiraj x, ponovite y
        x = CGFloat (širina / -2) + (širina ćelije / 2)
        y - = širina ćelije
    }
}
Slika H

Vaš kôd trebao bi odgovarati kôdu odozgo, nakon pokretanja igre, čini se da se ništa nije promijenilo. Ako želite vidjeti ploču s igrama kao na gornjoj snimci simulatora, dodajte sljedeći kôd u svoju početnu funkciju igre tako da se podudara sa slikom I.

bestScore.run (SKAction.move (do: bottomCorner, trajanje: 0,4)) {
    self.gameBG.setScale (0)
self.currentScore.setScale (0)
self.gameBG.isHidden = lažno
self.currentScore.isHidden = lažno
self.gameBG.run (SKAction.scale (do: 1, trajanje: 0,4))
self.currentScore.run (SKAction.scale (do: 1, trajanje: 0,4))
}

Kratko objašnjenje metode createGameBoard prije nego što nastavimo. Ova metoda se petlja kroz 40 redaka i 20 stupaca, za svaki red / položaj stupca stvaramo novi kvadratni okvir ili "cellNode" i dodamo to sceni. Također dodamo i ovaj cellNode u niz "gameArray" kako bismo lako mogli označiti red i stupac u odgovarajućoj ćeliji.

Slika I - Prikazuje novu ploču s igrama!

Izrada primjerka igre

Sada imamo radni gumb za reprodukciju, okvir pun manjih kutija i nekoliko naljepnica. Kako to pretvoriti u igru ​​koja je zapravo zabavna za igranje? Prvo ćemo trebati objekt da pratimo mjesto "zmije" na zaslonu kako bismo se mogli kretati. Otvorite klasu GameManager.swift i stvorite sljedeće metode. Također dodajte ovu promjenu (// 1) u funkciju didMove (za prikaz: SKView) u GameScene.swift tako da se vaš kod podudara sa slikom J.

// 1 - GameScene.swift
igra = GameManager (scena: samo)
// 2 - GameManager.swift
klasa GameManager {
    
    var scene: GameScene!
    init (scena: GameScene) {
        self.scene = prizor
    }
}
Slika J

Uvođenjem ovih promjena kažemo da GameManager mora sadržavati referencu na klasu GameScene nakon što se inicijalizira. Sada GameManager klasa može komunicirati s GameScene-om pozivom scene.method_name. Na primjer, scene.startGame () pokrenuo bi funkciju pokretanja igre unutar kontrole GameManager klase.

Sada smo spremni učitati player u GameView. Najprije dodajte sljedeći isječak koda u svoju GameScene.swift datoteku u metodi startGame () unutar zagrada na bestScore.run () {} Ova metoda će pozvati funkciju initGame nakon što oznaka najboljeg rezultata dovrši SKAction.

// novi kod
self.game.initGame ()
Slika K

Sada idite na svoj GameManager.swift i dodajte sljedeće metode ispod init (scene: GameScene) metode kako bi se vaš kod podudarao sa slikom L.

// 1
func initGame () {
    // početna pozicija igrača
    scene.playerPositions.append ((10, 10))
    scene.playerPositions.append ((10, 11))
    scene.playerPositions.append ((10, 12))
    renderChange ()
}
// 2
func renderChange () {
    za (čvor, x, y) u sceni.gameArray {
        ako sadrži (a: scene.playerPositions, v: (x, y)) {
            node.fillColor = SKColor.cyan
        } else {
            node.fillColor = SKColor.clear
        }
    }
}
// 3
func sadrži (a: [(Int, Int)], v: (Int, Int)) -> Bool {
    neka (c1, c2) = v
    za (v1, v2) u {if v1 == c1 && v2 == c2 {povratak istinito}}
    vratiti lažno
}
Slika L
  • 1: funkcija initGame (). To dodaje 3 koordinate u nizu igračaPositions na GameSceneu,
  • 2: funkcija renderChange (). Nazvat ćemo ovu metodu svaki put kad pomaknemo "zmiju" ili igrača. Tako će svi prazni kvadrati biti jasni, a svi kvadrati na kojima se igrač nalazi kao cijan.
  • 3: Ovo je jednostavna funkcija koja provjerava postoji li koplja (brza struktura podataka koja može sadržavati kombinaciju tipova u obliku (Int, CGFloat, Int, String) ... itd.) U nizu tupola. Ova funkcija provjerava sadrži li matrica playerPositions unesene koordinate iz matrice ćelija GameScene-a. Ovo nije nužno najučinkovitiji način vršenja poslova jer tijekom svake nadogradnje provjeravamo svaku ćeliju. Ako želite izazvati sebe, pokušajte ažurirati kôd tako da izmijeni samo kvadrate iz polja playPositions!

Pomicanje igrača

Slika M

Sada je naš igrač prikazan na ekranu i mogućnost renderiranja bilo kojeg broja pozicija. Ako dodate više koordinata u playerPositions nizu, tada će više kvadrata biti obojeno cijan. Tijekom igre želimo neprestano pomicati "zmiju" u jednom smjeru sve dok igrač ne pređe mišem po zaslonu da promijeni smjerove. Evo rešetke koja prikazuje koordinate našeg mrežnog sustava, tako da možete lako shvatiti kako koordinate djeluju iza scene (slika M).

Kao što se vidi po grozno sitnim naljepnicama, gornji lijevi ugao je 0,0, a donji desni kut je 39,19. To znači da ako želimo pomaknuti igrača u pravcima lijevo, desno, gore i dolje, to radimo primjenom sljedeće osnovne algebre (slika N).

Slika N

Kao što vidite, smjer lijevo / desno se podudara s tipičnom koordinatnom ravninom; lijevo je negativno, a desno pozitivno. Međutim, da bismo se pomaknuli prema koordinatnoj ravnini želimo smanjiti y, a pomaknuti prema dolje želimo povećati y. To je zbog činjenice da je naša for petlja u funkciji createGameBoard započela pri vrhu i radila prema dolje.

Sada kada razumijete smjer ploče, možete implementirati metodu kojom se igrač pomiče. Ako otvorite GameScene.swift datoteku, primijetit ćete zgodnu metodu koja se zove update (_ currentTime: TimeInterval). U petlji iscrtavanja poziva se funkcija ažuriranja jednom u sekundi. To znači da ako se vaša aplikacija radi na 60 fps, funkcija se zove 60 puta u sekundi, a ako se igra u 40 fps, ona se zove samo 40 puta u sekundi. Unutar funkcije ažuriranja dodajte ovu liniju koda kako bi se vaš kôd podudarao sa slikom O.

// 1
ažuriranje igre (vrijeme: trenutnoTime)
Slika O

Nakon što dodate ovaj kôd, trebala bi se pojaviti crvena greška, kako biste je ispravili do svoje GameManager.swift datoteke i dodali ove retke koda tako da se vaša datoteka podudara sa slikom P.

// 1
var nextTime: Dvostruko?
var timeExtension: Double = 1
// 2
funkcionalno ažuriranje (vrijeme: Double) {
    if nextTime == nil {
        nextTime = vrijeme + vrijemeEkstenzija
    } else {
        ako je vrijeme> = nextTime! {
            nextTime = vrijeme + vrijemeEkstenzija
            ispis (vrijeme)
        }
    }
}
Slika P

Nakon pokretanja vaše aplikacije, konzola bi trebala ispisati novo vrijeme svake sekunde. Evo kratkog opisa onoga što ovaj kôd radi.

  • 1: inicijalizirati dvije nove varijable. nextTime je interval nextTime na ispis ćemo ispisati izjavu, timeExtension je koliko ćemo čekati između svakog ispisa (1 sekunda).
  • 2: Ova se funkcija ažuriranja zove 60 puta u sekundi, želimo ažurirati poziciju igrača samo jednom u sekundi kako igra ne bi bila smiješno brza. Da bismo to postigli provjeravamo je li postavljen nextTime. Kao što možete vidjeti iz // 1, nextTime je inicijaliziran kao izborna vrijednost. The "? "Nakon što Double kaže brzom prevoditelju da želimo da nextTime postane dvostruki i da se MOŽE postaviti na nulu. Kada se pozove funkcija ažuriranja, prvo provjeravamo je li postavljen nextTime, ako nije postavljen, postavili smo ga na trenutno vrijeme + vrijeme ekstenzije (1 sekunda). Nakon što trenutačno vrijeme pomrči „nextTime“, tada povećavamo nextTime za 1 sekundu. Ova funkcija sada uzima nepravilnu funkciju ažuriranja (oko 30-60 puta u sekundi) i stvara samo jedanput u sekundi.

Sada imamo funkciju koja se pokreće jednom u sekundi, ako želite povećati brzinu igre jednostavno snizite timeExtension na vrijednost veću od 0, ako želite usporiti igru, a zatim povećajte vrijednost timeExtension. (Napomena: "1" == 1 sekunda za vremensko proširenje).

Sada želimo pomicati player po zaslonu, dodati sljedeći kôd tako da se vaša datoteka podudara s slikom Q. Također, uklonite redak "print (vrijeme)" iz funkcije ažuriranja koju smo upravo stvorili u GameManager.swift, to će upamtiti vaš konzola i bila je samo korisna za testiranje valjanosti vašeg koda.

// 1
var playerDirection: Int = 1
// 2
updatePlayerPosition ()
// 3
private func updatePlayerPosition () {
    // 4
    var xChange = -1
    var yChange = 0
    // 5
    Switch playerDirection {
        1. slučaj:
            //lijevo
            xChange = -1
            yChange = 0
            pauza
        slučaj 2:
            // gore
            xChange = 0
            yChange = -1
            pauza
        3. slučaj:
            //pravo
            xChange = 1
            yChange = 0
            pauza
        slučaj 4:
            // dolje
            xChange = 0
            yChange = 1
            pauza
        zadano:
            pauza
    }
    // 6
    ako scene.playerPositions.count> 0 {
        var start = scene.playerPositions.count - 1
        dok start> 0 {
            scene.playerPositions [start] = scene.playerPositions [start - 1]
            početak - = 1
        }
        scene.playerPositions [0] = (scene.playerPositions [0] .0 + yPromijeni, scene.playerPositions [0] .1 + xPromijeni)
    }
    // 7
    renderChange ()
}
Slika Q

Nakon što dodate ovaj kôd, igra bi trebala izgledati kao gif sa slike Q (postavite playerDirection na 4 da biste dobili isti smjer pokreta). Dvije stvari su mi se odmah istaknule kad sam ovo napisao; prvo, zmija se kreće bolno sporo, možda bismo trebali povećati brzinu igre s 1 sekunde na 1/2 ili 1/4 sekunde. Drugo, što ćemo učiniti kad zmija udari u zid? U nekim verzijama zmija igrač se omota oko zaslona, ​​u drugim verzijama sudar sa zidom rezultira smrću. Sviđa mi se izgled warp zaslona, ​​pa mislim da ćemo tu metodu koristiti za ovu igru. Sada objašnjenje za ovaj kôd koji ste upravo napisali:

  • 1: Stvorite varijablu koja se koristi za određivanje trenutnog smjera igrača. U kodu je varijabla postavljena na 1, u gifu na slici Q sam postavio smjer 4. Izmijenite ovu varijablu da biste vidjeli sve različite smjerove.
  • 2: Uklonili smo ispis (vrijeme) i zamijenili ga pozivom updatePlayerPosition (), u ovoj iteraciji pozivamo ažuriranje svake sekunde.
  • 3: Ova metoda pomiče igrača ili "zmiju" po zaslonu.
  • 4: Postavite varijable da odredite promjenu koju trebamo izvršiti u x / y prednjem dijelu zmije.
  • 5: Ovo je izjava o prebacivanju, ona uzima ulaz playPosition-a i mijenja x / y varijable u skladu s tim da se igrač kreće gore, dolje, lijevo ili desno.
  • 6: Ovaj blok koda pomiče pozicije prema naprijed u nizu. Želimo pomaknuti prednji dio repa u odgovarajućem smjeru, a zatim pomaknuti sve repne blokove prema naprijed na sljedeći položaj.
  • 7: Prikažite promjene koje smo izvršili u polju položaja.

Zamahuje zmija oko zaslona

Sada imamo igrača koji se kreće, lijep posao! Prvo ćemo htjeti povećati brzinu igre, a ispada da je čekanje 1 sekunde samo prespor da bi bilo zabavno. Ovo je lekcija koju ćete naučiti u dizajnu igara, ima puno podešavanja i malih promjena koje ćete morati izvršiti kako biste usavršili osjećaj igre. Kad radim na projektu često većinu svog vremena provodim radeći na malim izmjenama da bi prilagodio osjećaj, morate usavršiti svoju mehaniku da biste stvorili zabavnu igru; Jednom kada imate savršenu mehaniku možete raditi na dodavanju fantastičnih dodataka poput čestica i zvukova.

Promijenite varijablu timeExtension u 0,15 i sastavite svoj projekt.

// 1 - GameManager.swift
Vreme proširivanja: Dvostruko = 0,15

Sada možemo započeti zvrtanje zmije oko zaslona, ​​dodati sljedeći kôd tako da se vaš projekt podudara sa slikom R. Napomena, ovaj se kôd dodaje funkciji updatePlayerPosition () u GameManager.swift koju smo upravo napisali.

// 1
ako scene.playerPositions.count> 0 {
    neka je x = scene.playerPositions [0] .1
    neka je y = scene.playerPositions [0] .0
    ako je> 40 {
        scene.playerPositions [0] .0 = 0
    } else ako y <0 {
        scene.playerPositions [0] .0 = 40
    } else ako je x> 20 {
       scene.playerPositions [0] .1 = 0
    } else ako je x <0 {
        scene.playerPositions [0] .1 = 20
    }
}
Slika R

Nakon sastavljanja vaše aplikacije vaš bi se ekran trebao podudarati s gifom sa slike R, koristio sam playerDirection 4 u gif-u. Zmija sada može iskriviti sa svake strane ekrana.

  • 1: Ovaj je kôd prilično jednostavan, provjerava je li položaj glave zmije prešao gornju, donju, lijevu ili desnu stranu, a zatim premješta igrača na drugu stranu zaslona.

Kontroliranje kretanja zmije pomoću pokreta gipkom

Naša igra se nastavlja, sada nam treba metoda za kontrolu smjera zmije. Da bismo to implementirali, upotrijebit ćemo kretnje prstom za pomicanje lijevo, desno, gore i dolje. Dodajte ovaj kôd u svoju GameScene.swift datoteku tako da se podudara sa slikom S.

// 1
neka swipeRight: UISwipeGestureRecognizer = UISwipeGestureRecognizer (target: self, action: #selector (swipeR))
swipeRight.direction =. ispravno
view.addGestureRecognizer (swipeRight)
neka swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer (target: self, action: #selector (swipeL))
swipeLeft.direction =. lijevo
view.addGestureRecognizer (swipeLeft)
neka swipeUp: UISwipeGestureRecognizer = UISwipeGestureRecognizer (cilj: samo, akcija: #selector (swipeU))
swipeUp.direction = .up
view.addGestureRecognizer (swipeUp)
neka swipeDown: UISwipeGestureRecognizer = UISwipeGestureRecognizer (target: self, action: #selector (swipeD))
swipeDown.direction =. dolje
view.addGestureRecognizer (swipeDown)
// 2
@objc func swipeR () {
    print ( "R")
}
@objc func swipeL () {
    print ( "L")
}
@objc func swipeU () {
    print ( "U")
}
@objc func swipeD () {
    print ( "d"),
}
Figure
  • 1: Dodajte geste za pokretanje funkciji didMove (za prikaz: SKView).
  • 2: Stvorite funkcije koje se pozivaju kada korisnik uđe kretnjom prstom. "@Objc" prije nego što funkcija stvori cilj-c funkciju, ovo je neophodno za pozivanje putem #selektora u izvornom UISwipeGestureRecognizer.

Testirajte svoj kôd sastavljanjem aplikacije, a zatim prelaskom prstom u sva četiri smjera, na vašoj konzoli treba ispisati odgovarajuće slovo za svaku kretnju prstom. Sada kada su postavljeni prepoznatitelji geste, trebamo promijeniti smjer kretanja igrača, zamijeniti izjave ispisa unutar poteza prstom ovim kôdom i dodati kôd GameManager.swift tako da se vaš projekt podudara sa slikom T.

// 1 - GameScene.swift
game.swipe (ID: 3)
game.swipe (ID: 1)
game.swipe (ID: 2)
game.swipe (ID: 4)
// 2 - GameManager.swift
func prelazite prstom (ID: Int) {
    ako! (ID == 2 && playerDirection == 4) &&! (ID == 4 && playerDirection == 2) {
        ako! (ID == 1 && playerDirection == 3) &&! (ID == 3 && playerDirection == 1) {
            playerDirection = ID
        }
    }
}
Slika TSlika T
  • 1: Jednom kada se otkrije pokretanjem poteza obavijesti se klasa gameManager.
  • 2: Ako pomicanje prstom nije u sukobu s trenutnim smjerom, postavite smjer igrača na prijelazni prst. Ako se krećete prema dolje, ne možete se odmah pomaknuti prema gore. Ako se krećete lijevo, ne možete iznenada krenuti desno. U nekim verzijama unosa zmija neprimjeren potez poput ovog rezultirao bi smrću, ali u ovoj verziji jednostavno ćemo ignorirati vanjske unose.

Dodavanje bodova igri i prilagođavanje rezultata

Sada imamo radni sustav izbornika koji otvara ploču s igrama, niz ćelija, niz pozicija igrača, igrač koji se može kretati po zaslonu i vrtati se po ivicama te prevlačenje prstom za kontrole. Sada moramo dodati mehanizam bodovanja kako bi igra bila zabavna. Ovaj mehanizam stvorit će slučajne bodove što će povećati rezultat i produljiti trag "zmije" ili igrača.

Prvi korak: Stvaranje slučajne točke i prikaz na zaslonu. U svoju GameScene.swift datoteku dodajte sljedeći kod tako da se podudara sa slikom U.

// 1
var scorePos: CGPoint?
Slika U

Sada idite na datoteku GameManager.swift i dodajte sljedeći kôd tako da se podudara sa slikom V.

// 2
generateNewPoint ()
// 3
private func generatorNewPoint () {
    neka randomX = CGFloat (arc4random_uniform (19))
    neka slučajno Y = CGFloat (arc4random_uniform (39))
    scene.scorePos = CGPoint (x: randomX, y: randomY)
}
// 4
ako scene.scorePos! = nil {
    ako je Int ((scene.scorePos? .x)!) == y && Int ((scene.scorePos? .y)!) == x {
        node.fillColor = SKColor.red
    }
}
Slika V

Nakon pokretanja koda, vaš simulator trebao bi prikazivati ​​nasumično postavljeni crveni kvadrat.

  • 1: Inicijalizirajte varijablu za položaj slučajnih rezultata. The "? "Označava da je to nula (prazna ili još nije postavljena) dok varijablu ne postavimo kasnije.
  • 2: Nazovite funkciju unutar funkcije initGame () koja će stvoriti novu slučajnu točku.
  • 3: Ova funkcija generira slučajni položaj unutar granica ploče (20/40), nizovi počinju računati od 0, pa računamo od 0 do 19 i od 0 do 39, ovo je niz 20x40.
  • 4: Unutar petlje za renderiranje provjeravamo da li se položaj trenutnog čvora podudara sa slučajno postavljenim rezultatom, ako imamo podudaranje, a boju smo tada postavili crvenom. Možete modificirati boju po želji. Varijabla koja sprema položaj rezultata je CGPoint, to znači da moramo provjeriti point.x i point.y i usporediti ih s lokacijama x i y trenutnog čvora. Napominjemo da su pozicije x / y okrenute u nizu čvorova, zato uspoređujemo x == y i y == x.

Sada moramo dodijeliti varijablu koja drži rezultat trenutne igre i ponoviti je kada igrač postigne poen. Kad igrač pogodi bod, moramo generirati novu slučajnu točku i povećati duljinu igračevog "repa".

U datoteku GameManager.swift dodajte sljedeći kod tako da se podudara sa slikom W.

// 1
var trenutniScore: Int = 0
// 2
checkForScore ()
// 3
private func checkForScore () {
    ako scene.scorePos! = nil {
        neka je x = scene.playerPositions [0] .0
        neka je y = scene.playerPositions [0] .1
        ako je Int ((scene.scorePos? .x)!) == y && Int ((scene.scorePos? .y)!) == x {
            trenutni rezultat + = 1
            scene.currentScore.text = "Ocjena: \ (trenutni rezultat)"
            generateNewPoint ()
         }
     }
}
// 4
dok sadrži (a: scene.playerPositions, v: (Int (randomX), Int (randomY))) {
    randomX = CGFloat (arc4random_uniform (19))
    randomY = CGFloat (arc4random_uniform (39))
}
Slika W
  • 1: Inicijalizirajte varijablu kako biste pratili trenutni rezultat u ovoj igri.
  • 2: Nazovite funkciju checkForScore () unutar funkcije ažuriranja, to se zove svaki put kada se igrač pomakne.
  • 3: Ova funkcija provjerava je li postavljen rezultatPos, ako ima, tada provjerava glavu zmije. Ako zmija dodirne točku, tada se rezultat ponavlja, tekstualna naljepnica koja prikazuje rezultat se ažurira i stvara se nova točka.
  • 4: Dodao sam ovaj kôd metodi GeneNewPoint () kako bih osigurao da se ne stvara točka u tijelu zmije. Kako zmija raste u dužinu, vjerojatnije je da ćemo naići na ovaj problem, pa bi taj blok kod trebao riješiti problem.

Nakon pokretanja koda primijetit ćete da će postizanje rezultata generirati novi rezultat na ploči i ponoviti naljepnicu vašeg rezultata. Sada moramo povećati duljinu zmije tako da se mehanika igre bliži kraju. Ispada da je nevjerojatno jednostavan, jednostavno dodajte ovaj isječak koda svojoj funkciji checkForScore () kako bi vaš kôd odgovarao slici X.

scene.playerPositions.append (scene.playerPositions.last!)
scene.playerPositions.append (scene.playerPositions.last!)
scene.playerPositions.append (scene.playerPositions.last!)
Slika X

Završetak igre

Sada moramo implementirati metodu koja završava igru ​​i vraća se u sustav izbornika. U igri zmija igra se završava nakon što igrač naleti na vlastiti rep. Taj efekt možemo postići primjenom sljedećih redaka koda u datoteku GameManager.swift. Osigurajte da se vaš kôd podudara sa slikom Y.

// 1
checkForDeath ()
// 2
private func checkForDeath () {
    ako scene.playerPositions.count> 0 {
        var arrayOfPositions = scene.playerPositions
        neka headOfSnake = arrayOfPositions [0]
        arrayOfPositions.remove (na: 0)
        ako sadrži (a: arrayOfPositions, v: headOfSnake) {
            playerDirection = 0
        }
    }
}
// 3
ako igračDirection! = 0 {
    playerDirection = ID
}
// 4
slučaj 0:
    //mrtav
    xChange = 0
    yChange = 0
    pauza
Slika YSlika Y
  • 1: Nazovite funkciju checkForDeath ().
  • 2: Provjerite je li se igračeva glava sudarila s bilo kojom pozicijom repa. Ako je igrač umro, postavite playerDirection na 0.
Slika Z
  • 3: Ako je igrač umro (playerDirection = 0), nemojte dopustiti nove geste za pokretanje kao ulaze.
  • 4: Dodajte novi slučaj u izjavu o prebacivanju u updatePlayerPosition (), ako je playerDirection postavljen na 0, tada ne mijenjajte položaj glave. To će omogućiti da se položaji repa polako uklone iz pogleda.

Nakon provedbe ovih promjena koda, vaša aplikacija trebala bi funkcionirati kao u snimanju na zaslonu (slika Z).

Kad se zmija sudara sa sobom, igra je završila, sada moramo uspostaviti metodu za ponovno pokretanje igre i spremanje rezultata kao rezultata.

Ponovno pokretanje igre i spremanje visokih rezultata

Sada smo izgradili radnu igru ​​zmija (većim dijelom). Posljednji koraci su vidljivi! Potrebna nam je metoda za ponovno pokretanje igre i povratak na izbornik, također moramo spremiti podatke visokog rezultata na uređaj ako je rezultat ovog kruga bio bolji od najboljeg vašeg najboljeg rezultata.

Prvo provedimo metodu koja se vraća na jelovnik nakon što zmija završi animaciju zatvaranja. U datoteku GameManager.swift dodajte sljedeći kôd tako da se vaš kôd podudara sa slikom AA.

// 1
finishAnimation ()
// 2
private func FinAnimation () {
    if playerDirection == 0 && scene.playerPositions.count> 0 {
        var hasFinished = istina
        neka headOfSnake = scene.playerPositions [0]
        za položaj u sceni.playerPositions {
            ako je headOfSnake! = položaj {
                hasFinished = lažno
            }
         }
     if hasFinished {
        ispis ("krajnja igra")
        playerDirection = 4
        // animacija je dovršena
        scene.scorePos = nula
        scene.playerPositions.removeAll ()
        renderChange ()
        // povratak na izbornik
        scene.currentScore.run (SKAction.scale (do: 0, trajanje: 0,4) {
        self.scene.currentScore.isHidden = istina
}
        scene.gameBG.run (SKAction.scale (do: 0, trajanje: 0,4)) {
            self.scene.gameBG.isHidden = istina
            self.scene.gameLogo.isHidden = lažno
            self.scene.gameLogo.run (SKAction.move (do: CGPoint (x: 0, y: (self.scene.frame.size.height / 2) - 200), duration: 0.5)) {
                 self.scene.playButton.isHidden = lažno
                 self.scene.playButton.run (SKAction.scale (do: 1, trajanje: 0,3))
                 self.scene.bestScore.run (SKAction.move (do: CGPoint (x: 0, y: self.scene.gameLogo.position.y - 50), trajanje: 0,3))
               }
          }
          }
     }
}
Slika AA

Evo objašnjenja za ovu metodu:

  • 1: Nazovite funkciju finishAnimation ().
  • 2: Ova će funkcija provjeriti završetak posljednje animacije zmije kada se zatvori u sebe. Jednom kada se sve pozicije u playerPositions nizu međusobno podudaraju, zmija se smanjila na jedan kvadrat. Nakon što se to dogodi postavili smo playerDirection na 4 (prethodno je bilo postavljeno na 0 što ukazuje na smrt), a zatim prikazujemo objekte izbornika. Također sakrivamo trenutnuScore oznaku i gameBG objekt (mrežu kvadrata).

Dodajmo metodu koja na uređaju sprema visoku ocjenu, tako da kad se aplikacija zatvori, ne izgubimo podatke o visokoj ocjeni. U novoj metodi (finishAnimation ()) upravo ste napisali dodajte ovu liniju koda tako da se vaša datoteka podudara sa slikom BB.

updateScore ()
Slika BB

Sada otvorite svoju aplikacijsku datoteku AppDelegate.swift i dodajte sljedeće retke koda kako bi se vaš projekt podudarao sa slikom CC. Ovaj isječak koda koristi UserDefaults za spremanje podataka u memoriju vašeg uređaja. Ako planirate graditi projekt s ogromnim količinama pohranjenih podataka, to može prouzrokovati problem, no, on funkcionira u redu za jednostavne stvari poput preklopnika postavki i varijabli.

neka zadane postavke = UserDefaults.standard
neka defaultValue = ["bestScore": 0]
defaults.register (zadane vrijednosti: defaultValue)
Slika CC

Vratite se na svoju GameManager.swift datoteku i stvorite sljedeću metodu tako da vam kôd odgovara slici DD. Ovaj blok koda jednostavno provjerava je li rezultat pobijedio najbolji rezultat i ažurira ga u skladu s tim.

// 1
privatni func updateScore () {
     ako je trenutniScore> UserDefaults.standard.integer (forKey: "bestScore") {
          UserDefaults.standard.set (trenutniScore, forKey: "bestScore")
     }
     currentScore = 0
     scene.currentScore.text = "Ocjena: 0"
     scene.bestScore.text = "Najbolji rezultat: \ (UserDefaults.standard.integer (forKey:" bestScore "))"
}
Slika DD

Otvorite GameScene.swift i uredite funkciju InitializeMenu () tako da se vaša datoteka podudara s slikom EE. To osigurava da se pri učitavanju igre prikazuje spremljeni najbolji rezultat, a ne 0.

bestScore.text = "Najbolji rezultat: \ (UserDefaults.standard.integer (forKey:" bestScore "))"
Slika EE

Nakon dodavanja novog koda, visoka ocjena bit će spremljena u memoriji vašeg uređaja nakon što se aplikacija zatvori.

Zatvaranje misli

Da biste uklonili podatke za razvojne programere na dnu zaslona otvorite svoju GameViewController.swift datoteku i postavite view.showFPS i view.showsNodeCount na false.

Sada ste izgradili cijelu iPhone igru ​​od nule! Evo videozapisa koji demonstrira konačni proizvod.

Ako vam se svidio projekt razmislite o provjeri moje aplikacije za IOS! Ako imate bilo kakvih pitanja ili pitanja, slobodno mi pišite na shrader.gavin@gmail.com.

Ono što smo danas izgradili jedva je izgrebalo površinu složenosti koju SpriteKit motor može ponuditi. U budućnosti planiram raditi vježbe s fizikom, dizajnom nivoa i animacijama.