【问题标题】:How to drag and flick a node in SpriteKit while gravity is present?存在重力时如何在 SpriteKit 中拖动和轻弹节点?
【发布时间】:2021-07-03 19:48:12
【问题描述】:

使用我当前的代码,该节点非常滞后,并且在其轻弹时出于某种原因在随机方向上移动或传送。我该如何解决这个问题,也有人可以解释为什么它会传送并移动到场景中的随机位置。

另外,是否允许仅在从其位置拖动节点时才移动节点,而不是始终位于手势识别器的坐标处?


    override func didMove(to view: SKView) {
    let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.pan(_:)))
    

    view.addGestureRecognizer(gestureRecognizer)
    circleNode.physicsBody = SKPhysicsBody(circleOfRadius: 20)
    self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
    self.addChild(circleNode)
}


@objc func pan(_ recognizer: UIPanGestureRecognizer) {
   

    
    if recognizer.state == .changed {

        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        var location = recognizer.location(in: self.view!)
        location = self.convertPoint(fromView: location)
        
        
        circleNode.position = location
        
        
        
        
    }
    
    if recognizer.state == .ended {
        self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
        let transformerX = 1024/self.view!.frame.size.width
        let transformerY = 768/self.view!.frame.size.height
        let velocity = recognizer.velocity(in: self.view)
        circleNode.physicsBody?.applyForce(CGVector(dx: velocity.x * transformerX, dy: velocity.y * transformerY))



    }
    
    
    
}

   

【问题讨论】:

    标签: ios swift sprite-kit skspritenode skphysicsworld


    【解决方案1】:

    为什么不简单地根据滑动手势向对象施加力,而不是关闭重力,手动移动对象,然后在滑动结束时再次打开重力?

    【讨论】:

    • 如果刚开始设置重力(y:-9.8),球不能被拖动,因为它会在每个位置落下并且不会停留在识别器的坐标上
    【解决方案2】:

    这是我正在玩的一些代码。我可以拖动和轻弹长矛(长矛图像),还可以“弹出”猪头。这就是整个 GameScene。删除不需要的代码。 :)

     import SpriteKit
     import CoreMotion
    
    class GameScene: SKScene, SKPhysicsContactDelegate  {
    
      enum CollisionTypes: UInt32{
        case spear = 1
        case wall = 2
        case head = 4
      }
    
    
      var touchPoint: CGPoint = CGPoint()
      var touching: Bool = false
    
    override func didMove(to view: SKView) {
        self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        //Add contact delegate
        physicsWorld.contactDelegate = self
        self.backgroundColor = .white
        
        self.addChild(spearNode)
        self.addChild(headNode)
    }
    
    
    
    lazy var spearNode: SKSpriteNode = {
        let node = SKSpriteNode(imageNamed: "spear2")
        node.name = "Spear"
        node.physicsBody = SKPhysicsBody(texture: node.texture!,
                                         size: CGSize(width: node.frame.width  , height: node.frame.height))
        node.position = CGPoint(x:self.frame.midX , y:self.frame.midY)
        node.physicsBody?.affectedByGravity = true
        node.physicsBody?.allowsRotation = false
        node.size = CGSize(width: node.frame.width , height: node.frame.height )
        node.physicsBody?.categoryBitMask = CollisionTypes.spear.rawValue
        node.physicsBody?.contactTestBitMask = CollisionTypes.head.rawValue
        node.physicsBody?.collisionBitMask = CollisionTypes.head.rawValue
        return node
    }()
    
    lazy var headNode: SKSpriteNode = {
        let node = SKSpriteNode(imageNamed: "Pig")
        node.name = "Pig"
        node.physicsBody = SKPhysicsBody(texture: node.texture!,
                                         size: CGSize(width: node.frame.width  , height: node.frame.height))
        node.position = CGPoint(x:self.frame.midX , y:self.frame.maxY - 100)
        node.physicsBody?.affectedByGravity = true
        node.physicsBody?.allowsRotation = false
        node.size = CGSize(width: node.frame.width / 2  , height: node.frame.height / 2 )
        node.physicsBody?.categoryBitMask = CollisionTypes.head.rawValue
        return node
        
    }()
    
    func didBegin(_ contact: SKPhysicsContact){
        guard let nodeA = contact.bodyA.node else {return}
        guard let nodeB = contact.bodyB.node else {return}
        
        print("Contacted")
        
        if nodeA.name == "Pig" && nodeB.name == "Spear"{
            nodeA.removeFromParent() 
        }
        
        if nodeA.name == "Spear" && nodeB.name == "Pig"{    
            nodeB.removeFromParent()
        }
    }
    
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first!
        let location = touch.location(in:self)
        
        if spearNode.frame.contains(location) {
            touchPoint = location
            touching = true
        }
    }
    
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first!
        let location = touch.location(in: self)
        touchPoint = location
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        touching = false
    }
    
    
    override func update(_ currentTime: TimeInterval) {
        physicsWorld.gravity = CGVector(dx:0, dy: -9.8)
        
        if touching {
            let dt:CGFloat = 1.0/60.0
            let distance = CGVector(dx: touchPoint.x-spearNode.position.x, dy: touchPoint.y-spearNode.position.y)
            let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
            spearNode.physicsBody!.velocity=velocity
        }
      }
    }
    

    【讨论】:

    • 谢谢!我明天早上试试
    • 我根本无法让它工作。当任何对象被点击时它会崩溃,因为 spearNode.physicsBody 在展开时为零,所以我给它一个明确的身体大小,它现在移动,但它只是随机移动并且不跟随手势。你知道发生了什么吗?
    • 只需将图像分配给 SKSpriteNode(imageNamed: "yourImage")
    • 我分配了一个图像,它没有任何区别
    • 那么你在代码中实际改变了什么?代码在我这边完美运行。
    猜你喜欢
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多