【问题标题】:cocos2d sprite collision detection, one sprite sometimes has a contentSize.width of 0.000000cocos2d精灵碰撞检测,一个精灵有时contentSize.width为0.000000
【发布时间】:2013-08-09 04:59:55
【问题描述】:

您好,我在 cocos2d 游戏中遇到碰撞检测问题。我正在开发一款需要测试子弹是否击中角色的游戏。我正在使用 CGRectIntersectsRect 方法来查看是否发生碰撞。在模拟器中,您可以看到子弹穿过角色,但没有任何反应。如果子弹击中角色,我希望角色消失。在我的代码中,我有一个 CCLOG 语句,如果子弹击中角色,则输出“COLLISION”。此外,我还有另外两个 CCLOG 语句,它们输出项目符号和字符的 contentSize.width。子弹的 contentSize.width 应该是 20.0 但有时它会输出宽度为 0。这是碰撞检测的代码。

-(void)testForBulletCollision:(ccTime)delta{
CCLOG(@"bullet.contentsize.width = %f",bullet.contentSize.width);
CCLOG(@"character.contentsize.width = %f",character.contentSize.width);
if (CGRectIntersectsRect([bullet boundingBox], [character boundingBox]))
{
    CCLOG(@"BULLET COLLISION");
    character.visible = NO;
    bullet.visible = NO;
}
}

这是创建角色的代码。

character = [CCSprite spriteWithFile:@"mcharacter.png"];
    character.position = ccp(screenWidth/3.4, screenHeight/2 - 100);
    [self addChild:character z:-3];

这里是创建子弹和子弹动画的代码。

