.sks文件中SKSpriteNode的子类

时间:2015-01-12 18:07:57

标签: swift sprite-kit xcode6

我正在使用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

任何帮助?

感谢。

1 个答案:

答案 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文件中设置更多配置详细信息,则可以考虑自动执行该过程。

  1. 制作一个执行上述节点交换技巧的方法。 (称之为Plumber。)
  2. 为您的自定义类创建一个初始化程序,它使用let spawnPoint = childNodeWithName("spawnPoint") let player = Plumber() player.position = spawnPoint.position addChild(player) spawnPoint.removeFromParent() .sks,并让它设置所有继承的属性(或至少是您关心的属性,如颜色和纹理)节点
  3. 使用enumerateChildNodesWithName:usingBlock:search pattern查找场景中具有某种名称的所有节点,并将其替换为使用初始化程序创建的新节点。类似的东西:

    replaceNode(_:withNode:)