【发布时间】:2021-07-28 19:49:39
【问题描述】:
所以我通过构建这样的 buildCharacter 方法解决了我关于减少重复代码的其他问题之一 -
func buildCharacter(name:String, height: CGFloat, width: CGFloat, position: CGPoint, zPosition: CGFloat) {
let animatedAtlas = SKTextureAtlas(named: name)
var animationFrames: [SKTexture] = []
let numImages = animatedAtlas.textureNames.count
for i in 1...numImages {
let textureName = "\(name)\(i)"
animationFrames.append(animatedAtlas.textureNamed(textureName))
}
animatedCharacter = animationFrames
let firstFrameTexture = animatedCharacter[0]
builtCharacter = SKSpriteNode(texture: firstFrameTexture)
builtCharacter.size.height = height
builtCharacter.size.width = width
builtCharacter.position = position
builtCharacter.zPosition = zPosition
builtCharacter.name = name
isUserInteractionEnabled = true
addChild(builtCharacter)
}
然后我像这样在每个场景的基础上调用它们 -
buildCharacter(name: "Bear", height: 370, width: 370, position: CGPoint(x: 295, y: 25), zPosition: 10)
buildCharacter(name: "Cat", height: 240, width: 240, position: CGPoint(x: 134, y: -38), zPosition: 12)
这非常适合构建并将它们添加到场景中,但是我正在努力检测触摸然后为它们设置动画。我之前的 TouchesBegan 是这样的 -
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if let touch = touches.first {
let location = touch.location(in: self)
var closest:CGFloat?
let nodes = nodes(at:location)
for node in nodes as [SKNode] {
if let sprite = node as? SKSpriteNode {
// Calculate the distance from the node to the touch
let dx = location.x - node.position.x
let dy = location.y - node.position.y
let distance = dx*dx + dy*dy
// Find the closest
if closest == nil || distance < closest! {
closest = distance
selectedNode = sprite
}
}
}
}
switch selectedNode {
case bear:
if builtCharacter.hasActions() {
SoundEngine.shared.stopBackgroundMusic(fadeOut: false)
stopAllAnimation()
} else {
SoundEngine.shared.playBackgroundMusic("blueRail.aif", loop: false)
startAllAnimation()
}
case cat:
if cat.hasActions() {
SoundEngine.shared.stopBackgroundMusic(fadeOut: false)
stopAllAnimation()
} else {
SoundEngine.shared.playBackgroundMusic("cluckOldHen.aif", loop: false)
animateCat()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.startAllAnimation()
}
}
所以基本上我正在努力访问节点名称?我尝试了builtCharacter.name,但无法弄清楚...我想我可以在 TouchesBegan 中做一些不同的事情,或者在 buildCharacter 方法中添加一些东西?
我知道我可以很容易地在情节提要中做到这一点,这是我的备用计划 - 只是尝试通过这种方法学习更多内容。提前致谢!
【问题讨论】:
-
在您的
switch selectedNode语句中,您不需要对所选节点的名称进行切换并将案例:熊和猫放在引号中吗?是熊和猫字符串还是它们不在您提供的代码中的枚举? -
它们是字符串 - 所以如果我把它们作为 case 他们会出错,因为 selectedNode 是 SKSpriteNode...我也尝试将 selectedNode 转换为字符串 - 也有错误...但我喜欢它也是那个部分的东西。
-
您必须打开所选节点的名称:
selectedNode.name,其中包含“bear”或“cat”的情况,因为它们是字符串。该名称是可选的,因此您可能无法直接切换该名称。在您当前的代码中,您正在打开所选节点。 SpriteKit 没有熊和猫精灵节点,因此这些情况下的代码永远不会执行。 -
这是有道理的——我尝试使用字符串大小写打开“selectNode.name”,是的,它不起作用。我不确定还有什么要打开的?是否可以在 buildCharacters 方法中创建一个熊和猫精灵节点,而不仅仅是使用 builtCharacter 节点?
-
selectedNode.name不能直接工作,因为SKNode的name属性是可选的。您需要在名称上使用if let声明并打开它。该名称是确定所触摸的精灵类型的唯一直接方法。唯一的选择是为角色创建自己的结构或类,以及为角色类型创建一个枚举:熊、猫或其他。结构/类具有枚举和精灵节点的属性。使用枚举来确定被触摸的字符类型。
标签: swift sprite-kit