如何给精灵准确的触摸位置?

How to give to sprite exact touch place?

我的问题是

当我触摸黑色箭头区域时,我仍然触摸整个画面,但是当我只触摸红色区域时,我只想触摸并有动作。 我试图给 spriteNode 命名 plane = childNode(withName: "play") 但它 take/touch 所有图像帧不仅是 alphaBody.

red and black areas

我在 google 上进行了一些搜索,但没有得到肯定的结果。

非常感谢。

It seems like SpriteKit 中未包含您想要的行为,因此您必须自己实现。

引自上文link:

You will have to find out the locationInNode(spriteNode) of the UITouch object object to get the coordinates within the sprite and then read the alpha value from the sprite Image (not trivial) or precompute bitmasks (ones and zeros) from your images and read the value at the corresponding point in the bitmask for the sprite

因此您需要将图像加载为 UIImage 或 CGImage,并检查发生触摸的像素处的颜色是否透明。您可以在这个问题中找到有关如何执行此操作的更多信息:How to get pixel color from SKSpriteNode or from SKTexture?

一个非常简单的解决方案可能是在您的飞机上放置命中测试区域 object(为了示例,我将它们留得稍微有点红,但您可以将它们设为透明)。我在编辑器中创建了我的平面 class 并将其作为参考拖到我的场景中,但您也可以轻松地从头开始对命中区域进行编程。

然后在您的平面中 class 将它们添加到平面中并检测平面内的触摸 class 本身。这并不准确,但与您的图片中的 alpha 追踪相距不远。

此方法的一个好处是您可以将此触摸隔离到平面区域。一些用途可能是...

  • 触摸left/right机翼转向那个方向
  • 触摸body加油
  • 触摸翅膀换枪

这是我在 Plane 中使用的代码 class

class Plane: SKSpriteNode {

    private var background: SKSpriteNode!
    private var wingsHitTest: SKSpriteNode!
    private var bodyHitTest: SKSpriteNode!
    private var smallWingsHitTest: SKSpriteNode!

    init() {

        super.init(texture: nil, color: .clear, size: CGSize.zero)
    }

    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)
        setup()
    }

    func setup() {

        isUserInteractionEnabled = true
        self.color = .clear

        if let background = self.childNode(withName: "//background") as? SKSpriteNode {
            self.background = background
        }

        if let wingsHitTest = self.childNode(withName: "//wingsHitTest") as? SKSpriteNode {
            self.wingsHitTest = wingsHitTest
        }

        if let bodyHitTest = self.childNode(withName: "//bodyHitTest") as? SKSpriteNode {
            self.bodyHitTest = bodyHitTest
        }

        if let smallWingsHitTest = self.childNode(withName: "//smallWingsHitTest") as? SKSpriteNode {
            self.smallWingsHitTest = smallWingsHitTest
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        if let touch = touches.first as UITouch? {

            let touchLocation = touch.location(in: self)

            if wingsHitTest.contains(touchLocation) {
                print("hit in the wings")
            }
            else if smallWingsHitTest.contains(touchLocation) {
                print("hit in the back wings")
            }
            else if bodyHitTest.contains(touchLocation) {
                print("hit in the body")
            }
        }
    }
}