How to create a circle shape without solid polygon or non solid circle``

Deadly 提交于 2019-12-25 02:43:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!