gpt4 book ai didi

swift - 如何让 touch.locationInNode() 识别节点和它的子节点之间的区别?

转载 作者:搜寻专家 更新时间:2023-11-01 06:22:30 26 4
gpt4 key购买 nike

我首先声明了两个 SKSpriteNodes,handle 和 blade,然后将 handle 添加为 self 的子节点,将 blade 添加为 handle 的子节点

var handle = SKSpriteNode(imageNamed: "Handle.png")
var blade = SKSpriteNode(imageNamed: "Blade.png")

override func didMoveToView(view: SKView) {

handle.position = CGPointMake(self.size.width / 2, self.size.height / 14)
blade.position = CGPointMake(0, 124)

self.addChild(Handle)
Handle.addChild(Blade)
}

当我点击 handle 时,它会打印到控制台“Handle was clicked”,但是当我点击 Blade 时,它​​也会打印“Handle was clicked”。可以清楚地认识到 Blade 是句柄的子项,但是当我点击 Blade 时,我该如何做到这一点,它打印出“ Blade 被点击”?

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
if (Handle.containsPoint(location)){
NSLog("Handle was clicked")
}
else if (Blade.containsPoint(location)){
NSLog("Blade was clicked")
}

}
}

最佳答案

确定用户是触摸了剑柄还是 Blade 非常简单,但有一些注意事项。以下假设 1. 当 zRotation = 0 时,剑图像面向右侧, 2. anchorPoint剑的值为 (0, 0.5),并且 3. 剑( Blade 和 handle )是单个 Sprite 节点。当您将一个 Sprite 添加到另一个 Sprite 时,父级帧的大小会扩展以包含子节点。这就是你测试 Handle.containsPoint 的原因无论你点击剑的哪个位置都是如此。

下图显示了一个带有深灰色 handle (左侧)和浅灰色 Blade 的剑 Sprite 。剑周围的黑色矩形代表 Sprite 的框架,圆圈代表用户触摸的位置。标记为 a 的线的长度是接触点到剑底的距离。我们可以测试这个距离,看看用户是否触摸了 handle (如果是 a <= handleLength )或 Blade (如果是 a > handleLength )。当zRotation = 0 , a = x所以测试是x <= handleLength ,剑的底部是x = 0 .

enter image description here

在下图中,剑旋转了 90 度(即 zRotation = M_PI_2 )。同样,如果 a <= handleLength ,用户触摸 handle ,否则用户触摸 Blade 。唯一的区别是 a现在是 y值而不是 x由于剑的旋转。在这两种情况下,都可以使用框架的边界框来检测用户是否触摸了剑。

enter image description here

然而,当 Sprite 旋转 45 度时,它的框架会自动扩展以包围 Sprite ,如下图中的黑色矩形所示。因此,当用户触摸矩形中的任何地方时,测试 if sprite.frame.contains(location)将是真实的。这可能导致用户在触摸位置离剑相对较远时(即,当距离 b 较大时)拿起剑。如果我们希望最大触摸距离在所有旋转角度上都相同,则需要进行额外的测试。

enter image description here

好消息是 Sprite Kit 提供了一种从一个坐标系转换到另一个坐标系的方法。在这种情况下,我们需要从场景坐标转换为剑坐标。这极大地简化了问题,因为它还将点旋转到新的坐标系。从场景坐标转换为剑坐标后,转换后的触摸位置的xy值与距离相同 ab在所有旋转角度!现在我们知道ab ,我们可以确定触摸距离剑有多近,以及用户是触摸了 handle 还是 Blade 。

从上面,我们可以实现如下代码:

    let location = touch.locationInNode(self)
// Check if the user touched inside of the sword's frame (see Figure 1-3)
if (sword.frame.contains(location)) {
// Convert the touch location from scene to sword coordinates
let point = sword.convertPoint(location, fromNode: self)
// Check if the user touched any part of the sword. Note that a = point.x and b = point.y
if (fabs(point.y) < sword.size.height/2 + touchTolerance) {
// Check if the user touched the handle
if (point.x <= handleLength) {
println("touched handle")
}
else {
println("touched blade")
}
}
}

关于swift - 如何让 touch.locationInNode() 识别节点和它的子节点之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31373066/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com