问题
I am developing a casino roulette game in box2d. As you know in this game a ball/dice will be in a circular spinning wheel.
First I tried with b2circleShape but it didn't work. I mean that the ball is not sitting inside the circular shape.
Then I tried with b2EdgeShape. But for the b2edgeShape I need to create as many vertices as I can to build a smooth circular surface.
Is there anyway that I can create such circle shapes which are not polygons or which are not solid polygons?
If have any solution please let me know
回答1:
You can do this using a single body for the roulette wheel. Use a circle shape for the "inner" part of it and a chain shape for the "outer" part of it.
You should probably use "spikes" in the chain shape to add something for the ball to bounce off of. Here is the main creation function:
void MainScene::CreateBody()
{
const float32 INNER_RADIUS = 2.50;
const float32 OUTER_RADIUS = 3.0;
const float32 BALL_RADIUS = 0.1;
const uint32 DIVISIONS = 36;
Vec2 position(0,0);
// Create the body.
b2BodyDef bodyDef;
bodyDef.position = position;
bodyDef.type = b2_dynamicBody;
_body = _world->CreateBody(&bodyDef);
assert(_body != NULL);
// Now attach fixtures to the body.
FixtureDef fixtureDef;
fixtureDef.density = 1.0;
fixtureDef.friction = 1.0;
fixtureDef.restitution = 0.9;
fixtureDef.isSensor = false;
// Inner circle.
b2CircleShape circleShape;
circleShape.m_radius = INNER_RADIUS;
fixtureDef.shape = &circleShape;
_body->CreateFixture(&fixtureDef);
// Outer shape.
b2ChainShape chainShape;
vector<Vec2> vertices;
const float32 SPIKE_DEGREE = 2*M_PI/180;
for(int idx = 0; idx < DIVISIONS; idx++)
{
float32 angle = ((M_PI*2)/DIVISIONS)*idx;
float32 xPos, yPos;
xPos = OUTER_RADIUS*cosf(angle-SPIKE_DEGREE);
yPos = OUTER_RADIUS*sinf(angle-SPIKE_DEGREE);
vertices.push_back(Vec2(xPos,yPos));
xPos = OUTER_RADIUS*cosf(angle)*.98;
yPos = OUTER_RADIUS*sinf(angle)*.98;
vertices.push_back(Vec2(xPos,yPos));
xPos = OUTER_RADIUS*cosf(angle+SPIKE_DEGREE);
yPos = OUTER_RADIUS*sinf(angle+SPIKE_DEGREE);
vertices.push_back(Vec2(xPos,yPos));
}
vertices.push_back(vertices[0]);
chainShape.CreateChain(&vertices[0], vertices.size());
fixtureDef.shape = &chainShape;
_body->CreateFixture(&fixtureDef);
// Create some "spikes" for the ball to bounce off of.
// Start it spinning
_body->SetAngularVelocity(M_PI/8);
// NOW create a ball to bounce around inside...
bodyDef.position = Vec2((INNER_RADIUS+OUTER_RADIUS)/2,0);
_ballBody = _world->CreateBody(&bodyDef);
circleShape.m_radius = BALL_RADIUS;
fixtureDef.shape = &circleShape;
_ballBody->CreateFixture(&fixtureDef);
// Give it some velocity so it starts to bounce.
_ballBody->SetLinearVelocity(Vec2(-0.5,0.5));
}
This is what it looks like:
I created a demo of this. Give the ball some initial velocity and it will bounce a little, but quickly becomes stuck on the outside (centrifugal force?). To make this work, you will probably need to keep exciting the ball to make it bounce for a while, till you make it "attract" to a well/sensor point where you want it to end up.
Or you could use a second chain fixture a little inside the outer chain, which is "smooth". Then remove it when you want the ball to settle down. No matter what, you will need to use forces to keep the ball moving for a bit till you want it to settle down if you want it to look like a roulette ball in play.
I posted the entire project (Cocos2d-x, c++) to github here.
You can find articles about using Box2d on my site here.
Was this helpful?
来源:https://stackoverflow.com/questions/20093032/how-to-create-a-circle-shape-without-solid-polygon-or-non-solid-circle