2017-09-22 3 views
0

Ich lerne mit SprikeKit ein Spiel zu erstellen und das Spiel hat etwas mit Sushi-Train zu tun.Simulierender Sushi-Zug - Swift SpriteKit

Ich habe so etwas wie 20 Gerichte, die entlang eines rechteckigen Weges folgt, um das Aussehen zu simulieren, dass alle Gerichte auf einem sich bewegenden Förderband sind.

Ich habe mit einem Szeneneditor versucht, ein paar Sprite-Knoten zu platzieren und sie so auf einem quadratischen Pfad bewegen lassen.

let dish_1 = self.childNode(withName: "dish_1"); 
let dish_2 = self.childNode(withName: "dish_2"); 

let square = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 200, height: 200)); 
let followSquare = SKAction.follow(square.cgPath, asOffset: true, orientToPath: false, duration: 5.0); 

dish_1?.run(SKAction.sequence([followSquare])) 
dish_2?.run(SKAction.sequence([followSquare])) 

Zur Zeit verwenden die beiden Schalen des gleichen Platz und die Platz Position zu jeder Schale relativ ist, so dass sie, wie sie auf zwei verschiedenen rechteckigem Weg sind so aus, als Ausgangspunkt unterscheidet.

Ist dies der vernünftige Weg, um das Aussehen zu simulieren, nach dem ich suche? Der Grund, warum ich das frage ist, dass alle Gerichte so aussehen, als ob sie sich auf dem gleichen Weg bewegen, ich muss die x, y Positionen jedes Gerichtes anpassen und es wird wie 20 Gerichte sein.

Ich frage mich, ob es möglich wäre, Physik-Kit zu verwenden und lassen Sie einen Rechteck-Knoten macht die alle Gerichte auf dem Weg zu bewegen, solange sie innerhalb der rechteckigen Knotenbereich sind.

Antwort

1

Nun, ich hätte es wahrscheinlich in ähnlicher Weise getan, und ich denke, mit SKAction.Follow ist hier eine Lösung.

Aber es gibt ein paar Verbesserungen, die Sie in Ihrem Code tun könnten. Die erste ist, dass Sie nicht brauchen, um Ihre SKAction als eine Folge zu schreiben, weil es nur eine Aktion zusammengesetzt ist, so können Sie Ihren Code dies zu vereinfachen:

let squarePath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 200, height: 200)) 

    let followAction = SKAction.follow(path: squarePath.cgPath, duration: 5.0) 

    dish?.run(followAction) 

nun eine andere Sache, die wichtig ist, ist, Um Ihren Speicherverbrauch zu sparen, anstatt jedes Mal ein neues Gericht zu erstellen (20 Mal), können Sie einfach copy() auf Ihrem SKSpriteNode verwenden, um viele verschiedene Kopien davon zu erstellen. Je nachdem, was Sie erreichen müssen, können Sie natürlich jede Kopie anpassen, ihre Farbe oder Position ändern usw. Dies wäre viel effizienter.

Sie können eine Kopie Ihrer SKSpriteNode erstellen wie folgt:

import GameplayKit 

if let dishCopy = dish?.copy() as? SKSpriteNode { 
     dishCopy.position = CGPoint(x: GKRandomDistribution(lowestValue: 0, highestValue: 200).nextInt(), y: GKRandomDistribution(lowestValue: 0, highestValue: 500).nextInt()) 
     self.addChild(dishCopy) 
} 

Für die Position jedes Gericht zu kopieren, können Sie natürlich Ihre eigenen Werte einstellen, aber hier habe ich GameplayKit und seine sehr nützlich Zufalls Wertegenerator.

Update:

Wenn Sie einen eindeutigen Namen für jede Ihrer Gerichte festlegen möchten, während immer noch Kopie() verwenden, haben Sie mehrere Möglichkeiten.

Eine Möglichkeit wäre, einen eindeutigen Namen mit einem Zähler zu generieren, den Sie inkrementieren würden, eine andere Möglichkeit wäre currentTime in der Update-Methode zum Beispiel zu verwenden.

Aber eine andere elegantere Art, dies zu tun, und zu verfolgen, wo all Ihre Kopien sind, ist ein Array zu erstellen, das sie alle speichert.

An der Spitze der Szene Unterklasse, erklären Ihre Gerichte Array wie folgt:

var dishes = [SKSpriteNode]() 

Im Moment ist es noch leer ist, so dass Sie jede Kopie an das Array an der Zeit, die Sie erzeugen jeweils hinzufügen müssen sie aus:

// Create (safely) a dish copy: 

    if let dishCopy = dish?.copy() as? SKSpriteNode { 

     // Add the dish copy to the dishes array: 

     dishes.append(dishCopy) 

     // And add the dish copy to the world node: 

     worldNode?.addChild(dishCopy) 
    } 

