开发者

Cocos2d: CCSprite initWithFile in CCSprite subclass crashes

I have cocos2d project with custom CCSprite subclass:

MyCustomSprite.h:

#import "cocos2d.h"
@interface MyCustomSprite : CCSprite
@end

MyCustomSprite.m:

#import "MyCustomSprite.h"
@implementation MyCustomSpr开发者_运维技巧ite
- (id)init
{
    self = [super initWithFile:@"index.png"];
    return self;
}
@end

For some strange reason, this code will crash with "EXC_BAD_ACCESS".

But in spite of this, if i init super as ususal and then write code from CCSprite's initWithFile and initWithTexture, it will work fine:

self = [super init];
if (self) {
    // Code from CCSprite.m - initWithFile
    CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: @"index.png"];
    CGRect rect = CGRectZero;
    rect.size = texture.contentSize;

    // Code from CCSprite.m - iniWithTexture
    [self setTexture:texture];
    [self setTextureRect:rect];

    return self;
} 

What's the reason that the first example crashes, and second not and what's the difference between them?

Thanks for your answers!


Ok, the reason is bad CCSprite design. If we look to CCSprite.h, we can find:

-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
    NSAssert(texture!=nil, @"Invalid texture for sprite");
    // IMPORTANT: [self init] and not [super init];
    if( (self = [self init]) )
}

And thats the reason. Instead of [super init] this method calls [self init], and creates recursion ([self init]-[super InitWithFile:]-[self initWithTexture]-[self init]-...).

.

So, the simplest way to solve this problem - just re-name your init method to something else (for example "initialize") and call it instead of init: [[MyCustomSprite alloc] initialize].


Another approach that may work is just replace your code by this one:

- (id)init
{
    self = [super init];
    if (self != nil)
    {
        CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@"my_image_name.png"];
        CGRect rect = CGRectZero;
        if (texture != nil)
        {
            rect.size = texture.contentSize;
        }
        [self setDisplayFrame:[CCSpriteFrame frameWithTexture:texture rect:rect]];
    }
    return self;
}

And a simpler way, if you are using CCSpriteFrameCache, would be just setting the display frame by

[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"my_image_name.png"]

Hope to help somebody!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