2016-03-15 95 views
1

我想創建一個SKShapeNode實例和屏幕邊緣之間的碰撞,但由於某種原因,ShapeNode仍然超出屏幕的限制。我已經實現了我認爲應該處理碰撞的代碼,但我是SpriteKit的新手,所以我不完全確定。這裏有一段代碼:iOS SpriteKit碰撞屏幕邊緣不起作用

// 
// GameScene.swift 
// SpriteKitTest 
// 
// Created by 580380 on 3/10/16. 
// Copyright (c) 2016 580380. All rights reserved. 
// 

import SpriteKit 
import UIKit 
import CoreMotion 

class GameScene: SKScene { 

    //MARK: - Global variables 
    let motionManager = CMMotionManager() 
    var circleNode = SKShapeNode() 
    var destX : CGFloat = 0.0 
    var destY : CGFloat = 0.0 

    enum Collision :UInt32 { 
     case ball = 1 
     case wall = 2 
    } 
    //MARK: - Sprite kit functionality 
    override func didMoveToView(view: SKView) { 

     backgroundColor = UIColor.whiteColor() 
     createCircleNode() 
     moveCircleNode() 
     self.addChild(circleNode) 
    } 

    //Setup and configuring the SKShapeNode object 
    private func createCircleNode() { 
     circleNode.path = UIBezierPath(arcCenter: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), radius: 20, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true).CGPath 
     circleNode.fillColor = UIColor.redColor() 
     circleNode.strokeColor = UIColor.blueColor() 
     circleNode.lineWidth = 1 
    } 

    private func moveCircleNode() { 
     circleNode.physicsBody = SKPhysicsBody() 
     circleNode.physicsBody?.dynamic = true 
     circleNode.physicsBody?.affectedByGravity = false 
     if motionManager.accelerometerAvailable { 
      motionManager.accelerometerUpdateInterval = 0.1 
      motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { (data, error) -> Void in 
       self.destX = self.circleNode.position.x + CGFloat(data!.acceleration.x*100) 
       self.destY = self.circleNode.position.y + CGFloat(data!.acceleration.y*200) 
      }) 
     } 
     self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
     self.physicsBody!.dynamic = true 
     self.physicsBody!.affectedByGravity = false 
     self.physicsBody!.categoryBitMask = Collision.wall.rawValue 
     self.physicsBody!.collisionBitMask = Collision.ball.rawValue 
    } 

    override func update(currentTime: NSTimeInterval) { 
     let destXAction = SKAction.moveToX(destX, duration: 0.1) 
     let destYAction = SKAction.moveToY(destY, duration: 0.1) 
     self.circleNode.runAction(destXAction) 
     self.circleNode.runAction(destYAction) 
    } 
} 

任何想法,我可能會出錯?

回答

1

我會假設的主要問題是遊戲場景從未實際獲得其大小設置。

在您的GameViewController中添加scene.size = skView.bounds.sizelet skView = self.view as! SKView

這將正確設置場景的大小,所以現在你的球應該與你的屏幕邊緣碰撞....但是,當你設置你的circleNode路徑,你實現它的方式與你的圈子的一半大小屏幕。

如果您希望您的圈子出現在屏幕中間,則更好的解決方案是使用circleNode = SKShapeNode(circleOfRadius: 20)而不是circleNode.path = UIBezierPath(arcCenter: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), radius: 20, startAngle: 0, endAngle: CGFloat(2*M_PI), clockwise: true).CGPath。然後將其設置在circleNode.position = CGPointMake(frame.width/2, frame.height/2)的中心。

這應該可以解決整個問題,但是您可能會注意到,球可能會從屏幕邊緣消失。爲了解決這個問題,你的更新方法更改爲類似這樣

func clamp(value: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat { 
    if value > max { 
     return max 
    } 
    if value < min { 
     return min 
    } 
    return value 
} 


override func update(currentTime: NSTimeInterval) { 
    let ballRadius: CGFloat = 10 
    destX = clamp(destX, min: ballRadius, max: frame.width - ballRadius) 
    destY = clamp(destY, min: ballRadius, max: frame.height - ballRadius) 

    let destXAction = SKAction.moveToX(destX, duration: 0.1) 
    let destYAction = SKAction.moveToY(destY, duration: 0.1) 
    self.circleNode.runAction(destXAction) 
    self.circleNode.runAction(destYAction) 
} 

這將使使球不應該嘗試將屏幕的範圍之外去了。我還建議加入circleNode.physicsBody?.usesPreciseCollisionDetection = true,這樣你的碰撞就會更加準確。