.sks文件中SKSpriteNode的子类

Mar*_*iam 1 sprite-kit swift xcode6

我正在使用SpriteKit .sks文件我可以将.sks中的精灵变成SKSpriteNode的子类实例吗?

这是我的子类中的init方法:

    init(imageNamed: String) {

    let blockTexture = SKTexture(imageNamed: imageNamed)

    super.init(texture: blockTexture, color: nil, size: blockTexture.size())
}
Run Code Online (Sandbox Code Playgroud)

在GameScene.swift中,我可以创建一个这样的实例:

var myObj = Block(imageNamed: "Block")
Run Code Online (Sandbox Code Playgroud)

我的问题是如何将此实例与.sks文件相关联?

我尝试了这行代码,但它不起作用.

myObj     = childNodeWithName("block1") as Block
Run Code Online (Sandbox Code Playgroud)

有帮助吗?

谢谢.

ric*_*ter 16

这里有几个问题要解决......

.sks装载如何工作

当您加载.sks文件时,SpriteKit会实例化使用中的所有内容NSKeyedUnarchiver.这意味着内部的所有节点都被加载为Xcode在创建.sks文件时指定的任何基类- SKSpriteNode对于具有纹理艺术,SKLabelNode文本,SKFieldNode物理场等的精灵.Xcode目前不提供选项为.sks文件中的节点设置自定义类.

(一个例外是更改场景本身的运行时类 - .sks文件中所有内容的顶级容器.这只是因为SKNode.unarchiveFromFile项目模板中为您提供的自定义实现.它在加载时更改类的技术当存档中只有一个特定类的实例时,它就可以工作 - 对于SKScene场景中的许多节点来说,这样做不是很好.)

如何铸造工作

当你写下这样的东西:

myObj = childNodeWithName("block1") as Block
Run Code Online (Sandbox Code Playgroud)

你告诉编译器类似的东西:"嘿,你知道你得到的东西childNodeWithName吗?你知道的是它是一个SKNode,但我知道它真的是一个Block,所以请让我Block在它上面调用方法." (并且编译器说,"好的,无论如何.")

但是在运行时,你得到的东西最好真的是一个Block,或者你的应用程序会崩溃,因为你试图做一些Block与某些东西不同的东西Block.并且,根据.sks上面的加载,那件事不是也不可能是Block- Xcode不知道如何将Blocks放入.sks文件中.所以你无法摆脱Block它,所以你的应用程序肯定会崩溃.

解决方法

因此,如果您不能将自定义类放入.sks文件中,您可以做什么?这取决于你究竟想要完成什么.但是有一个很好的技巧,一般也可能是好的游戏/应用程序设计:使用该.sks文件进行一般布局和配置,并使用第二遍来引入需要自定义行为的东西.

例如,如果你正在2D平台游戏中构建一个级别,你就不会真的希望.sks文件包含你的Plumber类的实例,即使你可以 - 该类可能有很多关于高或胖的详细信息.伙计是,他跳得有多高,胡子的形状等等,你不想每次你创造一个新的水平时都要重新设置它们,更不用说在每个级别的.sks文件中再次保存它们.相反,你在每个关卡文件中真正需要知道的唯一事情就是他开始的位置.因此,在Xcode中拖出一个"空节点",并在加载时将该节点替换为您的Plumber类的实例,如下所示:

let spawnPoint = childNodeWithName("spawnPoint")
let player = Plumber()
player.position = spawnPoint.position
addChild(player)
spawnPoint.removeFromParent()
Run Code Online (Sandbox Code Playgroud)

如果您要在.sks文件中设置更多配置详细信息,则可以考虑自动执行该过程.

  1. 制作一个执行上述节点交换技巧的方法.(称之为replaceNode(_:withNode:).)
  2. 为您的自定义类创建一个初始化程序,它接受一个SKNodeSKSpriteNode,并从该节点设置所有继承的属性(或至少是您关心的属性,如颜色和纹理).
  3. enumerateChildNodesWithName:usingBlock:搜索模式一起使用以查找具有某种名称的场景中的所有节点,并将其替换为使用初始化程序创建的新节点.就像是:

    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))
    }
    
    Run Code Online (Sandbox Code Playgroud)