创建SKSpriteNode子类的子类

时间:2014-05-30 02:14:32

标签: objective-c inheritance sprite-kit skspritenode

假设我想创建一堆不同类型的太空飞船。我想设置一个基础太空船类,我可以用它来创建其他太小差异的太空飞船。

我的基类看起来像这样。

// BaseSpaceship.h
@interface SpaceshipNode : SKSpriteNode
@property NSColor color;
@property CGFloat engineThrust;
+ (id)baseSpaceshipWithImageNamed:(NSString *)name;
@end

// BaseSpaceship.m
@implementation BaseSpaceship
+ (id)baseSpaceshipWithImageNamed:(NSString *)name {
    BaseSpaceship *ship = [BaseSpaceship spriteNodeWithImageNamed:name];

    ship.color = [NSColor redColor];
    ship.engineThrust = 2.0;

    return ship;
}
@end

我可以在MyScene.m中创建一艘船就像这样。

BaseSpaceship *baseClass = [BaseSpaceship baseSpaceshipWithImageNamed:@"BaseShip"];

但是,我不确定如何创建BaseSpaceship的子类,例如DestroyerSpaceship。我不确定我是否应该使用静态方法。我在网上看到的例子使用静态方法来实例化SKSpriteNode。这就是我提出的,但这是错误的。

// DestroyerSpaceship.h
@interface DestroyerSpaceship : BaseSpaceship
@property CGFloat missileThrust;
- (id)makeDestroyerSpaceship;
@end

// DestroyerSpaceship.m
@implementation DestroyerSpaceship
- (id)makeDestroyerSpaceship{
    DestroyerSpaceship *ship = [DestroyerSpaceship baseSpaceshipWithImageNamed:@"DestroyerShip"];
    ship.engineThrust = 2.0;
    // ship doesn't have missileThrust, program crashes
    ship.missileThrust = 3.0; 

    return ship;
}
@end

最终,我希望能够做到这样的事情。

DestroyerSpaceship* a = [DestroyerSpaceship makeDestroyerSpaceship];
EvilSpaceship* b = [EvilSpaceship makeEvilSpaceship];
NiceSpaceship* c = [NiceSpaceship makeNiceSpaceship];

让他们都从BaseSpaceship继承基本属性和方法。

2 个答案:

答案 0 :(得分:7)

答案并不像你想象的那么复杂。好吧,代码可能有点复杂,但是一旦你有了结构,它就会变得最灵活。创建不同类型的宇宙飞船也会更具可读性。

您可以覆盖子类中的初始化方法。作为旁注,请使用(instancetype)代替(id)(来源:instancetype @ NSHipster)。

在向对象添加自定义正文精灵时,我会选择子类化SKNode而不是SKSpriteNode(所以@interface SpaceshipNode : SKNode代替@interface SpaceshipNode : SKSpriteNode)。

@interface SpaceshipNode : SKNode
  @property SKColor * color; // Use SKColor instead of NSColor
  @property CGFloat engineThrust;
@end

// ... 

@implementation SpaceshipNode

- (instancetype) init {
  if (self == [super init]) {
    NSLog(@"A new SpaceshipNode was just init'ed.");
    // set some default initial values here that all brand-new SpaceshipNodes will inherit

    // perhaps create and add a basic body sprite
    // SKSpriteNode * body = ...;
    // [self addChild:body];

    // set thrust
    self.engineThrust = 2.0;
  }
  return self;
}

然后你可以继承并创建一种新型宇宙飞船。真棒!

@interface DestroyerSpaceship : SpaceshipNode
  @property CGFloat missileThrust;
@end

@implementation DestroyerSpaceship

- (instancetype) init {
  // note that [super init] will call the SpaceshipNode's init method
  if (self = [super init]) {
    NSLog(@"A new DestroyerSpaceship was just init'ed.");

    // add a body sprite
    // SKSpriteNode * body = ...;
    // [self addChild:body];

    // a Destroyer is much faster than your average spaceship
    self.engineThrust = 10.0;

    // set class specific variables
    self.missileThrust = 5.f;
  }
  return self;
}

现在,您可以致电:

SpaceshipNode * newSpaceShip = [SpaceshipNode new]; // short for [[SpaceshipNode alloc] init];
DestroyerSpaceship * newDestroyer = [DestroyerSpaceship new];

这两行将记录以下内容。最后两行是由驱逐舰引起的,驱逐舰首先调用SpaceshipNode init,然后调用特定于驱逐舰的init方法。

  

新的SpaceshipNode刚刚初始化。

     

新的SpaceshipNode刚刚初始化。

     

新的DestroyerSpaceship刚刚开始使用。

你甚至可以这样使用它:

SpaceshipNode * newUnidentifiedVessel = [DestroyerSpaceship new];

if ([newUnidentifiedVessel isKindOfClass:[DestroyerSpaceship class]]) {
  NSLog(@"We are under attack! Route power to shields!");
}

答案 1 :(得分:0)

- (instancetype)makeDestroyerSpaceship{
    if (self = [super baseSpaceshipWithImageNamed:@"DestroyerShip"]) {
        self.engineThrust = 2.0;
        self.missileThrust = 3.0; 
    }
    return self;
}
相关问题