物理速度导致父母与孩子分开

时间:2017-05-18 12:49:43

标签: swift sprite-kit uigesturerecognizer uipangesturerecognizer skphysicsbody

我试图通过在播放器平移视图时以编程方式添加/删除纹理贴图来制作无限滚动地形。只应在具有开放边缘的现有切片旁边添加新切片。为了检测瓷砖是否有开放边缘,我计划附加一个小的物理主体,从瓷砖的所有4个边伸出来充当传感器。如果传感器与任何其他传感器接触,我们就知道瓷砖的边缘没有打开。

我遇到的问题是传感器并不总是与瓷砖保持对齐。为了显示这个问题,我使用下面的代码创建了一个SpriteKit项目。

触摸行为包括GameScene类中的手势识别器,该手势识别器会导致不可见的Handle对象移动。当手势结束时,我使用手柄的物理体在这条线上给它一点速度:

handle.physicsBody?.applyImpulse(CGVector(dx: velocity.x * multiplier, dy: -velocity.y * multiplier))

我还创建了一个Tile对象(下方的大绿色方块)并将其添加为隐形句柄的子项。这很棒,现在我添加的所有子图块都将与其父句柄一起移动。

每当实例化一个图块时,就会创建一个Sensor对象(下方的小红色方块),并将其添加为图块的子图层。这也很棒,现在所有的传感器都会随着它们的父牌一起移动,而父牌又与其父牌即不可见的牌一起移动。只有一个问题......

当我平移屏幕时,绿色瓷砖及其红色传感器(如下所示)将按预期一致地一起移动。当我释放我的平移手势时,我给手柄的额外速度也会延伸到其子平铺,也如预期的那样。但该速度不会影响瓷砖的子传感器。一旦我释放手势,传感器在屏幕上停止死亡,同时瓷砖继续随手柄一起移动,直到它们都缓慢停止。所需的行为是传感器与其父图块一起移动。

这是一个视频链接,可能会显示比我描述的更好的视频: enter image description here

我无法理解为什么瓷砖与其父母的动作保持同步,但传感器没有做同样的事情。感谢您对此问题的任何见解。

https://youtu.be/ccJKdZv-NsM

GameScene.swift:

import SpriteKit

class GameScene: SKScene {
    let handle = Handle()
    let startTile = Tile()

    override func didMove(to view: SKView) {
        self.backgroundColor = .white
        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)

        self.addChild(handle)
        startTile.position.x = handle.anchorPoint.x
        startTile.position.y = handle.anchorPoint.y
        handle.addChild(startTile)

        let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanFrom))
        panGestureRecognizer.cancelsTouchesInView = false
        panGestureRecognizer.delaysTouchesEnded = false
        self.view!.addGestureRecognizer(panGestureRecognizer)
    }

    func handlePanFrom(_ recognizer: UIPanGestureRecognizer) {
        if recognizer.state == .changed {
            var translation = recognizer.translation(in: recognizer.view)
            translation = CGPoint(x: translation.x, y: -translation.y)
            self.panForTranslation(translation)
            recognizer.setTranslation(.zero, in: recognizer.view)
        } else if recognizer.state == .ended {
            let velocity = recognizer.velocity(in: self.view)
            let multiplier = CGFloat(0.5)
            handle.physicsBody?.applyImpulse(CGVector(dx: velocity.x * multiplier, dy: -velocity.y * multiplier))
        }
    }

    func panForTranslation(_ translation: CGPoint) {
        let position = handle.position
        let newPosition = CGPoint(x: position.x + translation.x, y: position.y + translation.y)
        handle.position = newPosition
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        handle.physicsBody?.isResting = true
    }
}

处理课程:

import SpriteKit

class Handle : SKSpriteNode {
    init() {
        super.init(texture: nil, color: .clear, size: CGSize(width: 1, height: 1))
        self.physicsBody = SKPhysicsBody(rectangleOf: self.size)
        self.physicsBody?.mass = 1
        self.physicsBody?.linearDamping = 2
        self.physicsBody?.categoryBitMask = 0
        self.physicsBody?.contactTestBitMask = 0
        self.physicsBody?.collisionBitMask = 0
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

瓷砖类:

import SpriteKit

class Tile : SKSpriteNode {

    init() {
        super.init(texture: nil, color: .green, size: CGSize(width: 300, height: 300))
        let sensorA = Sensor()
        self.addChild(sensorA)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

传感器类:

import SpriteKit

class Sensor : SKSpriteNode {

    init() {
        super.init(texture: nil, color: .red, size: CGSize(width: 50, height: 50))
        self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 50, height: 50))
        self.physicsBody?.categoryBitMask = 0b1
        self.physicsBody?.contactTestBitMask = 0b1
        self.physicsBody?.collisionBitMask = 0
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

更新 Whirlwind提供的接受答案解决了我与孩子从父母分离时遇到的问题。我相信在答案的评论中,问题的原因变得清晰了。

我对它的理解是红色方块没有移动,因为它有自己的物理体,在手柄停止移动后没有接收任何速度。虽然句柄对象(及其子图块)保持移动,因为它确实具有速度。所以听起来像红盒子自己的物理机构正在把它拉回来。

1 个答案:

答案 0 :(得分:2)

我真的没有时间介绍为什么你的代码会做一些事情,但如果你想将另一个物理体与handle的物理体一起移动,那么你可以将它固定到它。

我将修改您的代码以使其正常工作,但您应该自己担心封装。首先在Tile类中创建一个对外界可见的传感器变量,以便稍后在场景中使用它:

class Tile : SKSpriteNode {
    let sensorA = Sensor()
    init() {
        super.init(texture: nil, color: .green, size: CGSize(width: 300, height: 300))

        self.addChild(sensorA)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

然后在你的场景针传感器到手柄:

   let pin = SKPhysicsJointPin.joint(withBodyA: self.startTile.sensorA.physicsBody!, bodyB: self.handle.physicsBody!, anchor: CGPoint.zero)
   startTile.sensorA.physicsBody?.allowsRotation = false
   self.physicsWorld.add(pin)

我想这就是你想要的:

sensor