检测 Sprite 纹理内的触摸而不是整个帧 iOS Swift SpriteKit?
Detect touch within Sprite texture and not the entire frame iOS Swift SpriteKit?
我现在正在使用 SpriteKit,我遇到了一个看似简单但在互联网上找不到任何东西的问题。我有三个形状像平行四边形的按钮,它们堆叠在一起,看起来像这样:
Screenshot of buttons
let button = SKSpriteNode(imageNamed: "playbutton")
let leaderButton = SKSpriteNode(imageNamed: "leaderbutton")
let homeButton = SKSpriteNode(imageNamed: "homebutton")
button.position = CGPoint(x: size.width/2, y: size.height/2)
addChild(button)
leaderButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height/2)
addChild(leaderButton)
homeButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height)
addChild(homeButton)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if button.containsPoint(location) {
button.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
else if leaderButton.containsPoint(location) {
leaderButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
else if homeButton.containsPoint(location) {
homeButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
}
}
这就是我检测触摸的方式。问题是它们重叠,因为精灵实际上是一个矩形,所以当我尝试点击第二个按钮的左上角时,顶部按钮会检测到它。我想知道有一种方法可以只在纹理中检测触摸,比如如何将物理体设置为纹理。
感谢您能给我的任何帮助!
Link 现在有效。
所以我尝试了这个:
button.position = CGPoint(x: size.width/2, y: size.height/2)
button.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "playbutton"), size: button.size)
button.physicsBody?.dynamic = false
addChild(button)
leaderButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height/2)
leaderButton.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "leaderbutton"), size: leaderButton.size)
leaderButton.physicsBody?.dynamic = false
addChild(leaderButton)
homeButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height)
homeButton.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "homebutton"), size: homeButton.size)
homeButton.physicsBody?.dynamic = false
addChild(homeButton)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if physicsWorld.bodyAtPoint(location)?.node == button {
button.runAction(SKAction.scaleTo(0.8, duration: 0.1))
print("play")
}
if physicsWorld.bodyAtPoint(location)?.node == leaderButton {
leaderButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
print("leader")
}
if physicsWorld.bodyAtPoint(location)?.node == homeButton {
homeButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
}
}
它仍然记录了完整的帧,而不仅仅是物理体。查看 link 查看按钮及其坐标如何相交。
如果您将物理体附加到每个按钮,您可以检测到您的触摸落在哪个物理体上。
您可以使用 SKPhysicsBody(texture:size:)
或 SKPhysicsBody(texture:alphaThreshold:size:)
从按钮的纹理(假设按钮是 SKSpriteNode
)生成物理体,或者您可以创建 CGPath
描述按钮的形状并使用 SKPhysicsBody(polygonFromPath:)
。将正文分配给按钮的 physicsBody
属性。假设您实际上不希望物理模拟器移动您的按钮,请将每个物体的 dynamic
属性 设置为 false
.
然后你可以使用 physicsWorld.bodyAtPoint(_:)
来获得触摸落在的物体之一(其中 physicsWorld
是你的 SKScene
的 属性)。使用正文的 node
属性 返回到按钮节点。如果物体重叠,bodyAtPoint
returns 任意物体。
如果您需要触摸所触及的所有物体,您可以使用 physicsWorld.enumerateBodiesAtPoint(_:usingBlock:)
。
一个完全不同的方法,如果你能创建一个描述按钮形状的CGPath
,就是使用SKScene.convertPointFromView(_:)
然后SKNode.convertPoint(_:fromNode:_)
将点转换成按钮的坐标系,然后使用CGPathContainsPoint
(全局函数)检测该点是否在描述按钮形状的路径中。
(我看不到你的头像 link,但我想我很清楚你在描述什么。)
有 some discussions on how to read the alpha value of out an SKTexture,但仅 "did I touch a parallelogram" 就需要相当多的开销?特别是如果您为按钮添加 alpha 效果。
您可以在位置上执行任何您想要的逻辑 - 您有一个包含位置的 CGPoint,并且您知道按钮的大小和形状。
编写一个函数来测试一个点是否在平行四边形按钮内应该非常简单。由于平行四边形基本上是在 "inner" 矩形的两端都有三角形的矩形,如果您知道 "inner" 矩形的大小,您可以很容易地确定触摸是否在您想要的位置:
检查它是否位于整个按钮的右侧。如果不是,你知道它不在平行四边形中。
检查它是否在 "inner" 矩形内 - 平行四边形的一部分,三角形 "chopped off" 结束。如果是,那么你知道它在平行四边形中。
检查它是否在其中一个三角形内。你知道触摸在包含三角形的矩形中有多远和多远,并且你知道划分该矩形以根据其宽度和高度形成三角形的线的斜率。这使得检查该点是否在三角形中变得微不足道 - 只需对一条线使用 "y=mx+b" 公式,其中 m 是斜率,b 是您需要添加以使该线通过矩形的一角(通常是您的 "y intercept")。如果 y 坐标小于 than/greater 小于 m*(x 坐标)+ b,您可以确定触摸是在该三角形内部还是外部。
一旦你有了那个函数,你就可以用它作为检查每个按钮的测试。
我现在正在使用 SpriteKit,我遇到了一个看似简单但在互联网上找不到任何东西的问题。我有三个形状像平行四边形的按钮,它们堆叠在一起,看起来像这样: Screenshot of buttons
let button = SKSpriteNode(imageNamed: "playbutton")
let leaderButton = SKSpriteNode(imageNamed: "leaderbutton")
let homeButton = SKSpriteNode(imageNamed: "homebutton")
button.position = CGPoint(x: size.width/2, y: size.height/2)
addChild(button)
leaderButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height/2)
addChild(leaderButton)
homeButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height)
addChild(homeButton)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if button.containsPoint(location) {
button.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
else if leaderButton.containsPoint(location) {
leaderButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
else if homeButton.containsPoint(location) {
homeButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
}
}
这就是我检测触摸的方式。问题是它们重叠,因为精灵实际上是一个矩形,所以当我尝试点击第二个按钮的左上角时,顶部按钮会检测到它。我想知道有一种方法可以只在纹理中检测触摸,比如如何将物理体设置为纹理。 感谢您能给我的任何帮助!
Link 现在有效。
所以我尝试了这个:
button.position = CGPoint(x: size.width/2, y: size.height/2)
button.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "playbutton"), size: button.size)
button.physicsBody?.dynamic = false
addChild(button)
leaderButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height/2)
leaderButton.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "leaderbutton"), size: leaderButton.size)
leaderButton.physicsBody?.dynamic = false
addChild(leaderButton)
homeButton.position = CGPoint(x: size.width/2, y: size.height/2 - button.size.height)
homeButton.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "homebutton"), size: homeButton.size)
homeButton.physicsBody?.dynamic = false
addChild(homeButton)
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if physicsWorld.bodyAtPoint(location)?.node == button {
button.runAction(SKAction.scaleTo(0.8, duration: 0.1))
print("play")
}
if physicsWorld.bodyAtPoint(location)?.node == leaderButton {
leaderButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
print("leader")
}
if physicsWorld.bodyAtPoint(location)?.node == homeButton {
homeButton.runAction(SKAction.scaleTo(0.8, duration: 0.1))
}
}
}
它仍然记录了完整的帧,而不仅仅是物理体。查看 link 查看按钮及其坐标如何相交。
如果您将物理体附加到每个按钮,您可以检测到您的触摸落在哪个物理体上。
您可以使用 SKPhysicsBody(texture:size:)
或 SKPhysicsBody(texture:alphaThreshold:size:)
从按钮的纹理(假设按钮是 SKSpriteNode
)生成物理体,或者您可以创建 CGPath
描述按钮的形状并使用 SKPhysicsBody(polygonFromPath:)
。将正文分配给按钮的 physicsBody
属性。假设您实际上不希望物理模拟器移动您的按钮,请将每个物体的 dynamic
属性 设置为 false
.
然后你可以使用 physicsWorld.bodyAtPoint(_:)
来获得触摸落在的物体之一(其中 physicsWorld
是你的 SKScene
的 属性)。使用正文的 node
属性 返回到按钮节点。如果物体重叠,bodyAtPoint
returns 任意物体。
如果您需要触摸所触及的所有物体,您可以使用 physicsWorld.enumerateBodiesAtPoint(_:usingBlock:)
。
一个完全不同的方法,如果你能创建一个描述按钮形状的CGPath
,就是使用SKScene.convertPointFromView(_:)
然后SKNode.convertPoint(_:fromNode:_)
将点转换成按钮的坐标系,然后使用CGPathContainsPoint
(全局函数)检测该点是否在描述按钮形状的路径中。
(我看不到你的头像 link,但我想我很清楚你在描述什么。)
有 some discussions on how to read the alpha value of out an SKTexture,但仅 "did I touch a parallelogram" 就需要相当多的开销?特别是如果您为按钮添加 alpha 效果。
您可以在位置上执行任何您想要的逻辑 - 您有一个包含位置的 CGPoint,并且您知道按钮的大小和形状。
编写一个函数来测试一个点是否在平行四边形按钮内应该非常简单。由于平行四边形基本上是在 "inner" 矩形的两端都有三角形的矩形,如果您知道 "inner" 矩形的大小,您可以很容易地确定触摸是否在您想要的位置:
检查它是否位于整个按钮的右侧。如果不是,你知道它不在平行四边形中。
检查它是否在 "inner" 矩形内 - 平行四边形的一部分,三角形 "chopped off" 结束。如果是,那么你知道它在平行四边形中。
检查它是否在其中一个三角形内。你知道触摸在包含三角形的矩形中有多远和多远,并且你知道划分该矩形以根据其宽度和高度形成三角形的线的斜率。这使得检查该点是否在三角形中变得微不足道 - 只需对一条线使用 "y=mx+b" 公式,其中 m 是斜率,b 是您需要添加以使该线通过矩形的一角(通常是您的 "y intercept")。如果 y 坐标小于 than/greater 小于 m*(x 坐标)+ b,您可以确定触摸是在该三角形内部还是外部。
一旦你有了那个函数,你就可以用它作为检查每个按钮的测试。