Problem to detect diamond shape in box2d
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) 开发者_Go百科{
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....
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)
精彩评论