Objective c XCode Cocos2d EXC\u错误\u访问错误

Objective c XCode Cocos2d EXC\u错误\u访问错误,objective-c,xcode,cocos2d-iphone,exc-bad-access,Objective C,Xcode,Cocos2d Iphone,Exc Bad Access,我按照教程做了一个小游戏。 游戏的工作原理如下,你控制一条特殊的鱼;敌人的鱼在周围产卵,目标是吃掉其他的鱼 我的问题是,我想能够以任何顺序吃任何鱼。 现在我只能吃上一次产卵的敌人鱼 当我尝试以错误的顺序吃鱼时,它会崩溃,EXC_BAD_ACCESS code=1错误 我试着修了好几个小时,但没找到 这是我的密码: @implementation HelloWorldLayer NSMutableArray *_targets; bool ScheduleVerification=NO; NSMu

我按照教程做了一个小游戏。 游戏的工作原理如下,你控制一条特殊的鱼;敌人的鱼在周围产卵,目标是吃掉其他的鱼

我的问题是,我想能够以任何顺序吃任何鱼。 现在我只能吃上一次产卵的敌人鱼

当我尝试以错误的顺序吃鱼时,它会崩溃,EXC_BAD_ACCESS code=1错误

我试着修了好几个小时,但没找到

这是我的密码:

@implementation HelloWorldLayer
NSMutableArray *_targets;
bool ScheduleVerification=NO;
NSMutableArray *ArraySides;

-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
    CGSize winSize = [[CCDirector sharedDirector] winSize];
   player = [CCSprite spriteWithFile:@"Fish1.png"
                                           rect:CGRectMake(0, 0, 15, 15)];
    NSLog(@"//Init//");
    _targets=[[NSMutableArray alloc] init];
  [self schedule:@selector(update:)];
    [self schedule:@selector(tracks:) interval:1];
    self.isTouchEnabled = YES;
    CCSprite *background = [CCSprite spriteWithFile:@"UnderwaterBackground.png"];
    background.position = ccp(winSize.width/2, winSize.height/2);
    CGSize BBox=[background boundingBox].size;
    [background setScaleX:(winSize.width)/BBox.width];
[background setScaleY:(winSize.height)/BBox.height];
    player.position = ccp(winSize.width/2, winSize.height/2);
    [self addChild:background];
    [self addChild:player];
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"CB1");
UITouch *touch=[touches anyObject];
CGPoint location=[touch locationInView:[touch view]];
location=[[CCDirector sharedDirector]convertToGL:location];
if (location.x<player.position.x){[player setFlipX:YES];}
if (location.x>=player.position.x){[player setFlipX:NO];}

[player runAction:[CCSequence actions:
                [CCMoveTo actionWithDuration:1.5 position:location],
                nil]];   
}
-(void)spriteMoveFinished:(id)sender {
   NSLog(@"CLEANUP");
CCSprite *sprite = (CCSprite *)sender;


    [_targets removeObject:sprite];
    [self removeChild:sprite cleanup:YES];

}
-(void)addTarget {
 NSLog(@"//addTarget//");
CCSprite *target = [CCSprite spriteWithFile:@"BadFish1.png"
                                       rect:CGRectMake(0, 0, 15, 15)];

// Determine where to spawn the target along the Y axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minY = target.contentSize.height/2;
int maxY = winSize.height - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
target.tag = 1;
[_targets addObject:target];

int ranSides=arc4random()%2;

int actualSide=winSize.width;
if (ranSides==0){actualSide=0;}

target.position = ccp(actualSide, actualY);
[self addChild:target];
NSLog(@"TARGET %@",target);


// Create the actions
id actionMove = [CCMoveTo actionWithDuration:15
                                    position:ccp(winSize.width, actualY)];
if (ranSides==1){actionMove = [CCMoveTo actionWithDuration:15
                                                  position:ccp(0, actualY)];
    [target setFlipX:YES];

}

id actionMoveDone = [CCCallFuncN actionWithTarget:self
                                         selector:@selector(spriteMoveFinished:)];
[target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];

}
-(void)gameLogic:(ccTime)dt {
 NSLog(@"CB2");
[self addTarget];
ScheduleVerification=NO;

}

-(void)tracks:(ccTime)dt {
NSLog(@"CB3");
int FishInterval=arc4random()%7+3;
// [self cleanup];

if (ScheduleVerification==NO){[self schedule:@selector(gameLogic:) interval:1 repeat:0 delay: FishInterval];}
ScheduleVerification=YES;
}

