更改场景后节点不移动

时间:2014-11-19 23:06:46

标签: xcode swift

我做了一个(基本的)游戏,效果很好,去GameOverScene,当它从GameOverScene回到GameScene时,玩家(spritenode)不再移动..

我在GameScene代码中评论了它的功能

我从Xcode中得不到任何错误!

该bug位于gamescene.swift文件中(函数:swipedRight + swipedLeft + swipedUp + swipedDown):

import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {

var kikker:SKSpriteNode = SKSpriteNode()
var auto1:SKSpriteNode = SKSpriteNode()
var lastYieldTimeInterval:NSTimeInterval = NSTimeInterval()
var lastUpdateTimerInterval:NSTimeInterval = NSTimeInterval()
let playerCategory:UInt32 = 0x1 << 1
let auto1Category:UInt32 = 0x1 << 0

required init(coder aDecoder:NSCoder) {
    fatalError("NSCoder not supported")
}

override init(size:CGSize) {
    super.init(size:size)
   anchorPoint = CGPoint(x:0, y:1.0)
    let background = SKSpriteNode(imageNamed: "bg5")
   var auto1:SKSpriteNode = SKSpriteNode(imageNamed: "auto1")
   background.position = CGPoint(x:0, y:0)
   background.anchorPoint=CGPoint(x:0,y:1.0)
   addChild(background)
    kikker = SKSpriteNode(imageNamed:"kikker5")
    kikker.anchorPoint = CGPoint(x:0.5, y:0.5)
     kikker.xScale = 0.22
   kikker.yScale = 0.22
    self.physicsWorld.gravity = CGVectorMake(0,0)
    self.physicsWorld.contactDelegate = self
   kikker.physicsBody?.categoryBitMask = playerCategory
    kikker.physicsBody?.contactTestBitMask = auto1Category
    kikker.physicsBody?.collisionBitMask = 0
    kikker.physicsBody?.usesPreciseCollisionDetection = true
    kikker.physicsBody = SKPhysicsBody(circleOfRadius: kikker.size.width/2)
    kikker.physicsBody?.dynamic = false
     kikker.position = CGPointMake(self.frame.size.width/2, -610)    
   addChild(kikker)    
    println(kikker.position)
}

 func didBeginContact(contact: SKPhysicsContact!) {
       var firstBody:SKPhysicsBody
    var secondBody:SKPhysicsBody
    if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask){
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    }else{
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if((firstBody.categoryBitMask & auto1Category) != 0 && (secondBody.categoryBitMask & playerCategory) != 0)
    {
    println("aasda")
    aangereden(contact.bodyB.node as SKSpriteNode, player: contact.bodyA.node as SKSpriteNode)  
    } 
}

func addCar(){
    var auto1:SKSpriteNode = SKSpriteNode(imageNamed: "auto2")
    auto1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(auto1.size.width/2,     auto1.size.height/2) )
auto1.physicsBody?.dynamic = true
    auto1.physicsBody?.categoryBitMask = auto1Category
    auto1.physicsBody?.contactTestBitMask = playerCategory
    auto1.physicsBody?.collisionBitMask = 0
    auto1.physicsBody?.usesPreciseCollisionDetection = true
    let position : CGFloat = 51 + (CGFloat(arc4random_uniform(4)+2)*(-111))
    auto1.anchorPoint = CGPoint(x:0.5, y:0.5)
    auto1.position = CGPointMake(-auto1.size.width/2, position)
    self.addChild(auto1)
    let minDuration = 2.5
    let maxDuration = 4.0
    let rangeDuration = maxDuration - minDuration
    let duration = Int(arc4random()) % Int(rangeDuration) + Int(minDuration)
      var actionArray:NSMutableArray = NSMutableArray()

    actionArray.addObject(SKAction.moveTo(CGPointMake(375 + auto1.size.width/2, position), duration: NSTimeInterval(duration)))
    actionArray.addObject(SKAction.removeFromParent())
      auto1.runAction(SKAction.sequence(actionArray))
}

    println("DOOD")
    player.removeFromParent()    
}

func updateWithTimeSinceLastUpdate(timeSinceLastUpdate:CFTimeInterval){
    lastYieldTimeInterval += timeSinceLastUpdate
    if (lastYieldTimeInterval > 2.5){
        lastYieldTimeInterval = 0
        addCar()
    }
    }

//#1 function not working after changing scenes: the function is executing, the println works 
but for some reason the runAction doesnt do its job, the node(kikker) is not moving as it should
func swipedRight1(sender:UISwipeGestureRecognizer){
    var naarRechts = SKAction()
    var positionX = kikker.position.x

    println("right2") 
    if(kikker.position.x<200){
        println(positionX)
        positionX = kikker.position.x + 125
        println(positionX)
        naarRechts  = SKAction.moveToX(positionX , duration: 0.25)
        kikker.zRotation=(-1.570)
        kikker.runAction(naarRechts)

    }
}

//#2 function not working, same story
func swipedLeft1(sender:UISwipeGestureRecognizer){
    var naarLinks = SKAction()
    var positionX = kikker.position.x
    if(kikker.position.x>150){
        positionX = kikker.position.x - 125
        naarLinks  = SKAction.moveToX(positionX , duration: 0.25)
        kikker.zRotation=(1.570)
        kikker.runAction(naarLinks)
    }
}

