box2d中检测钻石形状的问题

发布于 2024-11-01 09:24:19 字数 4955 浏览 1 评论 0原文

我做了一个简单的游戏。

它有许多钻石图像和一个球。当球与菱形接触时发生碰撞。在我的应用程序中,当球接触边缘时,碰撞正常工作,但当球接触角落时,碰撞不起作用。

代码已听到..

- (id)init {

if ((self=[super init])) {

    CGSize winSize = [CCDirector sharedDirector].winSize;

    self.isTouchEnabled = YES;

    self.isAccelerometerEnabled=YES;
    // Create a world
    b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
    bool doSleep = true;
    _world = new b2World(gravity, doSleep);

    // Create edges around the entire screen
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0,0);
    _groundBody = _world->CreateBody(&groundBodyDef);
    b2PolygonShape groundBox;
    b2FixtureDef groundBoxDef;
    groundBoxDef.shape = &groundBox;
    groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
    _bottomFixture = _groundBody->CreateFixture(&groundBoxDef);
    groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
    _groundBody->CreateFixture(&groundBoxDef);
    groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
    _groundBody->CreateFixture(&groundBoxDef);
    groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0));
    _groundBody->CreateFixture(&groundBoxDef);

    // Create sprite and add it to the layer
    CCSprite *ball = [CCSprite spriteWithFile:@"ball1.png" rect:CGRectMake(0, 0, 16,16)];
   // ball.position = ccp(180, 400);
    ball.tag = 1;

// Create ball body 
    b2BodyDef ballBodyDef;
    ballBodyDef.type = b2_dynamicBody;
    ballBodyDef.position.Set(180/PTM_RATIO, 450/PTM_RATIO);
    ballBodyDef.userData = ball;
     ballBody = _world->CreateBody(&ballBodyDef);

    // Create circle shape
    b2CircleShape circle;
    circle.m_radius = 16/PTM_RATIO;
    //circle.m_radius = 50/PTM_RATIO;

    // Create shape definition and add to body
    b2FixtureDef ballShapeDef;
    ballShapeDef.shape = &circle;
    ballShapeDef.density = 1.0f;
    ballShapeDef.friction = 0.0f; // We don't want the ball to have friction!
    ballShapeDef.restitution = 0.0f;
    _ballFixture = ballBody->CreateFixture(&ballShapeDef);

    // Give shape initial impulse...
    b2Vec2 force = b2Vec2(0, 0);
    ballBody->ApplyLinearImpulse(force, ballBodyDef.position);

    for(int i = 0; i < 5; i++) 


    {
        static int padding=25;



        CCSprite *block = [CCSprite spriteWithFile:@"diamond2.png"];
       int  xOffset = padding+block.contentSize.width/5+((block.contentSize.width+padding)*i);
        block.position = ccp(xOffset, 250);
        block.tag = 2;
        [self addChild:block];


        // Create block body
        b2BodyDef blockBodyDef;
       // blockBodyDef.type = b2_dynamicBody;
        blockBodyDef.position.Set(xOffset/PTM_RATIO, 400/PTM_RATIO);
        blockBodyDef.userData = block;

        b2Body *blockBody = _world->CreateBody(&blockBodyDef);

        // Create block shape
        b2PolygonShape blockShape;
        blockShape.SetAsBox(block.contentSize.width/PTM_RATIO/8,
                            block.contentSize.height/PTM_RATIO/8
                            );

        // Create shape definition and add to body
        b2FixtureDef blockshapeDef;
        blockshapeDef.shape = &blockShape;
        blockshapeDef.density = 0.0;
        blockshapeDef.friction = 10.0;
        blockshapeDef.restitution = 0.1f;
        blockBody->CreateFixture(&blockshapeDef);
    }

    [self addChild:ball]; 

// Create contact listener
    _contactListener = new MyContactListener();
    _world->SetContactListener(_contactListener);

    [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background-music-aac.caf"];

    [self schedule:@selector(tick:)];

}
return self;

}

