1

您好,我在 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] 项目符号。contentsize.width = 0.000000 2013-08-07 16:31:43.688 Zach App[1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.688 Zach App[1320:a0b] bullet.contentsize。宽度 = 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 Zach App[1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43。839 扎克应用 [1320:a0b] bullet.contentsize.width = 0.000000 2013-08-07 16:31:43.840 扎克应用 [1320:a0b] character.contentsize.width = 64.000000 2013-08-07 16:31:43.841 扎克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.000000000000 2013-08-07 16:31:43.843 扎克应用 [1320:a0b] character.contentsize.width = 64.000000000000 2013-08-07 16:31:43.843 扎克应用 [1320:a0b] character.contentsize.width = 64.000000

4

2 回答 2

1

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

编辑:

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

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

子弹头.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

子弹头.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

播放测试.h

#import "cocos2d.h"

@interface PlayTest : CCLayer
{
    NSMutableArray *bullets;
    CCSprite *character;
    CGSize winSize;
}

@end

播放测试.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
于 2013-08-08T02:23:04.203 回答
0

理论上有以下三个原因:

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

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

于 2013-08-07T22:47:44.170 回答