Willkommen bei SO!
Ok, es gibt eine Menge zu entpacken also etwas Popcorn ... Ich denke, dass Sie hier auf dem richtigen Weg sind, meistens müssen Sie auf Null prüfen, wenn Sie Fehler bekommen.
Erstens, das ist falsch in Ihrem Schnittstellencontroller, und der Teil, der mich betroffen. Hier werden nur neue GameScene-Instanzen instanziiert, die vollständig von der gameScene-Instanz getrennt sind, die von Ihrem Schnittstellen-Controller einige Zeilen entfernt erstellt wurde. Dann, waren Sie die Krone delegieren Funktionen auf diese völlig leer gameScenes Senden .:
private var game = GameScene() // You are referencing nothing here, just creating a new gamescene.
private var player = GameScene() // I don't think that player is supposed to be a gamescene!
Ich reparierte es, indem Sie die tatsächlichen gameScene Zuweisung an den Eigenschaften verwenden möchten (also können sie von der Krone Delegat verwendet werden) .
private var game: GameScene!
lazy private var player: SKSpriteNode = self.game.player
override func awake(withContext context: Any?) {
// ... Stuff...
if let scene = GameScene(fileNamed: "GameScene") {
game = scene
Dies wurde auch den neuen Code in Ihre Krone Delegierten zu vertreten geändert:
game.moveSprite(player: player, moveDirection: moveDirection)
In addPlayer Sie dies taten:
player.physicsBody?.isDynamic = true // This needs to go AFTER you init your pb.
player.physicsBody = SKPhysicsBody(rectangleOf: player.size)
... und ich repariere es durch Vertauschen der Linien.
Persönlich mag ich folgendes tun, um sicherzustellen, dass keine kleinen Fehler gemacht:
let pb = SKPhysicsBody(...)
pb.isDynamic = true
player.physicsBody = pb
moveSprite mit ihm ein paar Probleme hatte, so werde ich aufzählen sie nicht als Ich habe oben getan. Überprüfe, was ich getan habe, dann frag mich, ob du irgendwelche Fragen hast. Im Grunde genommen warst du von Anfang an mit dieser Funktion verdammt, weil du diese Methode vom Interface-Controller aus mit den ausgefuchsten player
Werten aufgerufen hast, die alle null waren.
Auch die .applyImpulse gab mir ziemlich schlechte Kontrollen, so änderte ich es auf eine einfache Einstellung von .position
. Es gibt immer noch ein kleines Problem mit dem Segeln, bevor der Spieler stoppt, aber das kann in einer anderen Frage behandelt werden :) (beachte, dass ich das nur am Simulator getestet habe ... ist möglicherweise kein Problem auf dem Gerät).
Auch ich hasse Fehler, die durch Rechtschreibfehler in Strings verursacht werden, also konvertierte ich dies zu einem enum für Sie.
func moveSprite(player : SKSpriteNode, moveDirection: Direction) {
// This will give us an equal amount of pixels to move across the watch devices:
// Adjust this number for shorter/longer movements:
let percentageOfScreenToMovePerRotation = CGFloat(1) // One percent
let modifier = percentageOfScreenToMovePerRotation/100
let amountToMove = self.frame.maxX * modifier
switch moveDirection {
case .UP:
player.position.x += amountToMove
case .DOWN:
player.position.x -= amountToMove
case .STOP:
break
}
}
Die wirkliche Moral der Geschichte ist hier zu -Check für null. Wenn Sie einfach someOptional?.someMethod()
die ganze Zeit verwenden, dann werden Sie wahrscheinlich nicht in der Lage sein, leicht zu bestimmen, ob someMethod()
tatsächlich aufgerufen wird oder nicht .. so wissen Sie nicht, ob das Problem mit der aufrufenden Logik ist, die Methode, oder mit dem Objekt nicht vorhanden, und etc.
Force Unwrapping ist in Produktionscode verpönt, aber IMO ist es äußerst wertvoll beim ersten Start - weil es Ihnen hilft, Fehler schnell zu identifizieren.
Später, können Sie beginnen, Dinge wie if let
und guard
zu helfen, überprüfen für null verwenden, ohne Ihre Programme abstürzt, sondern dass mehr Unordnung und Komplexität zu Ihrem Code hinzufügt, wenn Sie versuchen, nur die Grundlagen einer neuen API zu lernen und Sprache.
Und als letzter Tipp, versuchen Sie nicht hartcodierte Zeichenfolgen zu verwenden, wann immer möglich: sie in eine ENUM setzen oder eine Konstante, wie ich in Ihrem Code haben:
// Because I hate string spelling erros, and you probably do too!
enum Direction {
case UP, DOWN, STOP
}
// Because I hate errors related to spelling in strings:
let names = (ONE: "ONE", TWO: "TWO")
Hier sind die beiden Dateien in ihrer Gesamtheit .. beachten sie, dass ich ein paar Dinge kommentieren sie musste, um es in meinem Projekt zu arbeiten:
GameScene:
// Because I hate string spelling erros, and you probably do too!
enum Direction {
case UP, DOWN, STOP
}
class GameScene: SKScene, SKPhysicsContactDelegate, WKCrownDelegate {
var watchParticles:SKEmitterNode!
var player: SKSpriteNode!
var player2: SKSpriteNode!
var playerPosition:CGPoint!
// Because I hate errors related to spelling in strings:
let names = (ONE: "ONE", TWO: "TWO")
func addPlayer() {
player = SKSpriteNode(color: .blue, size: CGSize(width: 50, height: 50))
// player = SKSpriteNode(imageNamed: "Spaceship")
// player.setScale(0.15)
player.position = CGPoint(x: 5, y: -60)
player.name = names.ONE
player.physicsBody = SKPhysicsBody(rectangleOf: player.size)
player.physicsBody!.isDynamic = true // This was placed *before* pb initialzier (thus never got called)
player2 = SKSpriteNode(color: .yellow, size: CGSize(width: 50, height: 50))
// player2 = SKSpriteNode(imageNamed: "Spaceship")
// player2.setScale(0.15)
player2.position = CGPoint(x: 5, y: -60)
player2.name = names.TWO
player2.physicsBody = SKPhysicsBody(rectangleOf: player2.size)
player2.physicsBody!.isDynamic = false // This was placed *before* pb initialzier (thus never got called)
addChild(player)
addChild(player2)
playerPosition = player.position
}
override func sceneDidLoad() {
self.scaleMode = SKSceneScaleMode.aspectFill
//watchParticles = SKEmitterNode(fileNamed: "watchParticles")
//addChild(watchParticles)
self.physicsWorld.gravity = CGVector.zero
physicsWorld.contactDelegate = self
addPlayer()
}
func moveSprite(player : SKSpriteNode, moveDirection: Direction) {
// This will give us an equal amount of pixels to move across the watch devices:
// Adjust this number for shorter/longer movements:
let percentageOfScreenToMovePerRotation = CGFloat(1) // One percent
let modifier = percentageOfScreenToMovePerRotation/100
let amountToMove = self.frame.maxX * modifier
switch moveDirection {
case .UP:
player.position.x += amountToMove
case .DOWN:
player.position.x -= amountToMove
case .STOP:
break
}
}
}
InterfaceController:
class InterfaceController: WKInterfaceController, WKCrownDelegate {
@IBOutlet var skInterface: WKInterfaceSKScene!
private var moveDirection = Direction.STOP
private var game: GameScene!
lazy private var player: SKSpriteNode = self.game.player
override func awake(withContext context: Any?) {
super.awake(withContext: context)
crownSequencer.delegate = self
crownSequencer.focus()
if let scene = GameScene(fileNamed: "GameScene") {
game = scene // VERY IMPORTANT!
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
self.skInterface.presentScene(scene)
crownSequencer.delegate = self
crownSequencer.focus()
// Use a value that will maintain a consistent frame rate
self.skInterface.preferredFramesPerSecond = 30
}
else {
fatalError("scene not found")
}
}
func crownDidRotate(_ crownSequencer: WKCrownSequencer?, rotationalDelta: Double) {
if rotationalDelta > 0{
moveDirection = .UP
game.moveSprite(player: player, moveDirection: moveDirection)
} else if rotationalDelta < 0{
moveDirection = .DOWN
game.moveSprite(player: player, moveDirection: moveDirection)
}
}
func crownDidBecomeIdle(_ crownSequencer: WKCrownSequencer?) {
moveDirection = .STOP
game.moveSprite(player: player, moveDirection: moveDirection)
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
}
Wenn Sie Ihre Stellvertretung Code schreiben, kann ich Ihnen zeigen, wie es zu einem SKNode bespannen auf. – Fluidity
Ich habe es am besten aktualisiert Ich könnte hoffen, dass dies hilft und danke für die Hilfe. @Flüssigkeit –