SKNode子类应该如何与父场景和兄弟节点进行通信?

dou*_*lea 1 objective-c ios sprite-kit

当事件发生时,SKNode子类应该如何通知父场景?

我有一个SKNode子类,通过根据游戏逻辑重新绘制或删除节点来处理触摸事件.用于通知事件发生的父场景(或其他兄弟SKNode实例)的iOS最佳实践是什么?我应该使用NSNotification中心吗?某种形式的授权?我想避免紧耦合.我可以想到几种方法来完成它,但想知道是否有标准做法,因为似乎有非游戏MCV iOS设计(例如NSNotification用于模型之间的通信,或模型 - >控制器,委托或目标 - 视图操作 - >控制器等)

从概念上讲,我喜欢SKNode子类基本上服务于"视图"角色,解释触摸事件,然后将"语义"游戏信息传递给包含场景或其他节点的想法.

// SampleScene.m

#include "SampleScene.h"
#include "SampleBallNode.h"

@implementation SampleScene
- (void)didMoveToView:(SKView *)view {
  if (!self.contentCreated) {
    [self createSceneContents];
    self.contentCreated = YES;
  }
}

- (void)createSceneContents {
  self.backgroundColor = [SKColor whiteColor];
  self.scaleMode = SKSceneScaleModeAspectFit;
  [self addBall];
}

- (void)addBall {
  SampleBallNode *ball = [[SampleBallNode alloc] init];
  ball.position = CGPointMake(100, 100);
  [self addChild:ball];
}

@end

// SampleBallNode.m

#include "SampleBallNode.h"

- (id)init {
  if ([super init]) {
    self.name = @"ball";
    self.userInteractionEnabled = YES;
    [self drawSelf];
  }
  return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  [self removeFromParent];

  // TELL SCENE THAT I'VE DIED HERE... TO UPDATE SCORE OR SOMETHING...
}

- (void)drawSelf {
  UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect ...

  SKShapeNode *tokenBall = [[SKShapeNode alloc] init];
  tokenBall.path = ovalPath.CGPath;
  [self addChild:tokenBall];
}

@end
Run Code Online (Sandbox Code Playgroud)

Lea*_*s2D 7

对于像触摸和输入这样的东西,我会避免在每个单独的实例中处理它们.不仅因为它效率低下,您还没有简单的方法来决定谁接触到触摸以及触摸应该如何传播到其他节点.

简单的情况:两个重叠的节点 - 您是只想要移除最顶层的节点,还是只想触摸任何一个节点,或者只是在触摸位置?在这种情况下,最好在中心位置接收输入,然后迭代"可触摸"节点.

除此之外:

  • 使用委托,否则你会通过直接向另一个对象发送消息来进行紧密耦合
  • 如果您有多个可能想要对事件做出反应的潜在代表,并且该事件不会经常发生(即绝对不是每一帧),请使用通知
  • 当你完全懒惰而不关心时使用单身人士

从概念上讲,你会通过行为找到Kobold Kit中的好例子和解决方案,这是游戏组件的一种形式.还包括每节点模型存储类KKModel,它允许您在任何节点中存储得分等内容,而无需仅为变量添加子类.

例如:

[self.scene.model setDouble:score forKey:@"score"];
Run Code Online (Sandbox Code Playgroud)

然后,您可以在标签类中使用update方法来获取分数:

double score = [self.scene.model doubleForKey:@"score"];
Run Code Online (Sandbox Code Playgroud)

避免消息传递,委派和通知,同时降低(一点点)效率.