我正在使用 SpriteKit .sks 文件 我可以将 .sks 中的 Sprite 制作成 SKSpriteNode 子类的实例吗?
这是我的子类中的 init 方法:
init(imageNamed: String) {
let blockTexture = SKTexture(imageNamed: imageNamed)
super.init(texture: blockTexture, color: nil, size: blockTexture.size())
}
在 GameScene.swift 中,我可以创建一个这样的实例:
var myObj = Block(imageNamed: "Block")
我的问题是如何将此实例与 .sks 文件相关联?
我尝试了这行代码,但它不起作用。
myObj = childNodeWithName("block1") as Block
有什么帮助吗?
谢谢。
最佳答案
这里有几个问题需要解决.......sks
加载如何工作
当您加载 .sks
文件时,SpriteKit 会使用 NSKeyedUnarchiver
实例化其中的所有内容。这意味着里面的所有节点都被加载为 Xcode 在创建 .sks
文件时指定的任何基类 - SKSpriteNode
用于具有纹理艺术的 Sprite ,SKLabelNode
用于文本,SKFieldNode
用于物理场等。目前 Xcode 没有提供一个选项来为 .sks
文件中的节点设置自定义类。
(对此的一个异常(exception)是更改场景本身的运行时类 — .sks
文件中所有内容的顶级容器。这只是因为项目模板中为您提供的自定义 SKNode.unarchiveFromFile
实现。它在以下位置更改类的技术当存档中只有一个特定类的一个实例时,加载时间有效——对 SKScene
有利,对场景中的许多节点不利。)
类型转换的工作原理
当你写这样的东西时:
myObj = childNodeWithName("block1") as Block
你在告诉编译器这样的事情:“嘿,你知道你从
childNodeWithName
得到的东西吗?你只知道它是一个 SKNode
,但我知道它真的是一个 Block
,所以请让我调用 Block
方法(编译器说,“好吧,随便吧。”)但是在运行时,你得到的东西最好 真的是 a
Block
,否则你的应用程序会崩溃,因为你试图用不是 Block
的东西做一些 Block
y 的事情。而且,根据上面加载的 .sks
位,那个东西不是也不能是 Block
— Xcode 不知道如何将 Block
放入 .sks
文件中。所以你不能从中得到 Block
,所以你的应用程序肯定会崩溃。解决方法
那么,如果您不能将自定义类放入
.sks
文件中,您能做什么?这在一定程度上取决于您究竟要完成什么。但是有一个很好的技巧,通常也可能是好的游戏/应用程序设计:使用 .sks
文件进行一般布局和配置,并使用第二遍引入需要自定义行为的东西。例如,如果您在 2D 平台游戏中构建关卡,即使可以,您也不会真的希望
.sks
文件包含 Plumber
类的实例——该类可能有很多关于高度或高度的详细信息这个人很胖,他跳多高, mustache 的形状等等,你不想每次创建新关卡时都重新设置,更不用说在每个关卡的 .sks
文件中再次保存它们.相反,在每个级别文件中您真正需要知道的唯一事情是他开始的位置。因此,在 Xcode 中拖出一个“空节点”,并在加载时,将该节点替换为 Plumber
类的实例,如下所示:let spawnPoint = childNodeWithName("spawnPoint")
let player = Plumber()
player.position = spawnPoint.position
addChild(player)
spawnPoint.removeFromParent()
如果您想在
.sks
文件中设置更多配置详细信息,则可以考虑自动化该过程。replaceNode(_:withNode:)
之类的东西。)SKNode
或 SKSpriteNode
,并让它从该节点设置其所有继承属性(或至少您关心的属性,如颜色和纹理)。 enumerateChildNodesWithName:usingBlock:
和 search pattern 查找场景中具有某种名称的所有节点,并将它们替换为使用初始化程序创建的新节点。就像是:enumerateChildNodesWithName("//brick_[0-9]*") { node, stop in
self.replaceNode(node, withNode: BrickBlock(node))
}
enumerateChildNodesWithName("//question_[0-9]*") { node, stop in
self.replaceNode(node, withNode: QuestionBlock(node))
}
关于swift - .sks 文件中 SKSpriteNode 的子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27908165/