- (void)tick:(ccTime) dt {

   // bool blockFound = false;
_world->Step(dt, 10, 10);    
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {    
    if (b->GetUserData() != NULL) {
        CCSprite *sprite = (CCSprite *)b->GetUserData();     



        if (sprite.tag == 1) {
            static int maxSpeed = 20;

            b2Vec2 velocity = b->GetLinearVelocity();
            float32 speed = velocity.Length();

            // When the ball is greater than max speed, slow it down by
            // applying linear damping.  This is better for the simulation
            // than raw adjustment of the velocity.
            if (speed > maxSpeed) {
                b->SetLinearDamping(0.2);
            } else if (speed < maxSpeed) {
                b->SetLinearDamping(0.0);
            }

        }

       sprite.position = ccp(b->GetPosition().x * PTM_RATIO,
                                b->GetPosition().y * PTM_RATIO);
        sprite.rotation = 1 * CC_RADIANS_TO_DEGREES(b->GetAngle());

}
}
}

请帮助我检测菱形拐角附近的正确碰撞检测....

I make a simple game.

It has many diamond image and one ball. when ball touch with diamond shape then collision occur. in my application when ball touch on the edge then collision working correctly but when ball touch on the corner then collision is not working.

Code is hear..

- (id)init {

if ((self=[super init])) {

    CGSize winSize = [CCDirector sharedDirector].winSize;

    self.isTouchEnabled = YES;

    self.isAccelerometerEnabled=YES;
    // Create a world
    b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
    bool doSleep = true;
    _world = new b2World(gravity, doSleep);

    // Create edges around the entire screen
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0,0);
    _groundBody = _world->CreateBody(&groundBodyDef);
    b2PolygonShape groundBox;
    b2FixtureDef groundBoxDef;
    groundBoxDef.shape = &groundBox;
    groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
    _bottomFixture = _groundBody->CreateFixture(&groundBoxDef);
    groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
    _groundBody->CreateFixture(&groundBoxDef);
    groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
    _groundBody->CreateFixture(&groundBoxDef);
    groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0));
    _groundBody->CreateFixture(&groundBoxDef);

    // Create sprite and add it to the layer
    CCSprite *ball = [CCSprite spriteWithFile:@"ball1.png" rect:CGRectMake(0, 0, 16,16)];
   // ball.position = ccp(180, 400);
    ball.tag = 1;

// Create ball body 
    b2BodyDef ballBodyDef;
    ballBodyDef.type = b2_dynamicBody;
    ballBodyDef.position.Set(180/PTM_RATIO, 450/PTM_RATIO);
    ballBodyDef.userData = ball;
     ballBody = _world->CreateBody(&ballBodyDef);

    // Create circle shape
    b2CircleShape circle;
    circle.m_radius = 16/PTM_RATIO;
    //circle.m_radius = 50/PTM_RATIO;

    // Create shape definition and add to body
    b2FixtureDef ballShapeDef;
    ballShapeDef.shape = &circle;
    ballShapeDef.density = 1.0f;
    ballShapeDef.friction = 0.0f; // We don't want the ball to have friction!
    ballShapeDef.restitution = 0.0f;
    _ballFixture = ballBody->CreateFixture(&ballShapeDef);

    // Give shape initial impulse...
    b2Vec2 force = b2Vec2(0, 0);
    ballBody->ApplyLinearImpulse(force, ballBodyDef.position);

    for(int i = 0; i < 5; i++) 


    {
        static int padding=25;



        CCSprite *block = [CCSprite spriteWithFile:@"diamond2.png"];
       int  xOffset = padding+block.contentSize.width/5+((block.contentSize.width+padding)*i);
        block.position = ccp(xOffset, 250);
        block.tag = 2;
        [self addChild:block];


        // Create block body
        b2BodyDef blockBodyDef;
       // blockBodyDef.type = b2_dynamicBody;
        blockBodyDef.position.Set(xOffset/PTM_RATIO, 400/PTM_RATIO);
        blockBodyDef.userData = block;

        b2Body *blockBody = _world->CreateBody(&blockBodyDef);

        // Create block shape
        b2PolygonShape blockShape;
        blockShape.SetAsBox(block.contentSize.width/PTM_RATIO/8,
                            block.contentSize.height/PTM_RATIO/8
                            );

        // Create shape definition and add to body
        b2FixtureDef blockshapeDef;
        blockshapeDef.shape = &blockShape;
        blockshapeDef.density = 0.0;
        blockshapeDef.friction = 10.0;
        blockshapeDef.restitution = 0.1f;
        blockBody->CreateFixture(&blockshapeDef);
    }

    [self addChild:ball]; 

