SKNode遵循SKConstraint范围内的另一个SKNode

时间:2016-11-28 18:19:19

标签: ios swift sprite-kit

我试图用SpriteKit模拟眼睛。

当用户的手指在屏幕上移动时,眼睛的瞳孔会跟踪用户的手指,但必须保持在眼睛的范围内。

我试图通过使用SKConstraint来解决这个问题。

修改

我的想法是将SKConstraints应用于学生以限制其对眼睛的界限。任何触摸(即touchesMoved()等)都将以SKAction.moveTo()的形式应用于瞳孔, SpriteKit处理将瞳孔保持在眼睛范围内。

let touchPoint = CGPoint()
SKAction.moveTo( touchPoint, duration: 2)

视频代码可用:https://gist.github.com/anonymous/f2356e07d1ac0e67c25b1940662d72cb

Eyeball video demo

一张图片胜过千言万语......

想象一下,瞳孔是一个白色的小圆圈。蓝色框模拟用户在屏幕上移动手指。

理想情况下,瞳孔跟随屏幕周围的蓝色框,并遵循黄色圆圈定义的路径。

iOS 10 |斯威夫特3 | Xcode 8

2 个答案:

答案 0 :(得分:4)

您可以使用方向约束来旋转节点以面向触摸位置,而不是按距离进行约束。通过添加" pupil"对于受约束的节点具有x偏移的节点,瞳孔将朝向触摸点移动。以下是如何执行此操作的示例:

let follow = SKSpriteNode(color:.blue, size:CGSize(width:10,height:10))
let pupil = SKShapeNode(circleOfRadius: 10)
let container = SKNode()
let maxDistance:CGFloat = 25

override func didMove(to view: SKView) {
    addChild(container)
    // Add the pupil at an offset
    pupil.position = CGPoint(x: maxDistance, y: 0)
    container.addChild(pupil)

    // Node that shows the touch point
    addChild(follow)

    // Add an orientation constraint to the container
    let range = SKRange(constantValue: 0)        
    let constraint = SKConstraint.orient(to: follow, offset: range)
    container.constraints = [constraint]
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches {
        let location = t.location(in: self)
        follow.position = location
        adjustPupil(location: location)
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches {
        let location = t.location(in: self)
        follow.position = location
        adjustPupil(location: location)
    }
 }

// Adjust the position of the pupil within the iris
func adjustPupil(location:CGPoint) {
    let dx = location.x - container.position.x
    let dy = location.y - container.position.y
    let distance = sqrt(dx*dx + dy*dy)
    let x = min(distance, maxDistance)
    pupil.position = CGPoint(x:x, y:0)
}

enter image description here

答案 1 :(得分:0)

我想在发布答案之前等待回复,但@ 0x141E和我讨论了约束如何工作,所以这里是代码。用它来找出你出错的地方。

import SpriteKit


class GameScene: SKScene {
    static let pupilRadius : CGFloat = 30
    static let eyeRadius : CGFloat = 100

    let follow = SKSpriteNode(color:.blue, size:CGSize(width:10,height:10))
    let pupil = SKShapeNode(circleOfRadius: pupilRadius)

    override func didMove(to view: SKView) {
        let eye = SKShapeNode(circleOfRadius: GameScene.eyeRadius)
        eye.strokeColor = .white
        eye.fillColor = .white
        addChild(eye)

        pupil.position = CGPoint(x: 0, y: 0)
        pupil.fillColor = .blue
        eye.addChild(pupil)

        addChild(follow)

        pupil.constraints = [SKConstraint.distance(SKRange(lowerLimit: 0, upperLimit: GameScene.eyeRadius-GameScene.pupilRadius), to: eye)]

    }

    func moveFollowerAndPupil(_ location:CGPoint){
        follow.position = location
        pupil.position = convert(location, to: pupil.parent!)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        touches.forEach({moveFollowerAndPupil($0.location(in: self))})
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        touches.forEach({moveFollowerAndPupil($0.location(in: self))})
    }
}

正如你所看到的,在我的结尾没有使用平方根,希望Apple足够聪明,不要使用它,因为它不需要,这意味着理论上这应该比手动做距离公式更快。<​​/ p >

enter image description here