从另一个类调用调度方法时出现SIGABRT错误

时间:2013-08-11 17:13:10

标签: objective-c methods cocos2d-iphone scheduled-tasks

你好我正在制作一个侧滚动Cocos2d游戏,我正在实施敌人进入游戏,所以当一个敌人完成时,另一个进入屏幕。我有让敌人按计划方法移动的方法,所以我使用performSelector方法调用另一个。

以下是代码:

#import "RedEnemy.h"

@implementation RedEnemy
+(id)createRedEnemy{
return [[[self alloc]init]autorelease];
}
-(id)init{
if((self = [super init])){

CGSize size = [[CCDirector sharedDirector]winSize];
screenWidth = size.width;
screenHeight = size.height;

screenBounds = [[UIScreen mainScreen] bounds];

redEnemyFlameCounter = 1;

xPoint = screenWidth - 50;
yPoint = screenHeight - 50;

    randomNumberRedEnemy = arc4random() % 18;

    [self schedule:@selector(redEnemyFlight:)interval:randomNumberRedEnemy + 18/1.0f];
}
return self;
}

-(void)redEnemyFlight:(ccTime)delta{
redEnemy = [CCSprite spriteWithFile:@"redenemy.png"];
redEnemy.position = ccp(xPoint, yPoint);
[self addChild:redEnemy z:-1];

[self schedule:@selector(shootTheBullets:)interval:1.0f/2.0f];

CCMoveTo* redEnemyMoveDown  = [CCMoveTo actionWithDuration:3.0 position:ccp(xPoint, 70)];
CCMoveTo* redEnemyMoveUp = [CCMoveTo actionWithDuration:3.0 position:ccp(xPoint, yPoint -      60)];
CCSequence* redEnemyFloatingSequence = [CCSequence actions:redEnemyMoveDown, redEnemyMoveUp, nil];
CCRepeat* redEnemyFloatingRepeat = [CCRepeat actionWithAction:redEnemyFloatingSequence times:3];
[redEnemy runAction:redEnemyFloatingRepeat];

[self schedule: @selector(removeTheEnemy:)interval:18.0f/1.0f];

[self schedule: @selector(redEnemyFlame:)interval:1.0f/5.0f];
}

-(void)redEnemyFlame:(ccTime)delta{
redEnemyFlameCounter ++;

if (redEnemyFlameCounter % 2){
    [redEnemy setTexture:[[CCSprite spriteWithFile:@"redenemy2.png"]texture]];
}else{
    [redEnemy setTexture:[[CCSprite spriteWithFile:@"redenemy.png"]texture]];
}
}

-(void)removeTheEnemy:(ccTime)delta{
CCMoveBy* moveUp = [CCMoveBy actionWithDuration:0.5 position:ccp(70, 100)];
[redEnemy runAction:moveUp];
[self unschedule:@selector(removeTheEnemy:)];
[self performSelector:@selector(yellowEnemyFloating:) withObject:nil afterDelay:2.0f];
}
@end

这是最后一段代码片段。

#import "YellowEnemy.h"

@implementation YellowEnemy

+(id)createYellowEnemy{
return [[[self alloc]init]autorelease];
}

-(id)init{
if((self = [super init])){

    CGSize size = [[CCDirector sharedDirector]winSize];
    screenWidth = size.width;
    screenHeight = size.height;

    screenBounds = [[UIScreen mainScreen] bounds];

    yellowEnemyFlameCounter = 1;

    randomNumberYellowEnemy = arc4random() % 8;

    //[self schedule:@selector(yellowEnemyFloating:)interval:randomNumberYellowEnemy +       8 /1.0f];

}
return self;
}

-(void)yellowEnemyFloating:(ccTime)delta{
yellowEnemy = [CCSprite spriteWithFile:@"yellowenemy.png"];
yellowEnemy.position = ccp(screenWidth - 50, 50);
[self addChild:yellowEnemy z:-1];


yellowEnemyMoveDown  = [CCMoveTo actionWithDuration:2.0 position:ccp(yellowEnemy.position.x, 50)];
yellowEnemyMoveUp = [CCMoveTo actionWithDuration:2.0 position:ccp(yellowEnemy.position.x, screenHeight/2)];
yellowEnemyFloatingSequnece = [CCSequence actions:yellowEnemyMoveUp, yellowEnemyMoveDown, nil];
yellowEnemyFloatingRepeat = [CCRepeat actionWithAction:yellowEnemyFloatingSequnece times:2];
[yellowEnemy runAction:yellowEnemyFloatingRepeat];

[self schedule: @selector(yellowEnemyFlame:)interval:1.0f/5.0f];
}

