将物理实体保存在SKScene的中间?

时间:2015-09-23 14:36:22

标签: ios swift sprite-kit

我不确定如何提出这个问题,但我的SKScene中有一个SKSpriteNode。我希望它位于y轴的中间,但是在滑动(向上/向下)以使重力影响它直到它返回到y轴的中间。

示例设置:
1- SKSpriteNode处于默认位置(在x轴上的位置并不重要,但在y轴的中间) 2-用户向上滑动
3- SKSpriteNode受+ {OR} -y方向的applyImpulse()影响 4-重力在-y OR + y(分别)方向上影响SKSpriteNote 5- SKSpriteNode移回其默认位置(由于重力)

我将如何执行此操作?
我尝试过的事情:
- radialGravityField(没有像我预期的那样表现)
- linearGravityFieldWithVector(我有点失败了)
- 创建2个具有不同重力的矩形(可悲地失败)
- 检查SKSpriteNode y位置是否为<或者>屏幕中间取决于滑动是向上还是向下,如果是,则重置位置。签入didSimulatePhysics。这不起作用,从我能说的,它会重置位置,但在调试时,即使在重置后SKSpriteNode也不在y轴的中间

如果您需要我的代码,请告诉我,但我正在寻找的是一种执行此操作的方法

谢谢:)

修改

这是我用来检查精灵位置是否为<或者>比y轴的中间

override func didMoveToView(view: SKView) {

//set the players default position
playerDefaultPosition = CGPoint(x: self.size.width * 0.2, y: self.size.height / 2)


//background
backgroundColor = SKColor.whiteColor()

//world physics
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)

//create player
playerNode.position = playerDefaultPosition
playerNode.physicsBody = SKPhysicsBody(rectangleOfSize: playerNode.size)
playerNode.physicsBody?.mass = 300
playerNode.physicsBody?.linearDamping = 0

addChild(playerNode)


}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let yTouch = touches.first?.locationInNode(self).y {
        self.touches.append(yTouch)
        startTime = NSDate()

        }
    }

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let yTouch = touches.first?.locationInNode(self).y {
        self.touches.append(yTouch)

    }
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let yTouch = touches.first?.locationInNode(self).y {
        endTime = NSDate()
        self.touches.append(yTouch)
        if !self.touches.isEmpty {
            let velocity = getVelocity(self.touches, startTime: startTime, endTime: endTime)
            movePlayer(velocity)

        }


    }

func getVelocity(touchArray: [CGFloat], startTime: NSDate, endTime: NSDate) -> CGFloat {
    var v: CGFloat = 0
    if !touchArray.isEmpty {

        //get velocity from v = d/t
        let t = CGFloat(endTime.timeIntervalSinceDate(startTime))
        let d = touchArray.last! - touchArray.first!
        v = d / t
    }

    return v

}

func movePlayer(v: CGFloat) {
    let vector = CGVector(dx: 0.0, dy: v * 30)

    if vector.dy > 0 {
        //player going in +y direction
        swipedUp = true
        self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -10)
    } else {
        //player going in -y direction
        swipedUp = false
        self.physicsWorld.gravity = CGVector(dx: 0.0, dy: 10)
    }

    playerNode.physicsBody?.applyImpulse(vector)


}

override func didSimulatePhysics() {

    if playerNode.position.y < (self.view?.frame.height)! / 2 - 1 && swipedUp || playerNode.position.y > (self.view?.frame.height)! / 2 + 1 && !swipedUp {

        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        playerNode.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 0))
        print("gravity set to 0")
        playerNode.position = playerDefaultPosition

    }

}

经过多次调试后,似乎在设置playerNode.position = playerDefaultPosition之后,下一帧的playerNode.position.y < (self.view?.frame.height)! / 2 - 1 && swipedUp仍为真

编辑2

查看documentation我实现了在帧中调用的每个函数,并在每个函数调用期间检查了位置playerNode.position.y,并且当SKScene模拟使playerNode从中移动的物理时,似乎发生了某些事情它的默认位置是另一个。

3 个答案:

答案 0 :(得分:0)

也许只检查节点的y位置以及节点的y&lt; frame.middleY(或&gt;)关闭该节点的重力。滑动后打开。

答案 1 :(得分:0)

尝试在Y方向上将脉冲矢量设置回0

override func update(currentTime: NSTimeInterval) {

    if playerNode.position.y < (self.view?.frame.height)! / 2 - 1 && swipedUp || playerNode.position.y > (self.view?.frame.height)! / 2 + 1 && !swipedUp {

        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        print("gravity set to 0")
        let vector = CGVector(dx: 0.0, dy: 0.0)
        playerNode.physicsBody?.applyImpulse(vector)
        playerNode.position = playerDefaultPosition


    }

}

答案 2 :(得分:0)

@Steve在applyImpulse()中对didSimulatePhysics()说话时走在了正确的轨道上。由于物体仍然有作用力(由于它掉落),我不得不将其移除 你可以通过找到它已经下降的力量来做到这一点(这比我需要的代码多得多)或者我可以让它.dynamic = false并在我需要它时重新启用它。

这就是我现在所拥有的:

override func didFinishUpdate() {
    print(playerNode.position.y)
    if playerNode.position.y < (self.view?.frame.height)! / 2 - 10 && swipedUp || playerNode.position.y > (self.view?.frame.height)! / 2 + 10 && !swipedUp {
        //turn off all forces on the Node    
        playerNode.physicsBody?.dynamic = false
        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        playerNode.position = playerDefaultPosition
    }

}