//#3 function not working, same story
func swipedDown1(sender:UISwipeGestureRecognizer){
    var naarBeneden = SKAction()
    var positionY = kikker.position.y
    if(kikker.position.y>(-600)){
    positionY = kikker.position.y - 111
        naarBeneden = SKAction.moveToY(positionY , duration: 0.25)
        kikker.zRotation=3.141
        kikker.runAction(naarBeneden)
}
}

//#4 function not working, same story
func swipedUp1(sender:UISwipeGestureRecognizer){
    var naarBoven = SKAction()
    var positionY = kikker.position.y

    if(kikker.position.y < (-60)){
    positionY = kikker.position.y + 111
        naarBoven = SKAction.moveToY(positionY, duration: 0.25)
    kikker.zRotation=0
        kikker.runAction(naarBoven)
      }

    if(positionY > (-60)){
                var gameOverScene:SKScene = GameOverScene(size: self.size)
                self.view?.presentScene(gameOverScene)
    }
}

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
   var timeSinceLastUpdate = currentTime - lastUpdateTimerInterval
    lastUpdateTimerInterval = currentTime

    if (timeSinceLastUpdate > 1){
        timeSinceLastUpdate = 1/60
        lastUpdateTimerInterval = currentTime
    }
    updateWithTimeSinceLastUpdate(timeSinceLastUpdate)
}
}

这里是GameOverScene文件:

 import UIKit
import SpriteKit

class GameOverScene: SKScene {

override init(size:CGSize){
super.init(size:size)

    self.backgroundColor = SKColor.whiteColor()
    var message:NSString = NSString()
    message = "Game Over"
    var label:SKLabelNode = SKLabelNode(fontNamed:"DamascusBold")
    label.text = message
    label.fontColor = SKColor.blackColor()
    label.position = CGPointMake(self.size.width/2, self.size.height/2)
    self.addChild(label)
    var scene:GameScene!
    self.runAction(SKAction.sequence([SKAction.waitForDuration(3.0),
    SKAction.runBlock({
       // var transition:SKTransition = SKTransition.flipHorizontalWithDuration(0.5)
        var scene1:SKScene = GameScene(size: self.size)
        self.view?.presentScene(scene1)
    })
    ] ))
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

gameviewcontroller文件:

import UIKit
import SpriteKit
import AVFoundation

class GameViewController: UIViewController, UITextFieldDelegate{

var scene:GameScene!

func swipedRight(sender: UISwipeGestureRecognizer){
    scene.swipedRight1(sender)
}

func swipedLeft(sender: UISwipeGestureRecognizer){
    scene.swipedLeft1(sender)
}
func swipedDown(sender: UISwipeGestureRecognizer){
    scene.swipedDown1(sender)
}
func swipedUp(sender: UISwipeGestureRecognizer){
    scene.swipedUp1(sender)
}

override func viewDidLoad() {
    super.viewDidLoad()
   let skView = view as SKView
    skView.multipleTouchEnabled = false
    scene = GameScene(size: skView.bounds.size)
    scene.scaleMode = SKSceneScaleMode.AspectFill
    skView.presentScene(scene)
  let swipeRight:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedRight:"))
    swipeRight.direction = .Right
    view.addGestureRecognizer(swipeRight)
    let swipeLeft:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedLeft:"))
    swipeLeft.direction = .Left
    view.addGestureRecognizer(swipeLeft)
     let swipeUp:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedUp:"))
    swipeUp.direction = .Up
    view.addGestureRecognizer(swipeUp)
    let swipeDown:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedDown:"))
    swipeDown.direction = .Down
    view.addGestureRecognizer(swipeDown)
}

override func prefersStatusBarHidden() -> Bool {
    return true
}
}

1 个答案:

答案 0 :(得分:0)

您在错误的场景中调用swipedUp1(等)方法。这是正在发生的事情:

  1. 您的视图控制器引用了您开始的GameScene实例。它的手势动作方法称之为,一切都很好。

  2. 当您从GameOverScene开始新游戏时,会创建GameScene实例,并将其显示在视图中。现在您有两个 GameScene实例:视图控制器仍指向的实例,以及视图现在呈现的实例。

  3. 当你的手势动作开始时,他们仍在与第一个GameScene交谈。因此,您的日志行会打印出来,但是您没有看到任何事情发生,因为第二个GameScene是正在显示的那个。

  4. 无论如何,你可能不希望两个场景四处乱窜。

    您可以通过消除视图控制器中的scene属性并让您的手势操作调用view.scene代替(适当的投射后)来解决这两个问题:

    func swipedUp(sender: UISwipeGestureRecognizer) {
        let skView = view as SKView
        let gameScene = skView.scene as GameScene
        gameScene.swipedUp1(sender)
    }
    

    这样,滑动就会转到视图控制器view当前呈现的任何场景。

    或者,您可以保留原始的swipedUp(等)代码,并将scene从存储的属性更改为只读的计算代码,它始终会为您提供当前显示的场景:

    var scene: GameScene {
        let skView = view as SKView
        return skView.scene as GameScene
    }