- (void)update:(ccTime)dt {

//  NSMutableArray *playerToDelete = [[NSMutableArray alloc] init];
//NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
    CGRect playerRect = CGRectMake(
                                       player.position.x - (player.contentSize.width/2),
                                       player.position.y - (player.contentSize.height/2),
                                       player.contentSize.width, 
                                       player.contentSize.height);

              for (CCSprite *target in _targets) {
        CGRect targetRect = CGRectMake(
                                       target.position.x - (target.contentSize.width/2),
                                       target.position.y - (target.contentSize.height/2),
                                       target.contentSize.width,
                                       target.contentSize.height);

        if (CGRectIntersectsRect(targetRect, playerRect)) {
        [_targets removeObject:target];[self removeChild:target cleanup:YES];
 //   [targetsToDelete addObject:target];
        }
        }
}
- (void) dealloc
{
NSLog(@"DEALLOC");
[_targets release];
_targets = nil;
[super dealloc];
}

我该怎么做才能以任何顺序吃鱼?我做错了什么?

检查命中的循环看起来非常奇怪。为什么要将项目添加到targetsToDelete?我认为targetsToDelete的最终版本可能是个问题。像这样简化循环,看看会发生什么(不是在mo的Mac面前):-


您正在犯下令人发指的罪行,在遍历数组时从数组中删除元素

将代码的格式设置得稍微好一点,然后查看:

for (CCSprite *target in _targets) {
    CGRect targetRect = CGRectMake(
        target.position.x - (target.contentSize.width/2),
        target.position.y - (target.contentSize.height/2),
        target.contentSize.width,
        target.contentSize.height);
    if (CGRectIntersectsRect(targetRect, playerRect)) {
        [targetsToDelete addObject:target];
    }
    if (targetsToDelete.count > 0) {
        NSLog(@"Target Deleted");
        NSLog(@"targets %@",_targets);
        NSLog(@"target %@",target);
        [_targets removeObject:target];
        [self removeChild:target cleanup:YES];
    }
}
您有
targetsToDelete
,这一事实向我表明(无论是经过深思熟虑还是您遵循的教程),它都是为了正确地执行此操作。但有几件事出了问题

考虑这一点:

for (CCSprite *target in _targets) {
    CGRect targetRect = CGRectMake(
        target.position.x - (target.contentSize.width/2),
        target.position.y - (target.contentSize.height/2),
        target.contentSize.width,
        target.contentSize.height);
    if (CGRectIntersectsRect(targetRect, playerRect)) {
        [targetsToDelete addObject:target];
    }
}

for(CCSprite* target in targetsToDelete) {
    NSLog(@"Target Deleted");
    NSLog(@"targets %@",_targets);
    NSLog(@"target %@",target);
    [_targets removeObject:target];
    [self removeChild:target cleanup:YES];
}

[targetsToDelete removeAllObjects];

现在,您可以运行
\u目标
,将每个目标添加到
targetsToDelete
,并且在完成对
\u目标
的迭代后,可以单独删除它们。

不,不幸的是,它没有改变任何东西。它更干净,但当我吃了一条不是最后一次产卵的鱼时,我仍然会崩溃。张贴堆栈跟踪,它在哪条线上崩溃?没问题。要吸取的教训是,更整洁的代码更容易调试:)
for (CCSprite *target in _targets) {
    CGRect targetRect = CGRectMake(
        target.position.x - (target.contentSize.width/2),
        target.position.y - (target.contentSize.height/2),
        target.contentSize.width,
        target.contentSize.height);
    if (CGRectIntersectsRect(targetRect, playerRect)) {
        [targetsToDelete addObject:target];
    }
    if (targetsToDelete.count > 0) {
        NSLog(@"Target Deleted");
        NSLog(@"targets %@",_targets);
        NSLog(@"target %@",target);
        [_targets removeObject:target];
        [self removeChild:target cleanup:YES];
    }
}
for (CCSprite *target in _targets) {
    CGRect targetRect = CGRectMake(
        target.position.x - (target.contentSize.width/2),
        target.position.y - (target.contentSize.height/2),
        target.contentSize.width,
        target.contentSize.height);
    if (CGRectIntersectsRect(targetRect, playerRect)) {
        [targetsToDelete addObject:target];
    }
}

for(CCSprite* target in targetsToDelete) {
    NSLog(@"Target Deleted");
    NSLog(@"targets %@",_targets);
    NSLog(@"target %@",target);
    [_targets removeObject:target];
    [self removeChild:target cleanup:YES];
}

[targetsToDelete removeAllObjects];