如何检测是不是已触摸 SKSpriteNode
Posted
技术标签:
【中文标题】如何检测是不是已触摸 SKSpriteNode【英文标题】:How do I detect if an SKSpriteNode has been touched如何检测是否已触摸 SKSpriteNode 【发布时间】:2015-03-11 09:53:38 【问题描述】:我正在尝试检测我的精灵节点是否已被触摸,但我不知道从哪里开始。
let Pineapple = SKSpriteNode(imageNamed: "Pineappleimg")
Pineapple.userInteractionEnabled = true
Pineapple.position = CGPoint(x: CGRectGetMidX(self.frame) - 200, y: CGRectGetMidY(self.frame));
self.addChild(Pineapple)
【问题讨论】:
这个问题可以作为例子:***.com/questions/21840042/… 【参考方案1】:首先将SKSpriteNode
的name
属性设置为字符串。
pineapple.name = "pineapple"
pineapple.userInteractionEnabled = false
然后在touchesBegan
函数中的Scene
override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
let touch:UITouch = touches.anyObject()! as UITouch
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
if name == "pineapple"
print("Touched")
这是一种方法。
您还可以继承 SKSpriteNode
并覆盖其中的 touchesBegan
。
class TouchableSpriteNode : SKSpriteNode
override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
print("touched")
那就做吧
let pineapple = TouchableSpriteNode(imageNamed: "Pineappleimg")
pineapple.userInteractionEnabled = true
pineapple.position = CGPoint(x: CGRectGetMidX(self.frame) - 200, y: CGRectGetMidY(self.frame));
self.addChild(pineapple)
【讨论】:
在 swift 3 中编译失败。 Swift4.1。覆盖 func touchesBegan(_ touches: Set如果您只寻找可以触摸的几个节点(例如,游戏 UI 中的“继续”或“退出”标签),这可能是一种替代但非常简单的解决方案:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
let touch = touches.first!
if myNode.containsPoint(touch.locationInNode(self))
print("touched")
【讨论】:
如何区分 Continue 和 Exit 标签? 可能......也许......你建议这段代码在两个标签中,继续和退出,当 touchesBegun 信息发送给它时,其中一个将被调用。 . 因为它是通过覆盖 touchesBegun 为触摸信息注册的。是这样吗,还是我…… 当然这不适用于重叠或相交的标签,但 touchesBegan() 旨在为整个场景覆盖,而不是标签的方法。 所以 touchesBegun() 只能存在于场景类中? 其实它是由 UIResponder 继承的:developer.apple.com/reference/uikit/uiresponder/… ... 这是 UIView 的超类。 SKScene 包含一个继承自 UIView 的 SKView :)【参考方案3】:更新 Swift Swift 版本 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1) 和 XCode 版本 8.2.1 (8C1002):
“Set”类型的值没有成员“anyObject”
'locationInNode' 已重命名为 'location(in:)'
'nodeAtPoint' 已重命名为 'atPoint(_:)'
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
for touch in touches
let location = touch.location(in: self)
let node : SKNode = self.atPoint(location)
if node.name == "myNodeName"
print("Hello")
【讨论】:
【参考方案4】:这将在 Xcode 9.2 Swift 4.0
中检测触摸override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
let touch:UITouch = touches.first!
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name
if name == "playLbl"
print("playLbl Touched")
【讨论】:
touches.first
不会错过一些当节点相互重叠为Florian mentions for another answer 的用例?【参考方案5】:
实现在触摸开始时调用的touchesBegan
方法。或者,您也可以在 touchesEnded
中执行此操作。
override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
let touch = touches.anyObject() as UITouch
let location = touch.locationInNode(self)
let nodes = self.nodesAtPoint(location)
for node in nodes
if node.name == "youNodeName"
// Node tapped
// Do something
break
【讨论】:
【参考方案6】:Swift 3 答案在SKSpriteNode
的子类中嵌入了触摸功能:
class SpriteSub: SKSpriteNode
init()
super.init(texture: nil, color: UIColor.red, size: CGSize(width: 50, height: 50))
isUserInteractionEnabled = true
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
...
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
print("touch!")
【讨论】:
Crashalot 它仍然让我进入 NSCoder 初始化...我忘记了如何正确覆盖这个东西 x @Fluidity 是的,你也需要这个 @Fluidity 再次更新。您编辑的 UIColor.clear() 也不是 Swift 3 代码。 Crashalot 是的,我也抓住了这个问题 @Fluidity 没什么,因为 UIColor.clear 是透明的。试试 UIColor.red。【参考方案7】:swift 5更新
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
for touch in touches
let location = touch.location(in: self)
let touchedNode = self.nodes(at: location)
for node in touchedNode
if node.name == "play_button"
startGame()
【讨论】:
【参考方案8】:使用这段代码来检测 SKSpriteNode 上的触摸
if(nodeAtPoint(location) == node)
【讨论】:
有史以来最简单的答案!谢谢你:) 这有效,但前提是所讨论的节点不与其他节点重叠,对吧? 比较类,你不应该使用===
而不是==
吗?
@mogelbuster 是的,如果您进行身份平等,似乎 === 是正确的。详情:***.com/a/44222407/144088【参考方案9】:
Swift 3.0 和 XCode 7.3.1 的更新。我有一个 SKShapeNode 派生到一个新类并将其插入到场景中。当我想检测这个对象时,我检查如下:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
for touch in touches
let location = touch.locationInNode(self)
let nodes = self.nodesAtPoint(location)
for node in nodes
if node is SKNodeDerivedNode
NSLog("Touch a SKNodeDerivedNode")
break
【讨论】:
【参考方案10】:这是我在 Swift 4 中用于查找特定类型节点中是否存在触摸的方式:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
guard let touch = touches.first else
return
let touchPosition = touch.location(in: self)
let touchedNodes = nodes(at: touchPosition)
for node in touchedNodes
if let nodoTouched = node as? YourNodeType
// touched!
【讨论】:
【参考方案11】:如果您在子类化SKSpriteNode
之后仍然没有让您的精灵工作,那么您很可能在初始化时忘记添加node.isUserInteractionEnabled = true
!
这允许调用touchesBegan(_:with:)
,因为您现在可以与节点交互。
例子:
node = MySprite(texture: texture, size: size)
node.isUserInteractionEnabled = true
【讨论】:
以上是关于如何检测是不是已触摸 SKSpriteNode的主要内容,如果未能解决你的问题,请参考以下文章
在触摸时将动画添加到 SKSpriteNode (Swift)