我正在使用SpriteKit .sks文件我可以将.sks中的精灵变成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
任何帮助?
感谢。
答案 0 :(得分:16)
这里有几个问题要解决......
.sks
加载的工作原理当您加载.sks
文件时,SpriteKit会使用NSKeyedUnarchiver
实例化所有内容。这意味着内部的所有节点都被加载为Xcode在创建.sks
文件时指定的基类类别 - SKSpriteNode
用于带有纹理艺术的精灵,SKLabelNode
用于文本,{ {1}}用于物理领域等.Xcode目前不提供为SKFieldNode
文件中的节点设置自定义类的选项。
(一个例外是更改场景本身的运行时类 - .sks
文件中所有内容的顶级容器。这只是因为为您提供的自定义.sks
实现在项目模板中。当你在一个档案中只有一个特定类的实例时,它在加载时改变类的技术很有用 - 适用于SKNode.unarchiveFromFile
,对场景中的许多节点来说不太好。)
当你写下这样的东西时:
SKScene
你告诉编译器类似的东西:“嘿,你知道你从myObj = childNodeWithName("block1") as Block
得到的东西吗?你所知道的是它是childNodeWithName
,但我知道它真的是{{1}所以请让我在其上调用SKNode
方法。“ (并且编译器说,“好的,无论如何。”)
但是在运行时,你得到的东西更好 真的 一个Block
,否则你的应用会崩溃因为你试图做某事{ {1}} y的内容不是Block
。并且,根据上面Block
加载的内容,该内容不是,也不可能是Block
- Xcode不知道如何将Block
放入.sks
文件。因此,您无法获得Block
,因此您的应用可以保证崩溃。
那么,如果您不能将自定义类放入Block
文件中,那么可以吗?这取决于你究竟想要完成什么。但是有一个很好的技巧,一般也可能是好的游戏/应用程序设计:使用.sks
文件进行一般布局和配置,并使用第二遍来引入需要自定义行为的东西。
例如,如果您在2D平台游戏中构建关卡,即使可以,您也不希望Block
文件包含.sks
类的实例 - 那个班级可能有很多细节,关于这个家伙有多高或多胖,跳得多高,小胡子的形状等等,你不想每当你达到一个新的水平时都要重新设置它们,更少的是在每个级别的.sks
文件中再次保存它们。相反,你在每个关卡文件中真正需要知道的唯一事情就是他开始的位置。因此,在Xcode中拖出一个“空节点”,并在加载时将该节点替换为.sks
类的实例,如下所示:
Plumber
如果您要在.sks
文件中设置更多配置详细信息,则可以考虑自动执行该过程。
Plumber
。)let spawnPoint = childNodeWithName("spawnPoint")
let player = Plumber()
player.position = spawnPoint.position
addChild(player)
spawnPoint.removeFromParent()
或.sks
,并让它设置所有继承的属性(或至少是您关心的属性,如颜色和纹理)节点使用enumerateChildNodesWithName:usingBlock:
和search pattern查找场景中具有某种名称的所有节点,并将其替换为使用初始化程序创建的新节点。类似的东西:
replaceNode(_:withNode:)