Cocos2d: CCSprite initWithFile в сбоях подкласса CCSprite - PullRequest
1 голос
/ 03 сентября 2011

У меня есть проект cocos2d с пользовательским подклассом CCSprite:

MyCustomSprite.h:

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

MyCustomSprite.m:

#import "MyCustomSprite.h"
@implementation MyCustomSprite
- (id)init
{
    self = [super initWithFile:@"index.png"];
    return self;
}
@end

По какой-то странной причине этот код вылетает с "EXC_BAD_ACCESS".

Но, несмотря на это, если я инициализирую super как ususal, а затем напишу код из initSithFile и initWithTexture CCSprite, он будет работать нормально:

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;
} 

В чем причина сбоя первого примера, а второго - нет, и в чем разница между ними?

Спасибо за ваши ответы!

Ответы [ 2 ]

1 голос
/ 04 сентября 2011

Хорошо, причина в плохом дизайне CCSprite. Если мы посмотрим на CCSprite.h, мы можем найти:

-(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]) )
}

И в этом причина. Вместо [super init] этот метод вызывает [self init] и создает рекурсию ([self init]-[super InitWithFile:]-[self initWithTexture]-[self init]-...).

.

Итак, самый простой способ решить эту проблему - просто переименовать ваш метод init в другое (например, «initialize») и вызвать его вместо init: [[MyCustomSprite alloc] initialize].

0 голосов
/ 14 февраля 2012

Другой подход, который может сработать, это просто заменить ваш код следующим:

- (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;
}

И более простым способом, если вы используете CCSpriteFrameCache, было бы просто установить рамку дисплея на

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

Надеюсь кому-нибудь помочь!

...