如何将客户端数据添加到SKNode / SKSpriteNode?

时间:2014-03-07 09:12:17

标签: ios model-view-controller sprite-kit skspritenode sknode

我正在使用IOS SpriteKit并想知道是否有某种方法可以将客户端数据添加到精灵节点?

例如,我想将特定行为附加到节点,附加属性,与其他节点的关系等。

我不愿意子类SKNode,因为这似乎打破了模型/视图/控制器模型,其中节点只是“视图”。

目前我正在保持一个单独的控制器对象层次结构,但这感觉很笨拙,而且性能不是很好。

什么是最佳做法?

3 个答案:

答案 0 :(得分:0)

在这方面,子类化不会改变任何内容。您仍然保留完整功能,并且不做任何事情。事实上,我认为如果你正在制作大型游戏,这几乎是不可避免的。

但是如果你真的不想再使用userData: SKNode -> userData

答案 1 :(得分:0)

所有SKNode类都提供userData属性,可用于此目的。

您可以编写Objective-C类别,通过该类别可以添加其他属性而无需子类化。以下是一种经过验证的模式。

接口:

#import "YourCustomObject.h"

@interface SKNode (customObject)
@property (nonatomic) YourCustomObject* yourCustomObject;
@end

实现:

static NSString* YourCustomObjectUserDataKey = @"YourCustomObjectUserDataKey";

@implementation SKNode (customObject)
-(NSMutableDictionary*) internal_getOrCreateUserData
{
    NSMutableDictionary* userData = self.userData;
    if (userData == nil)
    {
        userData = [NSMutableDictionary dictionary];
        self.userData = userData;
    }

    return userData;
}

-(void) setYourCustomObject:(YourCustomObject*)customObject
{
    NSMutableDictionary* userData = [self internal_getOrCreateUserData];
    [userData setObject: customObject forKey:YourCustomObjectUserDataKey];
}

-(YourCustomObject*) yourCustomObject
{
    NSMutableDictionary* userData = [self internal_getOrCreateUserData];
    return (YourCustomObject*)[userData objectForKey:YourCustomObjectUserDataKey];
}
@end

YourCustomObject替换为您的实际班级名称。

当然,类别可以扩展为托管多个属性,您不必为每个属性编写单独的类别。该类别也不必在SKNode上,如果您需要一个额外的属性,但只在SKSpriteNode上,您可以在SKSpriteNode上将其作为一个类别。

您经常需要访问YourCustomObject中的拥有节点。

出于这个原因,提供一个初始化器和/或属性是一个好主意,它将拥有节点作为输入。我更喜欢readonly属性和自定义初始化程序,因为通常你不希望所有者在整个对象的生命周期内改变。非常重要:此属性必须为weak才能创建保留周期。

@interface YourCustomObject
@property (weak, readonly) SKNode* owningNode;
+(instancetype) customObjectWithOwningNode:(SKNode*)owningNode;
@end

@implementation YourCustomObject
+(instancetype) customObjectWithOwningNode:(SKNode*)owningNode
{
    return [[self alloc] initWithOwningNode:owningNode];
}
-(id) initWithOwningNode:(SKNode*)owningNode
{
    self = [super init];
    if (self) 
    {
        _owningNode = owningNode;
    }
    return self;
}
@end

然后,您可以在节点类中创建和分配自定义对象:

YourCustomObject* customObject = [YourCustomObject customObjectWithOwningNode:self];
self.yourCustomObject = customObject;

答案 2 :(得分:0)

虽然这里的其他答案已经提到您可以将userData字典用于任意键值,但我要补充一点,您可以很好地继承SKNode s,因为SpriteKit在第一个不是MVC地方(或者至少不是UIKit的意思)。

SKNode旨在适合常见的游戏架构(组件模式和朋友),实际上可以是模型,视图或控制器。例如,SKNode不是可显示的对象,但可以保存有关游戏实体/状态或其他子节点的信息。