Seit ihrer Einführung in Xcode 6 neben Swift und ihrer aktuellen Iteration in Xcode 7.3.1 haben Spielplätze einen langen Weg zurückgelegt. Mit neuen Funktionen und besserer Stabilität entwickeln sie sich zu einem praktikablen Werkzeug für das schnelle Prototyping oder für ein schnelles Zusammenbringen eines Proof-of-Concept.
Als Entwickler haben Sie manchmal Inspiration in Form einer interessanten Idee für eine App, und Sie möchten schnell einen Prototyp erstellen, der das Wesentliche Ihrer Idee darstellt. Oder Sie möchten nur Ihr Verständnis des Verhaltens eines UIKit-Codes verifizieren. Wenn Sie wie ich sind, möchten Sie lieber den Ärger und den mentalen Aufwand vermeiden, wenn Sie ein Xcode-Projekt erstellen und sich mit einer Vielzahl von Faktoren auseinandersetzen müssen, z. B. Gerätetypen, Auflösungen und Buildeinstellungen. Diese Entscheidungen können verschoben werden, bis Sie sich entschieden haben, dass die Kernidee eine Verfolgung wert ist.
In diesem Lernprogramm erstellen wir ein kartenbasiertes Gedächtnisspiel, das sich alle innerhalb eines Spielplatzes befindet. Es ist ein allgemein bekanntes Spiel, daher gibt es keine Anerkennung für Originalität. Das Spiel besteht aus acht Paaren identischer Karten (also insgesamt 16 Karten), die verdeckt in einem 4x4-Raster platziert werden.
Der Spieler muss zwei Karten umdrehen, deren Gesichter kurz aufgedeckt und dann schnell wieder umgedreht werden. Ziel des Spiels ist es, dass der Spieler versucht, sich die Positionen der Karten zu merken und identische Paare zu finden, die dann aus dem Spiel entfernt werden. Das Spiel ist vorbei, wenn das Raster gelöscht wird.
Das Spiel ist touchbasiert und enthält einfache Ansichtsanimationen. Sie erfahren, wie Sie Änderungen an Ihrer App vornehmen können, und sehen das Ergebnis Ihrer Änderungen live.
Starten Sie Xcode und wählen Sie Neu> Spielplatz… von Xcode's Datei Speisekarte. Geben Sie dem Spielplatz einen Namen, z MemoryGameXCPTut, einstellen Plattform zu iOS, und rette den Spielplatz. Ich verwende Xcode 7.3.1 für dieses Tutorial.
Lassen Sie uns einige Zeit mit dem Spielplatz-Interface vertraut machen. Fühlen Sie sich frei, diesen Abschnitt zu überfliegen, wenn Sie mit Spielplätzen bereits vertraut sind.
Ein Spielplatz kann mehrere Seiten haben, von denen jede mit einer eigenen Live-Ansicht und eigenen Quellen- / Ressourcenordnern verknüpft ist. In diesem Tutorial werden wir nicht mehrere Seiten verwenden. Spielplätze unterstützen Markup-Formatierungen, mit denen Sie einem Spielplatz Rich-Text hinzufügen und eine Verknüpfung zwischen den Spielplatzseiten herstellen können.
Das erste, was Sie nach dem Erstellen eines Spielplatzes sehen, ist der Editor für Spielplatzquellen. Hier schreiben Sie Code, der sich unmittelbar auf die Live-Ansicht auswirkt. Eine der Möglichkeiten, um die (Un) Erscheinung des zu ändern Projektnavigator verwendet die Verknüpfung Befehl-0. In dem Projektnavigator, Sie können zwei Ordner sehen, Quellen und Ressourcen.
In dem Quellen In diesem Ordner können Sie zusätzlichen Code in einer oder mehreren Swift-Dateien hinzufügen, z. B. benutzerdefinierte Klassen, Ansichtscontroller und Ansichten. Auch wenn der Großteil des Codes, der die Logik Ihres Prototyps definiert, dorthin geht, ist dies in dem Sinne hilfreich, dass er sich im Hintergrund befindet, wenn Sie Ihre App live betrachten.
Der Vorteil, den Hilfscode in die Quellen Ordner ist, dass er automatisch jedes Mal kompiliert wird, wenn Sie die Datei ändern und speichern. Auf diese Weise erhalten Sie in der Live-Ansicht ein schnelleres Feedback von Änderungen auf dem Spielplatz. Zurück auf dem Spielplatz können Sie zugreifen Öffentlichkeit Eigenschaften und Methoden, die Sie im Zusatzcode verfügbar machen, der das Verhalten Ihrer App beeinflusst.
Sie können externe Ressourcen hinzufügen, z. B. Bilder Ressourcen Mappe.
In diesem Lernprogramm müssen Sie häufig zwischen einer von uns erstellten Swift-Datei wechseln Quellen Ordner und die Spielplatzdatei (technisch auch eine Swift-Datei, es sei denn, Sie beziehen sich nicht auf den Dateinamen). Wir nutzen auch die Schnittassistenz Im Tutorial wird angezeigt, dass Zeitleiste, um die Live-Ausgabe neben dem Spielplatzcode anzuzeigen. Alle Änderungen, die Sie auf dem Spielplatz vornehmen, werden sofort (also innerhalb weniger Sekunden) in der Live-Ausgabe wiedergegeben. Sie können auch mit der Live-Ansicht und ihren Benutzeroberflächenelementen in Kontakt treten. Um sicherzustellen, dass Sie all dies tun können, werfen Sie einen Blick auf die folgende Abbildung.
Entsprechend den grünen Zahlen, die ich der Figur hinzugefügt habe:
Beim Betrachten des Spielplatzes müssen Sie manchmal sicherstellen, dass die Schnittassistenz zeigt die Zeitleiste anstelle einer anderen Datei. Die folgende Abbildung zeigt, wie das geht. In dem Schnittassistenz, wählen Zeitleiste, das Gegenstück des Spielplatzes statt Handbuch, Damit können Sie eine beliebige Datei im anzeigen Schnittassistenz.
Wenn Sie eine Quelldatei vom bearbeiten Quellen Ordner als Gegenstück, der Schnittassistenz zeigt die Schnittstelle Ihres Codes, dh Deklarationen und Funktionsprototypen ohne ihre Implementierungen. Ich ziehe es vor, das zu verstecken Schnittassistenz wenn ich an einer Datei im arbeite Quellen Ordner und legen Sie nur die Schnittassistenz auf dem Spielplatz, um die Live-Ansicht zu sehen.
Um auf die speziellen Fähigkeiten von Spielplätzen zugreifen zu können, müssen Sie das XCPlayground-Modul importieren.
XCPlayground importieren
Du hast das eingestellt Liveübertragung
Eigentum der aktuelle Seite
des XCPlaygroundPage
Objekt zu einem Objekt, das dem entspricht XCPlaygroundLiveViewable
Protokoll. Dies kann eine benutzerdefinierte Klasse sein oder eine UIView
oder UIViewController
Beispiel.
Ich habe ein paar Bilder hinzugefügt, mit denen wir in diesem Tutorial arbeiten können. Laden Sie die Bilder herunter, extrahieren Sie das Archiv und fügen Sie die Bilder in das Archiv ein Bilder Ordner zum Ressourcen Ordner des Spielplatzes in der Projektnavigator.
Stellen Sie sicher, dass Sie nur die Bilder ziehen, sodass sich jede Bilddatei in der Datei befindet Ressourcen Ordner, nicht in Ressourcen / Bilder.
Löschen Sie den Code auf dem Spielplatz. Klicken Sie mit der rechten Maustaste auf Quellen Ordner und wählen Sie Neue Datei aus dem menü. Legen Sie den Namen der Datei auf fest Game.swift.
Fügen Sie den folgenden Code hinzu Game.swift. Stellen Sie sicher, dass Sie die Datei nach jeder Code-Hinzufügung speichern.
import UIKit import XCPlayground importieren GameplayKit // (1) öffentliche Erweiterung UIImage // (2) public comfort init? (Farbe: UIColor, Größe: CGSize = CGSize (Breite: 1, Höhe: 1)) let rect = CGRect ( Ursprung: .Zero, Größe: Größe) UIGraphicsBeginImageContextWithOptions (rect.size, false, 0.0) color.setFill () UIRectFill (rect) let image = UIGraphicsGetImageContext () UIGraphicsEndImageContext (image) .init (CGImage: cgImage) lassen Sie cardWidth = CGFloat (120) // (3) let cardHeight = CGFloat (141) public class Karte: UIImageView // (4) public let x: Int public let y: Int public init (image: UIImage ?, x: Int, y: Int) self.x = x self.y = y super.init (image: image) self.backgroundColor = .grayColor () self.layer.cornerRadius = 10.0 self .userInteractionEnabled = true erforderlicher öffentlicher init? (Coder aDecoder: NSCoder) fatalError ("init (Coder :) wurde nicht implementiert")
Ich habe einige nummerierte Kommentare hinzugefügt, um einige Abschnitte der Implementierung zu erläutern:
UIKit
und XCPlayground
, wir importieren auch GamePlayKit
. Dieses Framework enthält eine praktische Methode, mit der wir eine Methode zum zufälligen Mischen eines Arrays implementieren können.UIImage
erlaubt uns mit Hilfe von UIKit
Methoden, um Bilder mit einer festen Farbe in beliebiger Größe zu erstellen. Wir werden dies verwenden, um das anfängliche Hintergrundbild der Spielkarten festzulegen.cardHöhe
und cardWidth
Konstanten stellen die Kartenbildgrößen dar, auf deren Grundlage wir andere Größen berechnen.Karte
Klasse, erbend von UIImageView
, repräsentiert eine Karte. Obwohl wir einige Eigenschaften in der eingestellt haben Karte
Klasse, der Hauptzweck der Erstellung dieser Klasse besteht darin, uns dabei zu helfen, die Unteransichten, die den Spielkarten im Spiel entsprechen, zu erkennen und zu durchlaufen. Die Karten haben auch Eigenschaften x
und y
um sich an ihre Position im Gitter zu erinnern.Fügen Sie den folgenden Code hinzu Game.swift, unmittelbar nach dem vorherigen Code:
öffentliche Klasse GameController: UIViewController // (1): öffentliche Variablen, damit wir sie auf dem Spielplatz bearbeiten können. public var padding = CGFloat (20) / * didSet resetGrid () * / public var backImage: UIImage = UIImage ( Farbe: .redColor (), Größe: CGSize (Breite: cardWidth, Höhe: cardHeight))! // (2): berechnete Eigenschaften var viewWidth: CGFloat get return 4 * cardWidth + 5 * padding var viewHeight: CGFloat get return 4 * cardHeight + 5 * padding var shuffledNumbers = [Int] () // speichert gemischte Kartennummern // var firstCard: Karte? // unkommentieren Sie später public init () super.init (nibName: nil, bundle: nil) preferredContentSize = CGSize (width: viewWidth, height: viewHeight) shuffle () setupGrid () // uncomment später: // Lassen Sie tap = UITapGestureRecognizer (target: self, action: #selector (GameController.handleTap (_ :))) // view.addGestureRecognizer (tap) Erforderlicher öffentlicher init? (Coder aDecoder: NSCoder) fatalError ("init (coder :) war nicht) implementiert ") public override func loadView () view = UIView () view.backgroundColor = .blueColor () view.frame = CGRect (x: 0, y: 0, width: viewWidth, height: viewHeight) // ( 3): Verwenden der GameplayKit-API zum Erzeugen eines Shufflings des Arrays [1, 1, 2, 2,…, 8, 8] func shuffle () Zahlen (1… 8) .flatMap [$ 0, $ 0] shuffledNumbers = GKRandomSource.sharedRandom (). arrayByShufflingObjectsInArray (Zahlen) als! [Int] // (4): Konvertieren Sie die Kartenposition im Raster in einen Index im gemischten Kartennummern-Array. Func cardNumberAt (x: Int, _ y: Int) -> Int assert (0 <= x && x < 4 && 0 <= y && y < 4) return shuffledNumbers[4 * x + y] // (5): Position of card's center in superview func centerOfCardAt(x: Int, _ y: Int) -> CGPoint assert (0 <= x && x < 4 && 0 <= y && y < 4) let (w, h) = (cardWidth + padding, cardHeight + padding) return CGPoint( x: CGFloat(x) * w + w/2 + padding/2, y: CGFloat(y) * h + h/2 + padding/2) // (6): setup the subviews func setupGrid() for i in 0… <4 for j in 0… <4 let n = cardNumberAt(i, j) let card = Card(image: UIImage(named: String(n)), x: i, y: j) card.tag = n card.center = centerOfCardAt(i, j) view.addSubview(card) // (7): reset grid /* func resetGrid() view.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight) for v in view.subviews if let card = v as? Card card.center = centerOfCardAt(card.x, card.y) */ override public func viewDidAppear(animated: Bool) for v in view.subviews if let card = v as? Card // (8): failable casting UIView.transitionWithView( card, duration: 1.0, options: .TransitionFlipFromLeft, animations: card.image = self.backImage , completion: nil)
Polsterung
und zurückBild
, werden erklärt Öffentlichkeit
damit wir später auf dem Spielplatz darauf zugreifen können. Sie repräsentieren den leeren Bereich, der die Karten im Raster umgibt, und das Bild, das auf der Rückseite jeder Karte angezeigt wird. Beachten Sie, dass beide Eigenschaften mit Anfangswerten versehen wurden, die eine Auffüllung von 20 und eine durchgehende rote Farbe für das bildseitige Bild der Karte darstellen. Sie können den auskommentierten Code vorerst ignorieren.viewWidth
Denken Sie daran, dass es in jeder Reihe vier Karten gibt, und wir müssen auch die Auffüllung jeder Karte berücksichtigen. Die gleiche Idee gilt für die viewHeight
Berechnung.(1… 8) .flatMap [$ 0, $ 0]
ist eine prägnante Methode zur Erstellung des Arrays [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8]
. Wenn Sie mit der funktionalen Programmierung nicht vertraut sind, können Sie auch eine schreiben zum
-Schleife, um das Array zu erzeugen. Methoden aus dem GamePlayKit
In diesem Rahmen mischen wir die Zahlen im Array. Die Zahlen entsprechen den acht Kartenpaaren. Jede Zahl steht für das Kartenbild mit demselben Namen (z. B. ein Wert von 1
im mischteArray
entspricht 1.png).gemischt nummern
Array der Länge 16. Der Faktor 4
In der arithmetischen Berechnung spiegelt sich die Tatsache wider, dass wir vier Karten pro Reihe haben.Center
Eigenschaft) im Raster basierend auf den Kartenabmessungen und dem Auffüllen.setupGrid ()
Die Methode wird während der Initialisierung des View-Controllers aufgerufen. Es legt den 4x4 fest Karte
Gitter. Es weist auch die Identität jeder Karte auf der Basis von zu gemischt nummern
Array und speichert es im Etikett
Eigenschaft, die von der Basisklasse der Karte geerbt wurde, UIView
. In der Spielelogik vergleichen wir die Etikett
Werte, um herauszufinden, ob zwei Karten übereinstimmen oder nicht. Dieses eher rudimentäre Modellierungsschema ist gut genug für unsere aktuellen Bedürfnisse.Polsterung
Eigentum als öffentliches Eigentum, so dass wir auf dem Spielplatz darauf zugreifen können.viewDidAppear (_ :)
Wird sofort ausgeführt, nachdem die Ansicht des View-Controllers sichtbar wird. Wir durchlaufen die Unteransichten der Ansicht und, wenn die Unteransicht eine Instanz von ist Karte
Klasse, (geprüft durch die wie?
fehlgeschlagener Downcasting-Operator) der Körper des ob
-Anweisung definiert den durchzuführenden Übergang. Hier ändern wir das Bild, das auf den Karten angezeigt wird, vom Cartoon-Bild, das das Gesicht jeder Karte definiert, zu dem (allgemeinen) Bild. zurückBild
von allen Karten. Dieser Übergang wird von einer Flip-Animation von links nach rechts begleitet, die das Erscheinungsbild der physisch umgedrehten Karten anzeigt. Wenn Sie nicht wissen, wie UIView
Animationen funktionieren, das kann ein bisschen seltsam aussehen. Obwohl wir die Animationen jeder Karte nacheinander in einer Schleife hinzugefügt haben, werden die Animationen in einer einzigen Animationstransaktion zusammengefasst und gleichzeitig ausgeführt, d. H., Die Karten werden zusammen gedreht.Besuchen Sie den Spielplatz erneut und ersetzen Sie den Text im Editor durch Folgendes:
importiere XCPlayground importiere UIKit gc = GameController () XCPlaygroundPage.currentPage.liveView = gc
Stellen Sie sicher, dass die Zeitleiste sichtbar ist. Die Ansicht des View-Controllers sollte zum Leben erweckt werden und zeigt uns ein 4x4-Kartenraster mit niedlichen Cartoons, die umgedreht werden, um uns die Rückseite der Karten zu zeigen. Im Moment können wir mit dieser Ansicht nicht viel anfangen, da wir noch keine Interaktion darin programmiert haben. Aber es ist definitiv ein Anfang.
Lassen Sie uns nun die Rückseite der Karten von einem durchgehenden Rot in ein Bild umwandeln b.png in dem Ressourcen Mappe. Fügen Sie die folgende Zeile am unteren Rand des Spielplatzes hinzu.
gc.backImage = UIImage (benannt: "b")!
Nach ein oder zwei Sekunden sehen Sie, dass sich die Rückseite der Karten von normalem Rot zu einer Cartoonhand geändert hat.
Lass uns jetzt versuchen das zu ändern Polsterung
Eigenschaft, der wir einen Standardwert von 20 in zugewiesen haben Game.swift. Der Abstand zwischen den Karten sollte sich dadurch vergrößern. Fügen Sie die folgende Zeile am unteren Rand des Spielplatzes hinzu:
gc.padding = 75
Warten Sie, bis die Live-Ansicht aktualisiert wird, und sehen Sie, dass sich nichts geändert hat.
Um zu verstehen, was los ist, müssen Sie berücksichtigen, dass Entitäten wie View Controller und die zugehörigen Ansichten einen komplexen Lebenszyklus haben. Wir werden uns auf die letzteren, dh Ansichten, konzentrieren. Das Erstellen und Aktualisieren der Ansicht eines View-Controllers ist ein mehrstufiger Prozess. An bestimmten Punkten im Lebenszyklus der Ansicht werden Benachrichtigungen an den Server ausgegeben UIViewController
, Informieren Sie darüber, was los ist. Noch wichtiger ist, dass der Programmierer sich in diese Benachrichtigungen einfügt, indem er Code einfügt, um diesen Prozess zu steuern und anzupassen.
Das loadView ()
und viewDidAppear (_ :)
Methoden sind zwei Methoden, mit denen wir uns in den Ansichtslebenszyklus einklinken. Dieses Thema ist etwas umständlich und geht über den Rahmen dieser Diskussion hinaus, aber für uns zählt, dass der Code auf dem Spielplatz nach der Zuweisung des View-Controllers als Spielplatz gilt Liveübertragung
, wird einige Zeit zwischen dem Aufruf an ausgeführt viewWillAppear (_ :)
und der Anruf an viewDidAppear (_ :)
. Sie können dies überprüfen, indem Sie einige Eigenschaften auf dem Spielplatz ändern und diesen beiden Methoden Druckanweisungen hinzufügen, um den Wert dieser Eigenschaft anzuzeigen.
Das Problem mit dem Wert von Polsterung
nicht die erwartete visuelle Wirkung hat, ist die Ansicht und ihre Unteransichten zu diesem Zeitpunkt bereits angelegt. Denken Sie daran, dass der Spielplatz bei jeder Änderung des Codes von Anfang an wiederholt wird. In diesem Sinne ist dieses Problem nicht spezifisch für Spielplätze. Selbst wenn Sie Code für die Ausführung auf dem Simulator oder auf einem physischen Gerät entwickeln, müssen Sie häufig zusätzlichen Code schreiben, um sicherzustellen, dass die Änderung des Werts einer Eigenschaft die gewünschte Auswirkung auf das Erscheinungsbild oder den Inhalt der Ansicht hat.
Sie fragen sich vielleicht, warum wir den Wert von ändern konnten zurückBild
Eigenschaft und sehen das Ergebnis, ohne etwas Besonderes zu tun. Beachten Sie, dass die zurückBild
Eigenschaft wird tatsächlich zum ersten Mal in verwendet viewDidAppear (_ :)
, Zu diesem Zeitpunkt hat es bereits seinen neuen Wert erlangt.
Unser Umgang mit dieser Situation wird darin bestehen, Änderungen des Wertes von zu überwachen Polsterung
und die Größe und Ansicht der Ansicht und der Unteransichten ändern. Glücklicherweise ist dies mit Swifts Handy einfach zu erreichen Immobilienbeobachtung Merkmal. Beginnen Sie mit dem Auskommentieren des Codes für die resetGrid ()
Methode in Game.swift:
// (7): reset grid func resetGrid () view.frame = CGRect (x: 0, y: 0, width: viewWidth, height: viewHeight) für v in view.subviews wenn let card = v as? Karte card.center = centerOfCardAt (card.x, card.y)
Diese Methode berechnet die Position des Rahmens der Ansicht und die Position jedes Bilds neu Karte
Objekt basierend auf den neuen Werten von viewWidth
und viewHeight
. Es sei daran erinnert, dass diese Eigenschaften basierend auf dem Wert von berechnet werden Polsterung
, das wurde gerade geändert.
Ändern Sie auch den Code für Polsterung
verwenden Sie die didSet
Ein Beobachter, dessen Körper, wie der Name schon sagt, immer ausgeführt wird, wenn wir den Wert von setzen Polsterung
:
// (1): öffentliche Variablen, damit wir sie auf dem Spielplatz bearbeiten können. Public var padding = CGFloat (20) didSet resetGrid ()
Das resetGrid ()
Die Methode wird aktiviert, und die Ansicht wird aktualisiert, um den neuen Abstand wiederzugeben. Sie können dies auf dem Spielplatz überprüfen.
Es scheint, dass wir die Dinge ziemlich leicht beheben konnten. In der Realität wollte ich, als ich mich zum ersten Mal entschied, mit dem Internet interagieren können Polsterung
Eigenschaft, ich musste zurückgehen und den Code in ändern Game.swift. Zum Beispiel musste ich die abstrahieren Karte
Center-Berechnung in einer separaten Funktion (centerOfCardAt (_: _ :)
) die Positionen der Karten sauber und unabhängig (neu) zu berechnen, wann immer sie ausgelegt werden mussten.
Berechnete Eigenschaften für erstellen viewWidth
und viewHeight
hat auch geholfen. Diese Art des Umschreibens ist zwar etwas, worauf Sie als Kompromiss vorbereitet sein sollten, wenn Sie nicht viel Design im Vorfeld machen, es kann jedoch mit einigem Nachdenken und Erfahrung reduziert werden.
Es ist jetzt an der Zeit, die Logik des Spiels zu implementieren und es uns zu ermöglichen, durch Berührung mit ihr zu interagieren. Beginnen Sie damit, das Kommentarzeichen zu entfernen erste karte
Eigenschaftserklärung in der Spielcontroller
Klasse:
var firstCard: Karte?
Erinnern wir uns daran, dass die Logik des Spiels das Aufdecken zweier Karten nacheinander beinhaltet. Diese Variable überwacht, ob ein vom Spieler ausgeführter Kartenumschlag der erste von beiden ist oder nicht.
Fügen Sie am unteren Rand die folgende Methode hinzu Spielcontroller
Klasse, vor der abschließenden geschweiften Klammer:
func handleTap (gr: UITapGestureRecognizer) let v = view.hitTest (gr.locationInView (view), withEvent: nil)! wenn let card = v as? Card UIView.transitionWithView (card, Dauer: 0.5, Optionen: .TransitionFlipFromLeft, Animationen: card.image = UIImage (named: String (card.tag))) // nachfolgender Beendigungshandler: _ in card.userInteractionEnabled = false, wenn pCard = self.firstCard if pCard.tag == card.tag UIView.animateWithDuration (0.5, Animationen: card.alpha = 0.0, Abschluss: _ in card.removeFromSuperview ()) UIView.animateWithDuration (0.5, Animationen: pCard.alpha = 0.0, Fertigstellung: _ in pCard.removeFromSuperview ()) else UIView.transitionWithView (Karte, Dauer: 0,5, Optionen: .TransitionFlipFromLeft, Animationen: card.image = self.backImage) _ in card.userInteractionEnabled = true UIView.transitionWithView (pCard, Dauer: 0.5, Optionen: .TransitionFlipFromLeft, Animationen: pCard.image = self.backImage) _ in pCard.userInteractionEnabled = true self.firstCard = nil else self.firstCard = card
Das ist eine langwierige Methode. Das ist so, weil es alle erforderlichen Berührungshandlungen, die Spiellogik sowie die dazugehörigen Animationen in einer Methode vereint. Mal sehen, wie diese Methode funktioniert:
Karte
Beispiel. Das ist das gleiche wie?
Konstrukt, das wir früher verwendet haben.Karte
Wir drehen es beispielsweise mit einer Animation um, die der zuvor implementierten ähnelt. Der einzige neue Aspekt ist, dass wir den Beendigungs-Handler verwenden, der nach Abschluss der Animation ausgeführt wird, um Berührungsinteraktionen für diese bestimmte Karte vorübergehend zu deaktivieren, indem Sie die Option festlegen userInteractionEnabled
Eigentum der Karte. Dies verhindert, dass der Spieler dieselbe Karte umdreht. Beachten Sie das _ im
Konstrukt, das in dieser Methode mehrfach verwendet wird. Dies ist nur zu sagen, dass wir das ignorieren wollen Bool
Parameter, den der Completion-Handler übernimmt.erste karte
Mit der optionalen Bindung wurde ein nicht-null-Wert zugewiesen wenn lassen
konstruieren.erste karte
ist nicht Null, dann war dies die zweite Karte der Sequenz, die der Spieler umgedreht hat. Wir müssen nun das Gesicht dieser Karte mit dem vorherigen vergleichen (durch Vergleich der Etikett
Werte), um zu sehen, ob wir eine Übereinstimmung haben oder nicht. Wenn ja, animieren wir die Karten, die ausgeblendet werden Alpha
bis 0). Wir entfernen diese Karten auch aus der Ansicht. Wenn die Tags nicht gleich sind, was bedeutet, dass die Karten nicht übereinstimmen, drehen wir sie einfach nach unten und setzen sie userInteractionEnabled
zu wahr
damit der Benutzer sie erneut auswählen kann.erste karte
, wir setzen es auf entweder Null
oder zur vorliegenden Karte. So wechseln wir das Verhalten des Codes zwischen zwei aufeinander folgenden Berührungen.Unkommentieren Sie schließlich die folgenden beiden Aussagen in der Spielcontroller
Initialisierung, die der Ansicht eine Antippen-Gestenerkennung hinzufügt. Wenn die Antippen-Erkennungsfunktion ein Antippen erkennt, wird die handleTap ()
Methode wird aufgerufen:
let tap = UITapGestureRecognizer (Ziel: Selbst, Aktion: #selector (GameController.handleTap (_ :))) view.addGestureRecognizer (tap)
Gehe zurück zur Zeitleiste des Spielplatzes und spiele das Memory-Spiel. Fühlen Sie sich frei, um die Größe zu verringern Polsterung
Wir haben etwas früher vergeben.
Der Code in handleTap (_ :)
ist so ziemlich die unverblümte Version von dem, was ich zum ersten Mal geschrieben habe. Man könnte den Einwand erheben, dass es als einzelne Methode zu viel tut. Oder dass der Code nicht objektorientiert genug ist und dass die Logik und die Animationen der Karte auf einfache Weise in die Methoden der Karte
Klasse. Während diese Einwände nicht ungültig sind an sich, Denken Sie daran, dass der Schwerpunkt dieses Tutorials auf schnellem Prototyping liegt. Da wir nicht erwartet hatten, mit diesem Teil des Codes auf dem Spielplatz zu interagieren, könnten wir es uns leisten, ein bisschen mehr "hack-ish" zu sein..
Wenn wir etwas in Arbeit haben und uns dazu entschließen, die Idee weiter zu verfolgen, müssten wir das Code-Refactoring in Betracht ziehen. Mit anderen Worten: Zuerst muss es funktionieren, dann schnell / elegant / hübsch /…
Während der Hauptteil des Tutorials jetzt vorbei ist, möchte ich Ihnen als interessanten Nebeneffekt zeigen, wie Sie den Touch-Handling-Code direkt auf dem Spielplatz schreiben können. Wir werden zuerst eine Methode hinzufügen Spielcontroller
Klasse, die uns erlaubt, auf die Gesichter der Karten zu schauen. Fügen Sie dem folgenden Code hinzu Spielcontroller
Klasse, unmittelbar nach dem handleTap (_ :)
Methode:
public func quickPeek () für v in view.subviews wenn let card = v as? Card card.userInteractionEnabled = false UIView.transitionWithView (Karte, Dauer: 1.0, Optionen: .TransitionFlipFromLeft, Animationen: card.image = UIImage (benannt: String (card.tag))) _ in UIView.transitionWithView (card , duration: 1.0, Optionen: .TransitionFlipFromLeft, Animationen: card.image = self.backImage) _ in card.userInteractionEnabled = true
Angenommen, wir möchten die Möglichkeit, diese "Schnellansicht" innerhalb des Spielplatzes zu aktivieren oder zu deaktivieren. Eine Möglichkeit, dies zu tun, wäre die Schaffung einer Öffentlichkeit Bool
Eigentum in der Spielcontroller
Klasse, die wir auf dem Spielplatz einstellen konnten. Und natürlich müssten wir einen Gestenhandler in schreiben Spielcontroller
Klasse, aktiviert durch eine andere Geste, die das aufrufen würde quickPeek ()
.
Eine andere Möglichkeit wäre, den Code für die Gestenbehandlung direkt auf dem Spielplatz zu schreiben. Dies hat den Vorteil, dass wir neben dem Aufruf auch benutzerdefinierten Code integrieren können quickPeek ()
. Dies werden wir als Nächstes tun. Fügen Sie den folgenden Code am unteren Rand des Spielplatzes hinzu:
Klasse LPGR static var counter = 0 @objc static func longPressed (lp: UILongPressGestureRecognizer) if lp.state == .Began gc.quickPeek () counter + = 1 print ("Sie sahen \ (counter) time (s) . ") longPress = UILongPressGestureRecognizer (Ziel: LPGR.self, Aktion: #selector (LPGR.longPressed)) longPress.minimumPressDuration = 2.0 gc.view.addGestureRecognizer (longPress)
Um die Schnellzugriffsfunktion zu aktivieren, verwenden wir eine lange Druckbewegung, dh der Spieler hält den Finger für eine gewisse Zeit auf dem Bildschirm. Wir verwenden zwei Sekunden als Schwelle.
Für die Handhabung der Geste erstellen wir eine Klasse, LPGR
(Langes Drücken