识别SceneKit场景中先前标记的对象

时间:2015-01-10 15:01:29

标签: ios swift scenekit

这是一个3 x 5球体网格的场景套件项目。您可以通过点击它来移动蓝色球体,然后点击橙色球体,它将移动到该位置。问题是我不知道如何识别被标记为移动的球体。我只能将Blue1或Blue 2标记为可移动的球体。这是iOS模拟器和.dae文件的组成。将橙色球体视为空白区域。enter image description here

此外,这是代码:

import SceneKit

class GameViewController: UIViewController {

enum Type { case Orange;  case Blue }
struct BoardLoc { var x: Int;   var y: Int }
var selectedLoc: BoardLoc?
var board: Array<Array<Type>> = []

override func viewDidLoad() { super.viewDidLoad()

    // add a scene
    let scene = SCNScene(named: "art.scnassets/balls10.dae")
    let scnView = view as SCNView
    scnView.scene = scene
    scnView.autoenablesDefaultLighting = true

    // add a tapper
    let gestures = NSMutableArray()
    let tapper = UITapGestureRecognizer(target: self, action: "handleTap:")
    gestures.addObject(tapper)
    scnView.gestureRecognizers = gestures

    // add a 3 by 5 array, a board with most spaces empty except for 2 places
    for x in 0...2 {
        board.append(Array(count:5, repeatedValue:Type.Orange))
        for y in 0...4 {
            if x == 2 && y == 0 || x == 2 && y == 3 {
                board[x][y] = Type.Blue
            }
            else {
                board[x][y] = Type.Orange
            }
        }
    }
}

// handle tap
func handleTap(gesture: UIGestureRecognizer) {
    let scnView = view as SCNView
    let point = gesture.locationInView(scnView)
    if let hitResults = scnView.hitTest(point, options: nil) {
        if hitResults.count > 0 {
            let result: AnyObject! = hitResults[0]
            let tapLoc = BoardLoc(x: Int(point.x) / 106, y: Int(point.y) / 113)

            // if tapLoc blue, selectedLoc set as tapLoc
            if board[tapLoc.x][tapLoc.y] == Type.Blue {
                selectedLoc = tapLoc
            }

            // if tapLoc orange and selectedLoc not nil
            if board[tapLoc.x][tapLoc.y] == Type.Orange && selectedLoc != nil {

                // here is where I fail by just marking Blue1 for movement
                let ball = scnView.scene!.rootNode.childNodeWithName("Blue1", recursively: true)

                // placement of ball according to 3 by 5 grid
                let locX = Float(tapLoc.x) * 16.4 + 0.75
                let locY = Float(tapLoc.y) * -16.4 - 1.25

                let moveToTapLoc = SCNAction.moveTo(SCNVector3(x: locX, y: locY, z: 5), duration: 0.01)
                ball!.runAction(moveToTapLoc)

                // update array
                board[tapLoc.x][tapLoc.y] = Type.Blue
                board[selectedLoc!.x][selectedLoc!.y] = Type.Orange

                // set selectedLoc back to nil
                selectedLoc = nil
            }
        }
    }
}
}

如何标记要移动的球体?

我试过了:

            if board[tapLoc.x][tapLoc.y] == Type.Blue {
                selectedLoc = tapLoc
                var ball = !result.node!.name!.hasPrefix("Blue")
            }

            // if tapLoc orange and selectedLoc not nil
            if board[tapLoc.x][tapLoc.y] == Type.Orange && selectedLoc != nil {


                // placement of ball according to 3 by 5 grid
                let locX = Float(tapLoc.x) * 16.4 + 0.75
                let locY = Float(tapLoc.y) * -16.4 - 1.25

                let moveToTapLoc = SCNAction.moveTo(SCNVector3(x: locX, y: locY, z: 5), duration: 0.01)
                ball!.runAction(moveToTapLoc)

                // update array
                board[tapLoc.x][tapLoc.y] = Type.Blue
                board[selectedLoc!.x][selectedLoc!.y] = Type.Orange

                // set selectedLoc back to nil
                selectedLoc = nil
            }

当球!.runAction错误发生时:使用未解析的标识符'ball'

也许在viewDidLoad用于标记为移动的球之前添加变量,但我不知道什么类型或如何标记变量。

1 个答案:

答案 0 :(得分:0)

所以一种方法是将selectedLoc更改为selectedLocBlue1并添加一个类似的变量selectedLocBlue2。然后,而不是handleTap函数中的2个if语句,使用4个if语句,2个用于selectedLocBlue1,2个用于selectedLocBlue2。同时更改数组以反映有2种不同类型的蓝色,更改枚举有3种类型,橙色,蓝色1,蓝色2。我确信这是一种倒退的方式,所以请批评。感谢。