2013-05-27 2 views
1

Мой проект создает бомбу, взрыв, затем проверяет наличие столкновений во взрыве и, наконец, удаляет бомбы, которые не попали в столкновение. Это объясняется более подробно here. Следующий код делает это.NSArray removeObject удаляет все объекты в массиве

-(void)placeBomb 
{ 
    NSLog(@"Bomb placed"); 
    _circle = [[CCSprite alloc]initWithFile:@"Circle.png"]; 
    CGPoint circle0position = ccp(_cat.position.x , _cat.position.y); 
    CGPoint c0TileCoordt = [self tileCoordForPosition:circle0position]; 
    CGPoint c0TileCoord = [self positionForTileCoord:c0TileCoordt]; 
    _circle.position = c0TileCoord; 
    [self addChild:_circle]; 
    id fade = [CCScaleTo actionWithDuration:3.5 scale:0]; 
    [_circle runAction:fade]; 

    double delayInSeconds = 3.0; 
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
     [self explosionFromPoint:c0TileCoordt withSprite:_circle]; 
    }); 


} 

- (BOOL)isLocationBombable:(CGPoint)tileCoord; 
{ 
    if ([self isValidTileCoord:tileCoord] && ![self isWallAtTileCoord:tileCoord]) 
    { 
     return YES; 

    } 
    else 
    { 
     return NO; 
    } 
} 

-(void)explosionFromPoint:(CGPoint)explosionPoint withSprite:(CCSprite*)sprite; 
{ 
    //int 
    explosionLenght += 1; 
    if (explosionLenght >= 7) //Just for testing purposes, don't have a way to increase it naturally. 
    { 
     explosionLenght = 1; 
    } 

    BOOL topB = YES; 
    BOOL leftB = YES; 
    BOOL bottomB = YES; 
    BOOL rightB = YES; 

    int bombX = (explosionPoint.x + 1); 
    int bombY = (explosionPoint.y + 1); 
    int bombNegX = (explosionPoint.x - 1); 
    int bombNegY = (explosionPoint.y - 1); 

    CGPoint top = ccp(explosionPoint.x, bombY); 
    CGPoint left = ccp(bombNegX, explosionPoint.y); 
    CGPoint bottom = ccp(explosionPoint.x, bombNegY); 
    CGPoint right = ccp(bombX, explosionPoint.y); 

    if (![self isLocationBombable:top]) 
    {topB = NO;} 
    if (![self isLocationBombable:left]) 
    {leftB = NO;} 
    if (![self isLocationBombable:bottom]) 
    {bottomB = NO;} 
    if (![self isLocationBombable:right]) 
    {rightB = NO;} 

    for (int i = 0; i <= explosionLenght; i++) { 

     int bombX = (explosionPoint.x + i); 
     int bombY = (explosionPoint.y + i); 
     int bombNegX = (explosionPoint.x - i); 
     int bombNegY = (explosionPoint.y - i); 

     CGPoint top = ccp(explosionPoint.x, bombY); 
     CGPoint left = ccp(bombNegX, explosionPoint.y); 
     CGPoint bottom = ccp(explosionPoint.x, bombNegY); 
     CGPoint right = ccp(bombX, explosionPoint.y); 

     CCSprite *circleTop = [[CCSprite alloc]initWithFile:@"Circle.png"]; 
     CCSprite *circleLeft = [[CCSprite alloc]initWithFile:@"Circle.png"]; 
     CCSprite *circleBottom = [[CCSprite alloc]initWithFile:@"Circle.png"]; 
     CCSprite *circleRight = [[CCSprite alloc]initWithFile:@"Circle.png"]; 
     int scaleTime = 5; 
     if ([self isLocationBombable:top] && topB == YES) 
     { 
      circleTop.position = [self positionForTileCoord:top]; 
      [self addChild:circleTop]; 
      id fadeTop = [CCSequence actionOne:[CCMoveTo actionWithDuration:1 position:circleTop.position] two:[CCScaleTo actionWithDuration:scaleTime scale:0]]; 
      [circleTop runAction:fadeTop]; 
     } 
     if ([self isLocationBombable:left] && leftB == YES) 
     { 
      circleLeft.position = [self positionForTileCoord:left]; 
      [self addChild:circleLeft]; 
      id fadeLeft = [CCSequence actionOne:[CCMoveTo actionWithDuration:1 position:circleLeft.position] two:[CCScaleTo actionWithDuration:scaleTime scale:0]]; 
      [circleLeft runAction:fadeLeft]; 
     } 
     if ([self isLocationBombable:bottom] && bottomB == YES) 
     { 
      circleBottom.position = [self positionForTileCoord:bottom]; 
      [self addChild:circleBottom]; 
      id fadeBottom = [CCSequence actionOne:[CCMoveTo actionWithDuration:1 position:circleBottom.position] two:[CCScaleTo actionWithDuration:scaleTime scale:0]]; 
      [circleBottom runAction:fadeBottom]; 
     } 
     if ([self isLocationBombable:right] && rightB == YES) 
     { 
      circleRight.position = [self positionForTileCoord:right]; 
      [self addChild:circleRight]; 
      id fadeRight = [CCSequence actionOne:[CCMoveTo actionWithDuration:1 position:circleRight.position] two:[CCScaleTo actionWithDuration:scaleTime scale:0]]; 
      [circleRight runAction:fadeRight]; 
     } 
    } 

    [currentBombs addObject:sprite]; 
    int a = [currentBombs count]; 
    NSLog(@"cBCount: %i",a); 
    NSLog(@"Explosion done, call checkdamage"); 

    [self schedule:@selector(checkDamageForBomb)]; 
    [self performSelector:@selector(removeSprite:) withObject:sprite afterDelay:5]; 
} 

-(void)removeSprite:(CCSprite *)sprite{ 
    int aa = [currentBombs count]; 
    NSLog(@"removeSprite startcall cbc: %i",aa); 


    if([currentBombs containsObject:sprite]) 
    { 
     NSLog(@"Found sprite in array, deleted!"); 
     [currentBombs removeObject:sprite]; 
     int a = [currentBombs count]; 
     NSLog(@"containObject cbc: %i",a); 
    } 
    else { 
     NSLog(@"Didn't find the object in array, didn't delete!"); 
     int a = [currentBombs count]; 
     NSLog(@"elseCO cbc: %i",a); 
    } 
    if (currentBombs.count == 0) 
    { 
     [self stopCheckDamage]; 

    } 

} 

-(void)stopCheckDamage{ 

    NSLog(@"StopCheckDamage"); 
    [self unschedule:@selector(checkDamageForBomb)]; 

} 

-(void)checkDamageForBomb{ 
    for (CCSprite* bomb in currentBombs) 
    { 
     CGPoint bombPos = [self tileCoordForPosition:bomb.position]; 

     for (int i = 0; i <= explosionLenght; i++) { 

      CGPoint playerPos = [self tileCoordForPosition:_cat.position]; 

      int bombX = (bombPos.x + i); 
      int bombY = (bombPos.y + i); 
      int bombNegX = (bombPos.x - i); 
      int bombNegY = (bombPos.y - i); 

      CGPoint centre = bombPos; 
      CGPoint top = ccp(centre.x, bombY); 
      CGPoint left = ccp(bombNegX, centre.y); 
      CGPoint bottom = ccp(centre.x, bombNegY); 
      CGPoint right = ccp(bombX, centre.y); 

      //pastebin.com/biuQBfnv 

      if (CGPointEqualToPoint(top, playerPos) || CGPointEqualToPoint(left, playerPos) || CGPointEqualToPoint(bottom, playerPos) || CGPointEqualToPoint(right, playerPos)) 
      { 
       playerHits += 1; 
       NSLog(@"Player hit %i",playerHits); 
       [currentBombs removeObject:bomb]; 
       break; 
      } 
     } 
    } 
} 

