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 

, 당신은이 대신에 내가 원한 사람의 삭제 것을 볼 수 있습니다. 어떻게이 동작을 방지하거나 적절한 스프라이트 만 죽일 수 있도록 사용자 정의 할 수 있습니까?

편집 : 내가 생각 명확하게 그 나는에 sprite을 사용할 때 - (무효) explosionFromPoint : (CGPoint) explosionPoint withSprite : (CCSprite *) 스프라이트; 이것은 어떻게 든 개체에 고유 한 ID를 부여하고 내가 말한 것을 알 수 있습니다. 나는 코딩에 익숙하지 않다.

+0

을 폭탄을 만드는 동안 클래스 변수를 사용하지 마십시오! –

+0

이 결과는 매 실행마다 발생합니까? – giorashc

+0

어디에서 스프라이트 객체를 만들었습니까? 삭제하기 전에 배열에 값을 인쇄 해보십시오. 항상 동일한 객체가 추가 될 수 있습니다. – Durgaprasad

답변

3

@HotLicks에서 언급 한 문제는 배열에서 같은 인스턴스를 푸시하는 것입니다. 예약 된 호출에서 다른 인스턴스를 사용하려면 로컬 CCSprite 인스턴스를 사용해야합니다. 같은 인스턴스를 두 번 추가하는 이유는 무엇이든 일어나기 전에 placeBomb이 두 번 호출되기 때문이며 두 번째 호출에서는 이 먼저 작성한을 덮어 씁니다. _circle은 예약 된 작업이 모두 호출 될 때까지 포인터이므로 _circle과 동일한 인스턴스를 가리 킵니다.

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

에 :

그래서 변경

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

circle하지 _circle과 방법의 나머지 부분을 업데이트합니다.

+0

아, 알 겠어! 어리석은 사람들은 내가 어떻게 말하고 있는지 알 수있는 마법 같은 방법을 얻을 것이라고 생각합니다. 이걸 고쳤어, 고마워. 또한 도움을 주려는 다른 사람들 덕택입니다. –

4

배열에 동일한 스프라이트가 두 번 있습니다. 두 항목이 모두 제거됩니다. removeObject을 사용하려면 여러 개의 스프라이트 객체를 만들어야합니다. 그렇지 않으면 removeObjectAtIndex을 사용해야합니다.

2

코드에 문제가 있습니다. 당신이 배열에서 객체가 이렇게 제거 할 때 그런 일을 확인하십시오 :

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

을 코드가 잘 작동합니다. 이는 배열에서 하나의 객체 만 제거됩니다. 그런 다음 removeSprite 방법 print sprite 개체가 잘못되었는지 확인하는 것이 좋습니다.

동일한 스프라이트 개체를 사용하는 경우 태그 값을 사용할 수 있다고 생각합니다.

+0

이 문제는 항상 추가되는 새로운 폭탄 외에도 "checkForDamage"에서 제거 될 수 있다는 점입니다. –

1

동일한 (개별) 스프라이트를 두 번 추가했을 것입니까?

카운트가있는 변수를 로깅하는 대신 개체 자체를 기록 할 수 있습니다. 설명의 가치를 인쇄합니다. 그러면 기본값 당 모든 NSObject 하위 클래스의 클래스와 주소가 인쇄됩니다.사실 NSMutableArray (그리고 유사한 NS ... 클래스)이 꽤 잘 인쇄됩니다. 이렇게

NSLog ("%@",myObj); 

그래서 당신은 아마 더 명확 정말 무슨 일이 일어 나는지. 메신저 SO 요구하는 이유를 먹으 렴 -

1

는 @Divyu는 분명히 뭔가 잘못 프로그래머 ....

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

@downvoter 내게 downvote의 공명을 말해. –

+0

나는 downvoter가 아니지만 나는 이유가 이것이라고 생각할 것이다. 클래스 변수를 사용하는 좋은 이유가 없다면 클래스 varialbes를 사용하지 않는 것이 꽤 좋은 genral 문이지만 실제로 문제를 해결하지는 못합니다. 문제를 해결할 수는 있지만 문제의 원인을 실제로 설명하지는 않습니다. 클래스 변수를 사용하는 경우에도 문제가 해결 될 수 있습니다. –

관련 문제