-(void)yellowEnemyFlame:(ccTime)delta{
yellowEnemyFlameCounter ++;

if (yellowEnemyFlameCounter % 2){
    [yellowEnemy setTexture:[[CCSprite spriteWithFile:@"yellowenemy2.png"]texture]];
}else{
    [yellowEnemy setTexture:[[CCSprite spriteWithFile:@"yellowenemy.png"]texture]];
}
[self schedule:@selector(yellowEnemyFlight:)interval:8.0f/1.0f];

}

-(void)yellowEnemyFlight:(ccTime)delta{
yellowEnemyMoveLeft = [CCMoveTo actionWithDuration:4.0 position:ccp(-100, screenHeight/2)];
[yellowEnemy runAction:yellowEnemyMoveLeft];

[self performSelector:@selector(blueEnemyFlight:) withObject:nil afterDelay:2.0f];
}
@end

这是最后一段代码片段调用的内容:

 #import "BlueEnemy.h"


 @implementation BlueEnemy
+(id)createBlueEnemy{
return [[[self alloc]init]autorelease];
}

-(id)init{
if ((self = [super init])) {
    CGSize size = [[CCDirector sharedDirector]winSize];
    screenWidth = size.width;
    screenHeight = size.height;

    screenBounds = [[UIScreen mainScreen] bounds];

    blueEnemyFlameCounter = 1;

    xPointBlueEnemy = screenWidth - 50;
    yPointBlueEnemy = screenHeight - 100;

    //randomNumberBlueEnemy = arc4random() % 18;

    //[self schedule:@selector(blueEnemyFlight:)interval:randomNumberBlueEnemy + 18/1.0f];
}
return self;
}

-(void)blueEnemyFlight:(ccTime)delta{
blueEnemy = [CCSprite spriteWithFile:@"blueenemy.png"];
blueEnemy.position = ccp(xPointBlueEnemy, yPointBlueEnemy);
[self addChild:blueEnemy z:-1];

CCMoveTo* blueEnemyMoveDown  = [CCMoveTo actionWithDuration:3.0 position:ccp(xPointBlueEnemy, 70)];
CCMoveTo* blueEnemyMoveUp = [CCMoveTo actionWithDuration:3.0 position:ccp(xPointBlueEnemy, yPointBlueEnemy - 60)];
CCSequence* blueEnemyFloatingSequence = [CCSequence actions:blueEnemyMoveDown, blueEnemyMoveUp, nil];
CCRepeat* blueEnemyFloatingRepeat = [CCRepeat actionWithAction:blueEnemyFloatingSequence times:3];
[blueEnemy runAction:blueEnemyFloatingRepeat];

[self schedule:@selector(shootTheWaterBullets:)interval:1.0f/2.0f];

[self schedule: @selector(blueEnemyFlame:)interval:1.0f/5.0f];

[self schedule: @selector(removeTheBlueEnemy:)interval:20.0f/1.0f];
}
-(void)blueEnemyFlame:(ccTime)delta{
blueEnemyFlameCounter ++;

if (blueEnemyFlameCounter % 2){
    [blueEnemy setTexture:[[CCSprite spriteWithFile:@"blueenemy2.png"]texture]];
}else{
    [blueEnemy setTexture:[[CCSprite spriteWithFile:@"blueenemy.png"]texture]];
}
}

-(void)removeTheBlueEnemy:(ccTime)delta{
CCMoveBy* moveUpBlueEnemy = [CCMoveBy actionWithDuration:0.5 position:ccp(70, 200)];
[blueEnemy runAction:moveUpBlueEnemy];
[blueEnemy removeChild:blueEnemy cleanup:YES];
[self unschedule:@selector(removeTheBlueEnemy:)];
[self performSelector:@selector(redEnemyFlight:) withObject:nil afterDelay:2.0f];
}

@end

1 个答案:

答案 0 :(得分:2)

原因是scheduleSelector与performSelector的预期方法声明不同:

// scheduleSelector sends a delta time (float)
-(void) method:(ccTime)delta;

// performSelector sends no parameters
-(void) method;

// performSelector:withObject: sends an id parameter
-(void) method:(id)object;

所以你做不到:

[self performSelector:@selector(redEnemyFlight:) withObject:nil afterDelay:2.0f];

因为要执行的方法具有错误的签名:

-(void)redEnemyFlight:(ccTime)delta;

在这种情况下,您应该使用scheduleSelector。此外,如果您在BlueEnemy中运行上述performSelector代码,则会在BlueEnemy对象中执行选择器(即self)。要在红色敌人上实际执行选择器,你必须引用红色敌人并执行:

[redEnemy performSelector: and so on ];

PS:避免在外来对象中调度选择器,而是向外部对象发送消息,并在该方法中启动调度。每个对象都应该管理它自己的选择器。