Моя проблема с методом -(void)removeSprite:(CCSprite *)sprite{. Это должно удалить только тот, с которым он был вызван, но вместо этого он убивает их всех, как вы можете видеть в этом журнале.

15:14:02.499 Tile[1549:c07] Bomb placed 
15:14:03.816 Tile[1549:c07] Bomb placed 
15:14:05.501 Tile[1549:c07] cBCount: 1 
15:14:05.501 Tile[1549:c07] Explosion done, call checkdamage 
15:14:06.818 Tile[1549:c07] cBCount: 2 
15:14:06.819 Tile[1549:c07] Explosion done, call checkdamage 
15:14:06.819 Tile[1549:c07] CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: 0.00 to 0.00 
15:14:10.503 Tile[1549:c07] removeSprite startcall cbc: 2 // has 2 
15:14:10.503 Tile[1549:c07] Found sprite in array, deleted! //Line above and under 
15:14:10.504 Tile[1549:c07] containObject cbc: 0 //Deleted 2, supposed to kill 1 
15:14:10.505 Tile[1549:c07] StopCheckDamage 
15:14:11.820 Tile[1549:c07] removeSprite startcall cbc: 0 
15:14:11.820 Tile[1549:c07] Didn't find the object in array, didn't delete! 
15:14:11.821 Tile[1549:c07] elseCO cbc: 0 
15:14:11.821 Tile[1549:c07] StopCheckDamage 

Если вы посмотрите на местоположение в приведенном выше коде, вы увидите, что она удаляет два вместо одного я хотел. Как я могу предотвратить это поведение или настроить его, чтобы убить только правильный спрайт?

Edit: Для того, чтобы уточнить я подумал, что, как я использую sprite в - (Недействительными) explosionFromPoint: (CGPoint) explosionPoint withSprite: (CCSprite *) спрайтов; это как-то просто даст уникальный идентификатор объекту и узнает, о ком я говорю. Я новичок в кодировании.

+0

@Divyu Очевидно Theres что-то неправильно - вот почему им просят ТАК! –

+0

Этот результат возникает при каждом запуске? – giorashc

+0

где у вас создан спрайт-объект? попробуйте распечатать его значения в массиве перед удалением. возможно, один и тот же объект все время добавляется. – Durgaprasad

ответ

3

Проблема, о которой упоминается @HotLicks, заключается в том, что вы нажимаете один и тот же экземпляр в массиве. Вы должны использовать локальный экземпляр CCSprite, чтобы ваши запланированные вызовы использовали разные экземпляры. Причина добавления одного и того же экземпляра дважды связана с тем, что placeBomb вызывается дважды, прежде чем что-либо произойдет, а во втором вызове переопределить первый экземпляр, который вы создали. Так как _circle является указателем к тому времени, как обе запланированные задачи будут называться _circle, укажет на тот же экземпляр в обоих случаях.

Меняем:

_circle = [[CCSprite alloc]initWithFile:@"Circle.png"]; 

To:

CCSprite *circle = [[CCSprite alloc]initWithFile:@"Circle.png"]; 

и обновить остальную часть метода с circle и не _circle.

+0

А, я вижу! Глупый из меня думать, что они каким-то образом получат волшебный способ узнать, о каком объекте я говорю. Похоже, что это исправлено, спасибо большое! Также благодаря другим людям, которые пытались помочь. –

4

У вас тот же спрайт в массиве дважды. Обе записи удалены. Если вы собираетесь использовать removeObject, вам нужно создать несколько объектов спрайтов. В противном случае вам необходимо использовать removeObjectAtIndex.

2

В коде есть что-то неправильное. Попробуйте проверить что-то подобное при удалении объекта из массива:

if([currentBombs count]>1) 
    [currentBombs removeObjectAtIndex:1]; 

Если ваш код работает нормально. это только один объект, удаленный из вашего массива. Затем я предлагаю вам проверить свой метод removeSprite на печать sprite, чтобы проверить, что происходит.

Я думаю, вы можете использовать значения тегов, если используете одни и те же объекты спрайтов.

+0

Проблема с этим заключается в том, что они могут быть удалены в «checkForDamage» в дополнение к новым добавляемым бомбам все время. –

1

Возможно, вы дважды добавили один и тот же (условный) спрайт?

Вместо регистрации переменной, имеющей счетчик, вы можете самостоятельно зарегистрировать объект. Он напечатает значение его описания. Это напечатает класс и адрес для всех подклассов NSObject по умолчанию.Фактически NSMutableArray (и аналогичные классы NS ...) печатаются достаточно хорошо.

NSLog ("%@",myObj); 

Выполнение этого действия, возможно, более четко видно, что на самом деле происходит.

1

Не используйте переменную класса при создании бомбы и попробовать ....

CCSprite * _circle = [[CCSprite alloc]initWithFile:@"Circle.png"]; 
+0

@ downvoter скажите мне, что резонанс внизу. –

+0

Я не сторонник, но думаю, причина в этом. Хотя это довольно неплохая формулировка genral, не использовать класс varialbes, если нет веской причины для использования переменных класса, это действительно не решает проблему. Он может исправить это, но на самом деле это не объясняет, в чем проблема. Проблема как таковая вполне может быть исправлена ​​даже при использовании переменной класса. –

Смежные вопросы