繁体   English   中英

子类化使用SpriteKit .sks场景文件创建的SKNode

[英]Subclassing SKNodes created with SpriteKit .sks scene file

(这适用于XCode 6和iOS 8 beta 4)

喜欢新的SceneKit编辑器。 我已成功将场景从.sks文件加载到自定义SKScene类中。 但是,其中的对象被实例化为默认类(SKNode,SKSpriteNode等),我不确定如何将它们绑定为实例化为自定义子类。

目前,我通过创建自定义类并链接到Sprite节点作为属性来解决此问题,并且可以正常工作

目前,您应该在添加到SpriteKit游戏模板中的方法中按名称进行操作。 他们在WWDC 2014的SpriteKit最佳实践视频中涵盖了此主题。由于视频中包含很多内容,因此很容易错过。

这是方法。

+ (instancetype)unarchiveFromFile:(NSString *)file {
    /* Retrieve scene file path from the application bundle */
    NSString *nodePath = [[NSBundle mainBundle] pathForResource:file ofType:@"sks"];
    /* Unarchive the file to an SKScene object */
    NSData *data = [NSData dataWithContentsOfFile:nodePath
                                          options:NSDataReadingMappedIfSafe
                                            error:nil];
    NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    [arch setClass:self forClassName:@"SKScene"];
    SKScene *scene = [arch decodeObjectForKey:NSKeyedArchiveRootObjectKey];
    [arch finishDecoding];

    return scene;
}

这是SKScene上的类别,其中包括从mainBundle中的.sks文件加载时使用NSKeyedUnarchiver替代Class的方法。 在iOS中,他们将其添加到GameViewController.m文件中,在OS X中,将其添加到AppDelegate.m文件中。

在这里或您自己的SKNode子类中,您可以实现此功能。 这是他在下面的帖子中所做的。 这是由Apple提供的,并在WWDC视频中进行了介绍。 我想明年会更好。 在此期间,请求SKNode的错误获得类似于IBDesignable for Scene Editor的错误。 :)

我写了一个小助手代表来解决这个问题: https : //github.com/ice3-software/node-archive-delegate 它使用NSKeyedUnarchiverDelegate来按名称NSKeyedUnarchiverDelegate进行子类化。

我做了一个小技巧,如何使用SceneKit编辑器,我将尝试使用它,但是我不确定如何降低性能。 我想使用场景编辑器制作复杂的SKNodes结构并将其加载到当前场景中。 它还可以帮助子类化节点。

我在场景编辑器中配置节点,将父节点设置为名为“ base”的空节点,并成为SKNode的子类。 然后,我创建了一个init方法,并在需要时调用它:

// subclass code
class MyOwnSKNodeSubclass: SKNode {

let nodeLayer = SKNode()

   init(fromNode: SKNode){
       super.init()

       nodeLayer.addChild(fromNode.childNodeWithName("base").copy() as SKNode)
       addChild(nodeLayer)
   }
}



// scene code
if let myNode = SKNode.unarchiveNodeFromFile("MyScene")
{
   // you can use your subclass here
   let node = MyOwnSKNodeSubclass(fromNode: myNode)

   addChild(node)
}

我还使用了自己的SKNode扩展,但没什么大不同,但:

class func unarchiveNodeFromFile(file:String) -> SKNode?{

    if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
        var nodeData = NSData.dataWithContentsOfFile(path, options: .DataReadingMappedIfSafe, error: nil)
        var archiver = NSKeyedUnarchiver(forReadingWithData: nodeData)

        archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKNode")
        let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as SKNode
        archiver.finishDecoding()
        return scene
    } else {
        return nil
    }
}

就像我说的那样,我不确定生产率,但是我认为,如果不经常使用它,不会造成太大的伤害。 希望这对某人有帮助。

是的,Apple应该使我们所有人都更容易做到这一点,但是就目前而言,这是我需要的最可行的解决方案:

避免子类化

当然,这可能根本不可能,但是就我而言,我想到的子类包含控制我在SKS文件中布局的图形的逻辑……听起来与ViewController非常接近,不是吗?

我创建了一个OverlayController类,并使用以下代码对其进行了初始化:

self.childNodeWithName(Outlet.OverlayNode)!

因此,现在,overlay节点只是一个哑节点,而controller是具有所有优点的完整子类。

但是还有更多

只是把它扔进去就可以使交易变甜:

private extension SKNode {
    var progressBar: SKNode {
        return self.childNodeWithName("ProgressBar")!
    }
}

这是新控制器类文件中的一个私有扩展,因此我们可以轻松地访问哑SKNode的子SKNode

痛点

令人痛苦的一点是触摸处理。 将SKNode子类化以进行自定义触摸处理是很自然的,并且合成方法几乎无法在此方面做任何事情。 我目前正在从现场转发触摸,但是如果有更好的方法,我会发布更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM