Cameron Frank
Cameron Frank

Reputation: 47

Spritekit Subclassed node shows as nil

Heyo folks, having a weird issue when trying to create a subclassed node in SpriteKit. I get no errors at compile, and app runs until I progress to where the node needs to be added as a child of the scene, then fails and says reason: 'Attemped to add nil node to parent: I'm not sure what I'm missing, any help is appreciated! Here's my header for the node:

#import <SpriteKit/SpriteKit.h>

@interface Ships : SKSpriteNode

-(Ships *)initWithImageNamed: (NSString *)imageName;

@end

And here's the implementation:

#import "Ships.h"

@implementation Ships

-(Ships *)initWithImageNamed: (NSString *)imageName
{
self = [Ships spriteNodeWithImageNamed:imageName];

// Adds more accurate physics body for ship collisions
CGFloat offsetX = (self.frame.size.width * 1.2) * self.anchorPoint.x;
CGFloat offsetY = (self.frame.size.height * 1.2) * self.anchorPoint.y;

CGMutablePathRef path = CGPathCreateMutable();

CGPathMoveToPoint(path, NULL, 8 - offsetX, 30 - offsetY);
CGPathAddLineToPoint(path, NULL, 7 - offsetX, 22 - offsetY);
CGPathAddLineToPoint(path, NULL, 50 - offsetX, 2 - offsetY);
CGPathAddLineToPoint(path, NULL, 65 - offsetX, 7 - offsetY);
CGPathAddLineToPoint(path, NULL, 70 - offsetX, 8 - offsetY);
CGPathAddLineToPoint(path, NULL, 27 - offsetX, 31 - offsetY);

CGPathCloseSubpath(path);

self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];
self.physicsBody.dynamic = NO;
self.physicsBody.restitution = 0.0f;
self.physicsBody.friction = 0.0f;
self.physicsBody.linearDamping = 1.0f;
self.physicsBody.allowsRotation = NO;
self.physicsBody.usesPreciseCollisionDetection = YES;

// Keeps player ship on top of all other objects(unless other objects are assigned greater z position
self.zPosition = 100.0f;

return self;
}

@end

Then in my scene, I declare playerNode in interface with: Ships *playerNode; and here's the method that attempts to implement the node:

-(void) createPlayerNode
{
playerNode = [playerNode initWithImageNamed:@"Nova-L1"];
playerNode.position = CGPointMake(self.frame.size.width/5, self.frame.size.height/2);
playerNode.physicsBody.categoryBitMask = CollisionCategoryPlayer;
playerNode.physicsBody.collisionBitMask = 0;
playerNode.physicsBody.contactTestBitMask = CollisionCategoryBottom | CollisionCategoryObject | CollisionCategoryScore | CollisionCategoryPup;

[self addChild:playerNode];
}

and I call [self createPlayerNode]; elsewhere in the app, and as soon as I do...crash. Any help is greatly appreciated! Also, I'm running on my iPhone 5

Upvotes: 0

Views: 86

Answers (1)

0x141E
0x141E

Reputation: 12773

The initializer for Ships is an instance method not a class method, so your alloc/init statement should be

playerNode = [[Ships alloc] initWithImageNamed:@"Nova-L1"]];

and in Ships.m, replace

self = [Ships spriteNodeWithImageNamed:imageName];

with this

self = [super initWithImageNamed:imageName];

Additionally, you should release the path after creating the physics body...

    ship.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];

    CGPathRelease(path);

Alternatively, you can declare a convenience method in Ships.m to alloc/init in a single step.

EDIT:

Declare class method in Ships.m

+ (Ships *)shipNodeWithImageNamed:(NSString *)imageName
{
    return [[Ships alloc] initWithImageNamed:imageName];
}

Add method prototype to Ships.h

+ (Ships *)shipNodeWithImageNamed:(NSString *)imageName;

and create a new ship node by

playerNode = [Ships shipNodeWithImageNamed:@"Nova-L1"];

Upvotes: 2

Related Questions