nodeAtPoint 错误的节点

Posted

技术标签:

【中文标题】nodeAtPoint 错误的节点【英文标题】:nodeAtPoint wrong node 【发布时间】:2015-07-07 07:26:36 【问题描述】:

我正在使用 swift 和 spritekit 制作游戏,并且我有一个功能,可以让多个精灵从屏幕顶部落下。我也这样做了,这样我就可以使用 nodeAtPoint 检测精灵上的触摸,并可以轻弹精灵。我的问题是,由于 nodeAtPoint 拖动树中最深的节点,当我单击并拖动精灵时,场景中的最新精灵被拉向我的触摸,而不是我最初触摸的那个。如果有人对如何仅影响我接触的节点有一些建议,我将不胜感激。

    class GameScene: SKScene 

    var ball = SKSpriteNode(imagedNamed: "blueBlue")

    var touchedNode: SKNode? = SKNode()

     override func didMoveToView(view: SKView) 

       var create = SKAction.runBlock(() in self.createTargets())
            var wait = SKAction.waitForDuration(2)
            var waitAndCreateForever = SKAction.repeatActionForever(SKAction.sequence([create, wait]))
            self.runAction(waitAndCreateForever)
    


        func createTargets() 
             ball = SKSpriteNode(imageNamed: "blueBlue")
             let randomx = Int(arc4random_uniform(170) + 290)
             ball.zPosition = 0
            ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width / 11)

            ball.physicsBody?.dynamic = true
            ball.size = CGSize(width: ball.size.width / 1.5, height: ball.size.height / 1.5)
            let random = Int(arc4random_uniform(35))

            let textures = [texture1, texture2, texture3, texture4, texture5, texture6, texture7, texture8, texture9, texture10, texture11, texture12, texture13, texture14, texture15, texture16, texture17, texture18, texture19, texture20, texture21, texture22, texture23, texture24, texture25, texture1, texture7, texture18, texture24, texture25, texture1, texture7, texture18, texture24, texture25]

            ball.texture = textures[random] 
            ball.position = CGPoint(x: randomx, y: 1400) 
            addChild(ball)
    
        override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
            let touch = touches.first as! UITouch
            let touchLocation = touch.locationInNode(self)
           touchedNode = self.nodeAtPoint(touchLocation)
            if touchedNode.frame.contains(touchLocation) 
            touching = true
            touchPoint = touchLocation
            
       

        override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) 
            let touch = touches.first as! UITouch
            let touchLocation = touch.locationInNode(self)
            touching = true
            touchPoint = touchLocation

        
     override func update(currentTime: NSTimeInterval) 

            if touching 

                if touchPoint != touchedNode.position 

                    let dt: CGFloat = 0.1

                    let distance = CGVector(dx: touchPoint.x - touchedNode.position.x, dy: touchPoint.y - touchedNode.position.y)

                    let vel = CGVector(dx: distance.dx / dt, dy: distance.dy / dt)

                    if touchedNode.parent != nil 

                    touchedNode.physicsBody?.velocity = vel

                    
             
              
        
    

【问题讨论】:

不确定这是否对您有帮助,但请看这里:***.com/a/28259980/2158465 @EpicByte 看起来 OP 的代码是基于您的帖子。我发现有趣的是代码设置了移动物理体的速度,而不是使用力或冲量 是的,我从其他人那里得到了代码,他可能是从你的帖子中得到的。 @0x141E 我总是选择直接设置速度而不是通过 applyImpulse/force 方法间接设置速度,特别是如果我正在执行自定义实时计算,例如移动到一个点,模拟浮力, ETC;它也稍微快一点,让我可以完全控制计算。只有当我不自己进行计算时,我才会施加冲动和力量。例如,也许我想在某个点施加一个脉冲,或者我想考虑物理体的质量等。在这些情况下,我只是让物理引擎为我确定速度。 @DanielMihaila 您的问题解决了吗?还是有问题? 【参考方案1】:

我建议您对代码进行以下更改:

    添加检查精灵是否已被移动(如果是,则不执行任何操作) 关闭正在移动的精灵的affectedByGravity 属性 触摸结束时重置 touchedNodetouching 变量

这是一个具有上述更改的实现...

touchesBegantouchesMoved 替换为以下内容

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
    let touch = touches.first as! UITouch
    let touchLocation = touch.locationInNode(self)
    if (!touching) 
        let node = self.nodeAtPoint(touchLocation)
        if node is SKSpriteNode 
            touchedNode = node
            touching = true
            touchPoint = touchLocation
            touchedNode!.physicsBody?.affectedByGravity = false
        
    


override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) 
    if (touching) 
        let touch = touches.first as! UITouch
        let touchLocation = touch.locationInNode(self)
        touchPoint = touchLocation
    

并添加此方法

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) 
    if (touchedNode != nil) 
        touchedNode!.physicsBody!.affectedByGravity = true
    
    touchedNode = nil
    touching = false

【讨论】:

您好,谢谢您的建议。我使用了您的代码,不幸的是我仍然遇到同样的问题。不过我确实注意到,如果我让节点下降一点点,我可以成功拖动我单击的节点。也许这可以帮助我尝试做什么? 我没有遇到您所描述的问题,而且我看不出代码是如何发生的。当精灵从屏幕顶部落下时,我可以正确选择并拖动它们。 好吧,我没有发布我的完整代码,所以我的代码中可能有其他东西干扰了它。无论如何都很好,因为我将游戏更改为不需要拖动这些节点。再次感谢

以上是关于nodeAtPoint 错误的节点的主要内容,如果未能解决你的问题,请参考以下文章

移动父 SKNode 后,Sprite 工具包找不到 nodeAtPoint

分配节点ID失败,错误:'错误:无法分配节点ID

Kubernetes 中工作节点上的连接被拒绝错误

节点包和节点 sass 中的错误

解析序列/映射节点时出现无效的 yaml 节点错误

使用 datastax 进行错误的 SOlr 索引。从 1 个节点扩展到 2 个 cassandra 节点和 1 个搜索节点