SKSpriteNode 的正确子类化和实例初始化
Proper subclassing of SKSpriteNode and instance initialization
我正在尝试对 SKSpriteNode 进行子类化,以便我可以使用它为游戏创建具有不同属性的不同角色。我知道这应该是一项微不足道的任务,但我很难理解如何在创建实例时初始化变量。
在 header 我有:
#import <SpriteKit/SpriteKit.h>
@interface MyClass : SKSpriteNode
@property int myVariable;
@end
并在实施中:
#import "MyClass.h"
@interface MyClass ()
@end
@implementation MyClass
@synthesize myVariable;
- (id)init {
if (self = [super init]) {
myVariable = 100;
}
return self;
}
当我在场景中创建节点时:
@implementation GameScene
{
MyClass *mySprite;
}
- (void)didMoveToView: (SKView *) view
{
mySprite = [MyClass spriteNodeWithImageNamed:@"image.png"];
}
myVariable的值为0,我假设这意味着spriteNodeWithImageNamed没有执行init方法。如果我使用:
mySprite = [[MyClass alloc] init]; // or mySprite = [MyClass new];
mySprite = [MyClass spriteNodeWithImageNamed:@"image.png"];
变量名称正确设置为 100,但随后被 spriteNodeWithImageNamed 还原为 0。
我也试过:
mySprite = [[MyClass alloc] init]; // or mySprite = [MyClass new];
[mySprite setTexture:[SKTexture textureWithImageNamed:@"image.png"]];
在这种情况下myVariable的值是正确的,但是当我将节点添加到场景时没有图像出现。使用 spriteNodeWithImageNamed 时会调用什么 init 方法?我是否不正确地覆盖了 SKSpriteNode 初始化方法?
您已经通过创建 class 正确地完成了所有操作,但是您需要记住您正在调用工厂方法 spriteNodeWithImageNamed
,然后它会自行初始化和分配。因此,如果您想使用自定义 init
方法,您还需要重写工厂方法。
在您的 MyClass 实现中,覆盖调用初始化程序的方法:
+ (instancetype) spriteNodeWithImageNamed:(NSString *)imageName{
MyClass *newClass = [[MyClass alloc] init];
SKTexture *spriteTexture = [SKTexture textureWithImageNamed:imageName];
newClass.size = spriteTexture.size;
newClass.texture = spriteTexture;
return newClass;
}
希望这对您有所帮助,如果您有任何问题,请告诉我。
*EDIT:我实际上有点想放弃这个,只是因为 SKSpriteNode 没有 init
方法(或者至少我们不知道).所以除非你想深入了解 Apple 的奥秘,否则就这样做吧:
+ (instancetype) spriteNodeWithImageNamed:(NSString *)imageName{
MyClass *newClass = [[MyClass alloc] initWithImageNamed:imageName];
newClass.myVariable = 100;
return newClass;
}
您可以改写 initWithImage
以放入 myVariable,但重点是我会避免尝试将 init
初始化程序与 SKSpriteNode 一起使用。
这是我的做法。创建您自己的自定义 init 方法,只需调用默认的 spritenode initWithImage。
-(id)initShipWithType:(ShipType)type {
self = [super initWithImageNamed:[self getShipSprite:type]];
if (self) {
}
return self;
}
我正在尝试对 SKSpriteNode 进行子类化,以便我可以使用它为游戏创建具有不同属性的不同角色。我知道这应该是一项微不足道的任务,但我很难理解如何在创建实例时初始化变量。 在 header 我有:
#import <SpriteKit/SpriteKit.h>
@interface MyClass : SKSpriteNode
@property int myVariable;
@end
并在实施中:
#import "MyClass.h"
@interface MyClass ()
@end
@implementation MyClass
@synthesize myVariable;
- (id)init {
if (self = [super init]) {
myVariable = 100;
}
return self;
}
当我在场景中创建节点时:
@implementation GameScene
{
MyClass *mySprite;
}
- (void)didMoveToView: (SKView *) view
{
mySprite = [MyClass spriteNodeWithImageNamed:@"image.png"];
}
myVariable的值为0,我假设这意味着spriteNodeWithImageNamed没有执行init方法。如果我使用:
mySprite = [[MyClass alloc] init]; // or mySprite = [MyClass new];
mySprite = [MyClass spriteNodeWithImageNamed:@"image.png"];
变量名称正确设置为 100,但随后被 spriteNodeWithImageNamed 还原为 0。
我也试过:
mySprite = [[MyClass alloc] init]; // or mySprite = [MyClass new];
[mySprite setTexture:[SKTexture textureWithImageNamed:@"image.png"]];
在这种情况下myVariable的值是正确的,但是当我将节点添加到场景时没有图像出现。使用 spriteNodeWithImageNamed 时会调用什么 init 方法?我是否不正确地覆盖了 SKSpriteNode 初始化方法?
您已经通过创建 class 正确地完成了所有操作,但是您需要记住您正在调用工厂方法 spriteNodeWithImageNamed
,然后它会自行初始化和分配。因此,如果您想使用自定义 init
方法,您还需要重写工厂方法。
在您的 MyClass 实现中,覆盖调用初始化程序的方法:
+ (instancetype) spriteNodeWithImageNamed:(NSString *)imageName{
MyClass *newClass = [[MyClass alloc] init];
SKTexture *spriteTexture = [SKTexture textureWithImageNamed:imageName];
newClass.size = spriteTexture.size;
newClass.texture = spriteTexture;
return newClass;
}
希望这对您有所帮助,如果您有任何问题,请告诉我。
*EDIT:我实际上有点想放弃这个,只是因为 SKSpriteNode 没有 init
方法(或者至少我们不知道).所以除非你想深入了解 Apple 的奥秘,否则就这样做吧:
+ (instancetype) spriteNodeWithImageNamed:(NSString *)imageName{
MyClass *newClass = [[MyClass alloc] initWithImageNamed:imageName];
newClass.myVariable = 100;
return newClass;
}
您可以改写 initWithImage
以放入 myVariable,但重点是我会避免尝试将 init
初始化程序与 SKSpriteNode 一起使用。
这是我的做法。创建您自己的自定义 init 方法,只需调用默认的 spritenode initWithImage。
-(id)initShipWithType:(ShipType)type {
self = [super initWithImageNamed:[self getShipSprite:type]];
if (self) {
}
return self;
}