1

我的项目创建了一个炸弹,一个爆炸,然后检查爆炸中的碰撞,最后删除没有在碰撞中被击中的炸弹。此处将对此进行更详细的说明。以下代码执行此操作。

-(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在 -(void)explosionFromPoint:(CGPoint)explosionPoint withSprite: (CCSprite*)sprite; 中使用 这会以某种方式给对象一个唯一的 ID 并知道我在说哪一个。我是编码新手。

4

5 回答 5

4

您在数组中有两次相同的精灵。两个条目都被删除。如果你要使用removeObject你需要创建多个精灵对象。否则你需要使用removeObjectAtIndex.

于 2013-05-27T13:39:30.407 回答
3

@HotLicks 提到的问题是您在数组中推送相同的实例。您应该使用本地CCSprite实例,以便您的计划调用将使用不同的实例。两次添加相同实例的原因是因为placeBomb在任何事情发生之前被调用了两次,并且在第二次调用中您覆盖了您创建的第一个实例。由于_circle是一个指针,到两个计划任务将被调用时,它们都_circle将指向同一个实例。

所以改变:

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

到 :

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

circle并使用和不更新方法的其余部分_circle

于 2013-05-27T13:43:26.283 回答
2

您的代码中有问题。当您从数组中删除对象时,请尝试检查类似的内容:

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

如果您的代码工作正常。那只是从您的数组中删除的一个对象。然后我建议您检查您的removeSprite方法打印sprite对象以检查出了什么问题。

如果您使用相同的精灵对象,我认为您可以使用标签值。

于 2013-05-27T13:43:25.507 回答
1

您可能两次添加了相同的(个人)精灵?

您可以记录对象本身,而不是记录具有计数的变量。它将打印其描述的值。NSObject这将默认打印出所有子类的类和地址。实际上NSMutableArray(和类似的 NS ......类)打印得很好。

NSLog ("%@",myObj); 

这样做你可能会更清楚地看到真正发生的事情。

于 2013-05-27T13:44:48.807 回答
1

在创建炸弹时不要使用类变量并尝试....

CCSprite * _circle = [[CCSprite alloc]initWithFile:@"Circle.png"];
于 2013-05-27T13:47:52.467 回答