// Create contact listener
    _contactListener = new MyContactListener();
    _world->SetContactListener(_contactListener);

    [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background-music-aac.caf"];

    [self schedule:@selector(tick:)];

}
return self;

}

- (void)tick:(ccTime) dt {

   // bool blockFound = false;
_world->Step(dt, 10, 10);    
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {    
    if (b->GetUserData() != NULL) {
        CCSprite *sprite = (CCSprite *)b->GetUserData();     



        if (sprite.tag == 1) {
            static int maxSpeed = 20;

            b2Vec2 velocity = b->GetLinearVelocity();
            float32 speed = velocity.Length();

            // When the ball is greater than max speed, slow it down by
            // applying linear damping.  This is better for the simulation
            // than raw adjustment of the velocity.
            if (speed > maxSpeed) {
                b->SetLinearDamping(0.2);
            } else if (speed < maxSpeed) {
                b->SetLinearDamping(0.0);
            }

        }

       sprite.position = ccp(b->GetPosition().x * PTM_RATIO,
                                b->GetPosition().y * PTM_RATIO);
        sprite.rotation = 1 * CC_RADIANS_TO_DEGREES(b->GetAngle());

}
}
}

Plz help me for detect correct collsion detection near corner of the diamond shape....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无边思念无边月 2024-11-08 09:24:19

我不确定我是否理解,但看来你不是在制作钻石,而是在制作正方形/盒子:

blockShape.SetAsBox(block.contentSize.width/PTM_RATIO/8,block.contentSize.height/PTM_RATIO/8);

也许这就是你说碰撞不起作用的原因。

如果您的身体是正方形并且您的精灵是菱形,则有三种选择:

  • 或者菱形具有相等的宽度和高度,并且仅需要旋转正方形。这样碰撞应该没有问题。
  • 或者其他形状在不应该存在的情况下在正方形的(不可见)角上发生碰撞(当精灵/菱形适合正方形且正方形没有旋转或菱形的宽度!=高度需要自定义形状时)
  • 或者其他形状没有碰撞带有钻石精灵角(当正方形较小且适合钻石精灵时)。

还有其他方法可以创建自定义形状,例如:

void b2PolygonShape::Set(const b2Vec2* vertices, int32 count)
void b2PolygonShape::SetAsEdge(const b2Vec2& v1, const b2Vec2& v2)

I'm not sure i understood but it seems you are not making a diamond, you are making a square/box:

blockShape.SetAsBox(block.contentSize.width/PTM_RATIO/8,block.contentSize.height/PTM_RATIO/8);

maybe that's why you're saying collision is not working.

If your body is a square and your sprite is a diamond there are three options:

  • Or diamond has equal width and height and it's only necessary to rotate the square. Should be no problem with collision this way.
  • Or other shapes collide on the (invisible)corner of square when is not supposed to be there (when sprite/diamond fits inside square and square has no rotation or diamond has width != height needing a customized shape)
  • Or other shapes are not colliding with diamond sprite corner (when square is smaller and fits inside diamond sprite).

There are other methods to create customized shapes like:

void b2PolygonShape::Set(const b2Vec2* vertices, int32 count)
void b2PolygonShape::SetAsEdge(const b2Vec2& v1, const b2Vec2& v2)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文