-(void)shootTheBullets:(ccTime)delta{
bullet = [CCSprite spriteWithFile:@"thebullet.png"];
bullet.color = ccRED;
bullet.position = redEnemy.position;
[self addChild:bullet z:-1];
bulletRect = CGRectMake(bullet.position.x - (bullet.contentSize.width/2),
                        bullet.position.y - (bullet.contentSize.height/2),
                        bullet.contentSize.width,
                        bullet.contentSize.height);


CCLOG(@"bullet.contentSize.width = %f", bullet.contentSize.width);
bulletMoveLeft = [CCMoveTo actionWithDuration:4.0 position:ccp(-screenWidth,       screenHeight/2)];
[bullet runAction:bulletMoveLeft];

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

-(void)stopBullets:(ccTime)delta{
[self unschedule:@selector(shootTheBullets:)];
}

这是输出。

2013-08-07 16:31:43.637 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.638 Zach App[1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.638 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.638 Zach App[1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.639 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.639 Zach App [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.685 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.686 Zach App [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.686 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.687 Zach App [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.687 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.688 扎克应用 [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.688 Zach App [1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.689 Zach App[1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.689 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.690 Zach App [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.691 Zach App[1320:a0b] bullet.contentSize.width = 20.000000 2013-08-07 16:31:43.836 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.837 Zach App [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.838 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.838 扎克应用 [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.839 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.840 Zach App[1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.841 Zach App[1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.842 Zach App [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.843 Zach App[1320:a0b] bullet.contentsize.width = 20.000000 2013-08-07 16:31:43.843 Zach App[1320:a0b] character.contentsize.width = 64.000000

【问题讨论】:

    标签: objective-c cocos2d-iphone


    【解决方案1】:

    每次调用“shootTheBullets”时,都会替换“bullet”指向的指针,我猜这就是内容大小报告为 0 的原因,因为指针不再指向原始对象。您应该以数组或类似的形式收集子弹并遍历这些子弹以查看边界框是否与您的角色相交。

    编辑:

    我不知道为什么当你放入一个 CCSprite 时你会得到一个 CCNode,但无论如何,这是你的基本要求的一个简单的 sn-p - 子弹,一个角色,子弹伤害,角色损坏。

    免责声明:它适用于 cc2d 1.1,非 ARC 。这是我现在用得着的。

    Bullet.h

    #import "CCSprite.h"
    
    @interface Bullet : CCSprite
    {
        float damage;
        CGPoint velocity;
    }
    
    @property float damage;
    @property CGPoint velocity;
    
    +(Bullet *) bulletWithDamage:(float) damage andVelocity:(CGPoint) velocity;
    
    @end
    

    Bullet.m

    #import "Bullet.h"
    @implementation Bullet
    @synthesize damage, velocity;
    +(Bullet *) bulletWithDamage:(float) damage andVelocity:(CGPoint) velocity
    {
        Bullet *bullet = [[[self alloc] initWithFile:@"Icon.png"] autorelease];
        bullet.damage = damage;
        bullet.velocity = velocity;
        bullet.scale = 0.2f;
        return bullet;
    }
    
    -(id) init
    {
        if( (self = [super init]) )
        {}
        return self;
    }
    @end
    

    PlayTest.h

    #import "cocos2d.h"
    
    @interface PlayTest : CCLayer
    {
        NSMutableArray *bullets;
        CCSprite *character;
        CGSize winSize;
    }
    
    @end
    

    PlayTest.m

    #import "PlayTest.h"
    #import "Bullet.h"
    
    @implementation PlayTest
    
    -(id) init
    {
        if( (self=[super init]))
        {
            winSize = [CCDirector sharedDirector].winSize;
            bullets = [[NSMutableArray alloc] initWithCapacity: 10];
    
            character = [CCSprite spriteWithFile:@"Icon.png"];
            character.position = ccp(winSize.width/3.4f, winSize.height/2.0f - 100.0f);
            [self addChild:character z:-3];
    
            [self schedule:@selector(shootTheBullets:) interval:1.0f repeat: 10 delay: 3.0f];
            [self scheduleUpdate];
        }
    
        return self;
    }
    
    -(void)shootTheBullets:(ccTime)delta{
    
        float randX = CCRANDOM_0_1() * 0.5f;
        Bullet *b = [Bullet bulletWithDamage:5.0f andVelocity:ccp( randX, -1.0f)];
        b.position = ccp(40.0f, winSize.height);
        [bullets addObject:b];
    
        [self addChild: b];
    
    }
    
    -(void) update:(ccTime)dt
    {
        [self moveTheBullets];
        [self checkCollisions];
    }
    
    -(void) moveTheBullets
    {
        for (int i=0; i< bullets.count; i++)
        {
            Bullet *b = (Bullet *)[bullets objectAtIndex:i];
            b.position = ccpAdd(b.position, b.velocity);
        }
    }
    
    -(void) checkCollisions
    {
        NSMutableArray *collisions = [NSMutableArray arrayWithCapacity:10];
        BOOL characterHit = NO;
        for (int i=0; i< bullets.count; i++)
        {
            Bullet *b = (Bullet *)[bullets objectAtIndex:i];
            if(CGRectIntersectsRect(character.boundingBox, b.boundingBox) )
            {
                NSLog(@"bullet collision with character");
                [collisions addObject: b];
                characterHit = YES;
            }
            else if (b.position.y < 0.0f)
            {
                NSLog(@"bullet went off screen without hitting anything");
                [collisions addObject: b];
                b.damage = 0.0f;
            }
        }
    
        for (int i=0; i< collisions.count; i++)
        {
            Bullet *b = (Bullet *)[collisions objectAtIndex:i];
    
            // you could damage the character here, something like:
            // characterDamage -= b.damage
    
    
            [self removeChild:b cleanup:YES];
            [bullets removeObject: b];
            NSLog(@"bullets count is %d", bullets.count);
        }
    
        if(characterHit) // show character got damaged
        {
            if( ![character numberOfRunningActions])
            {
                id one = [CCActionTween actionWithDuration:0.1f key:@"opacity" from:255 to:128];
                id two = [CCActionTween actionWithDuration:0.1f key:@"opacity" from:128 to:255];
                id onetwo = [CCSequence actions: one, two, nil];
                [character runAction: onetwo];
            }
        }
    }
    
    -(void) dealloc
    {
        [bullets release];
        [super dealloc];
    }
    
    @end
    

    【讨论】:

    • 你好,我添加了一个名为arrayOfBullets的数组并写了[arrayOfBullets addObject:bullet]; [bullet runAction: bulletMoveLeft] 之后;在shootTheBullets 方法中。然后我在 testForBulletCollision 方法中的 if 语句之前添加了 for (bullet in arrayOfBullets){ ,但我仍然得到相同的结果。我做错了什么??
    • 很难在没有看到更多代码的情况下判断..您是否在其他地方删除项目符号,而不仅仅是将它们设置为“可见=否”?你摆脱了 ivar 'bullet' 吗?
    • 我没有删除任何子弹,只是创建它们,对它们执行 CCAction,将它们添加到数组中,然后遍历数组以查找是否有任何子弹碰撞。我的输出是一样的。我所有的代码都可以吗??
    • 正如我对 LearnCocos2D 所说的,子弹 CCSprite 属于 CCNode,他说这可能是子弹的 contentSize.width 为 0 的原因。你认为这就是数组不起作用的原因吗??
    • 感谢您的快速回复和解答!你给我的代码有效!
    【解决方案2】:

    理论上有三个原因:

    • bullet 在您记录其 contentSize 时为 nil
    • bullet 的 contentSize 为 nil,因为它要么是 CCNode,要么是没有纹理的“可视”节点
    • bullet 的 contentSize 已修改

    第一个很容易测试(断言非零)。第二个是验证子弹实际上是正确的类(例如使用 isKindOfClass:)。最后一个你可以通过在 CCNode 的 setContentSize: 方法中添加断点或记录来测试。

    【讨论】:

    • 感谢您的快速回答!我发现子弹是一个CCNode。我该如何解决这个问题??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-05
    相关资源
    最近更新 更多