Wenn Sie viele Kopien wie diese erstellen möchten, können Sie einen for loop verwenden, oder Sie können mit dem update(_ currentTime:) Methode spielen, indem sie angeben, dass Sie ein neues Sushi Teller alle 5 Sekunden zum Beispiel erstellen möchten :).

Und gut, wenn Sie jederzeit auf eine dieser Kopien zugreifen müssen, tun Sie dies, indem Sie auf das dishes Array zugreifen.

Zum Beispiel ist dies, wie Sie alle Kopien entfernen würden (Sie müßten mit dem ursprünglichen Gericht behandeln, wenn Sie es in die Szene allerdings hinzugefügt):

// And just iterate through all of your dish copies: 

for dish in dishes { 

    dish.removeFromParent() 

    // Do whatever you need here :) 

} 

Es ist ziemlich einfach und ermöglicht es Ihnen, um alle Objekte und/oder Kopien, die Sie zu Ihrer hinzugefügt haben, perfekt zu steuern.

Lassen Sie mich einfach wissen, wenn Sie weitere Fragen haben, ich würde gerne helfen!

Übrigens werde ich heute tatsächlich zu dem Sushi-Restaurant gehen, über das du in deiner Frage sprichst, das mit dem kleinen Zug .. Netter Zufall! : D

+0

Vielen Dank. Sehr hilfreich. Ich habe mit copy() gesucht. Da aber jede Gerichtsstrecke tatsächlich Sushi als Kindknoten haben muss, war ich nicht sicher, ob die kopierte Instanz einen Kindknoten hätte. Jedes Gericht muss auch einen eindeutigen Identifikator haben, damit der Spieler es auswählen und Sushi auffüllen kann, so dass ich mich fragte, wie ich seine ID kennen könnte, wenn es sich um kopierte Instanzen handelte. –

+1

Sie sind herzlich willkommen @SeongLeem, ich aktualisierte meine Antwort zu geben Sie mehr Details darüber, wie Sie das in Ihrer App implementieren könnten – Alex

+1

Das ist großartig. Vielen Dank! Was ist der Anwendungsfall für den Weltknoten hier anstelle der Szene?Jeder Gerichtkopieknoten muss einen Kindknoten wie Lachs, Thunfisch usw. haben. Ich denke also, ich kann Lachskindknoten für die ersten 5 Gerichte unter Verwendung einer Schleife wie in für _ in 0 zuordnen. <5 {füge Kindknoten hinzu}. Und ich denke, in jeder Programmiersprache kann ein Array mehrere Ebenen nach unten oder oben haben. –

1

asOffset scheint nicht korrekt. Laut the documentation ist dies genau das Gegenteil Verhalten Sie wollen.

Wenn JA, sind die Punkte im Pfad relative Offsets zur Startposition des Knotens. Wenn NEIN, sind die Punkte im Knoten absolute Koordinatenwerte.

Sie diesen Wert auf echte würde jedes Gericht ihre eigenen Rechteck-Pfad mit Koordinaten relativ zu ihrer Ausgangsposition zu folgen geben, wie Sie in der Frage beschreiben:

 
    v First dish 
     v Second dish 
    O--O-----.---. 
    | |  | | 
    | |  | | 
    '--'-----'---' 
       ^^ Second dish's path 
    ^^ First dish's path 

Stattdessen würde ich mir vorstellen, Sie müssen gesetzt, das Förderband in absoluten Koordinaten auf, initialisiert dann jede Ausgangspunkt der Schale unterschiedlich zu sein - wieder in absoluten Koordinaten - und schließlich haben jede Schale Folgen des Weg:

 
    v First dish (starting point x=0; y=0) 
     v Second dish (starting point x=20; y=0) 
    O--O-----. 
    |  | 
    |  | 
    '--------' 

    ^^ Single, absolute path 

(Wenn Sie ein Sushi-Förderband simulieren, bewegen sie sich im Uhrzeigersinn und die Nomenklatur "first" und "second" oben ist technisch rückwärts gerichtet. Der Austausch wird dem Leser überlassen. :-P)

+0

Vielen Dank für Ihre aufschlussreiche Antwort. Dies scheint definitiv der richtige Weg zu sein. Sorry, ich bin neu in der Spieleentwicklung, wie stelle ich den rechteckigen Pfad als absolute Koordinaten ein? Ist es standardmäßig relativ? –

+1

Ich würde mir vorstellen, dass alles in dem 'asOffset'-Parameter in Ihrem Aufruf von 'follow' steht. Wenn Sie dies auf false setzen, bedeutet dies, dass die Pfadkoordinaten absolut sind. –

Verwandte Themen