RevoluteJoint Box2d 的问题
我的旋转关节有问题。当我用小盒子和 revoluteJoint 画一条线时,我注意到第一个盒子的奇怪行为。它与其他盒子分开。
您可以在这里看到它:
您可以编译它,然后你会明白我在说什么...
HelloWorldScene.h
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "Box2D.h"
#import "GLES-Render.h"
// HelloWorld Layer
@interface HelloWorld : CCLayer
{
b2World* world;
GLESDebugDraw *m_debugDraw;
}
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;
-(void) Test;
@end
HelloWorldScene.mm
// Import the interfaces
#import "HelloWorldScene.h"
//Pixel to metres ratio. Box2D uses metres as the unit for measurement.
//This ratio defines how many pixels correspond to 1 Box2D "metre"
//Box2D is optimized for objects of 1x1 metre therefore it makes sense
//to define the ratio so that your most common object type is 1x1 metre.
#define PTM_RATIO 32
// enums that will be used as tags
enum {
kTagTileMap = 1,
kTagBatchNode = 1,
kTagAnimation1 = 1,
};
// HelloWorld implementation
@implementation HelloWorld
+(id) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorld *layer = [HelloWorld node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// initialize your instance here
-(id) init
{
if( (self=[super init])) {
// enable touches
self.isTouchEnabled = YES;
// enable accelerometer
self.isAccelerometerEnabled = YES;
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCLOG(@"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);
// Define the gravity vector.
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
// Do we want to let bodies sleep?
// This will speed up the physics simulation
bool doSleep = true;
// Construct a world object, which will hold and simulate the rigid bodies.
world = new b2World(gravity, doSleep);
world->SetContinuousPhysics(true);
// Debug Draw functions
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2DebugDraw::e_shapeBit;
flags += b2DebugDraw::e_jointBit;
// flags += b2DebugDraw::e_aabbBit;
// flags += b2DebugDraw::e_pairBit;
// flags += b2DebugDraw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);
// Define the ground box shape.
b2PolygonShape groundBox;
// bottom
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
//Set up sprite
[self Test];
[self schedule: @selector(tick:)];
}
return self;
}
- (void) Test {
// Circle
b2Body *circle1;
b2BodyDef bd1;
bd1.position.Set(45.0f/PTM_RATIO, 180.0f/PTM_RATIO);
bd1.type = b2_kinematicBody;
bd1.fixedRotation = false;
bd1.allowSleep = false;
circle1 = world->CreateBody(&bd1);
b2CircleShape shapecircle1;
shapecircle1.m_radius = 0.5f;
b2FixtureDef fdcircle1;
fdcircle1.shape = &shapecircle1;
fdcircle1.density = 2.0f;
fdcircle1.friction = 2.0f;
circle1->CreateFixture(&fdcircle1);
// Boxes
b2PolygonShape shape;
shape.SetAsBox(6.0f/PTM_RATIO, 0.125f);
b2FixtureDef fd;
fd.shape = &shape;
fd.density = 20.0f;
fd.friction = 0.2f;
b2RevoluteJointDef jd;
jd.collideConnected = false;
const float32 y = 9.0f;
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set(15.0f/PTM_RATIO, y);
b2Body* prevBody = world->CreateBody(&bd);
prevBody->CreateFixture(&fd);
b2Vec2 anchor(float32(0), y);
for (int32 i = 1; i < 8; ++i)
{
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set((15.0f + (i*10))/PTM_RATIO, y);
b2Body* body = world->CreateBody(&bd);
body->CreateFixture(&fd);
b2Vec2 anchor(float32(i*10)/PTM_RATIO, y);
jd.Initialize(prevBody, body, anchor);
world->CreateJoint(&jd);
prevBody = body;
}
}
-(void) draw
{
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
world->DrawDebugData();
// restore default GL states
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
-(void) tick: (ccTime) dt
{
//It is recommended that a fixed time step is used with Box2D for stability
//of the simulation, however, we are using a variable time step here.
//You need to make an informed choice, the following URL is useful
//http://gafferongames.com/game-physics/fix-your-timestep/
int32 velocityIterations = 8;
int32 positionIterations = 1;
// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
world->Step(dt, velocityIterations, positionIterations);
//Iterate over the bodies in the physics world
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
//Synchronize the AtlasSprites position and rotation with the corresponding body
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
delete world;
world = NULL;
delete m_debugDraw;
// don't forget to call "super dealloc"
[super dealloc];
}
@end
有什么想法吗?提前致谢
i have a problem with revolutejoint. When i make a line with litlle boxes and revoluteJoint i noticed a strange behavior of my first box. it separates from rest of the boxes.
You can see it here:
You can compile it, and you'll see what im talking about…
HelloWorldScene.h
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "Box2D.h"
#import "GLES-Render.h"
// HelloWorld Layer
@interface HelloWorld : CCLayer
{
b2World* world;
GLESDebugDraw *m_debugDraw;
}
// returns a Scene that contains the HelloWorld as the only child
+(id) scene;
-(void) Test;
@end
HelloWorldScene.mm
// Import the interfaces
#import "HelloWorldScene.h"
//Pixel to metres ratio. Box2D uses metres as the unit for measurement.
//This ratio defines how many pixels correspond to 1 Box2D "metre"
//Box2D is optimized for objects of 1x1 metre therefore it makes sense
//to define the ratio so that your most common object type is 1x1 metre.
#define PTM_RATIO 32
// enums that will be used as tags
enum {
kTagTileMap = 1,
kTagBatchNode = 1,
kTagAnimation1 = 1,
};
// HelloWorld implementation
@implementation HelloWorld
+(id) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorld *layer = [HelloWorld node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
// initialize your instance here
-(id) init
{
if( (self=[super init])) {
// enable touches
self.isTouchEnabled = YES;
// enable accelerometer
self.isAccelerometerEnabled = YES;
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCLOG(@"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);
// Define the gravity vector.
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
// Do we want to let bodies sleep?
// This will speed up the physics simulation
bool doSleep = true;
// Construct a world object, which will hold and simulate the rigid bodies.
world = new b2World(gravity, doSleep);
world->SetContinuousPhysics(true);
// Debug Draw functions
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2DebugDraw::e_shapeBit;
flags += b2DebugDraw::e_jointBit;
// flags += b2DebugDraw::e_aabbBit;
// flags += b2DebugDraw::e_pairBit;
// flags += b2DebugDraw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);
// Define the ground box shape.
b2PolygonShape groundBox;
// bottom
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
//Set up sprite
[self Test];
[self schedule: @selector(tick:)];
}
return self;
}
- (void) Test {
// Circle
b2Body *circle1;
b2BodyDef bd1;
bd1.position.Set(45.0f/PTM_RATIO, 180.0f/PTM_RATIO);
bd1.type = b2_kinematicBody;
bd1.fixedRotation = false;
bd1.allowSleep = false;
circle1 = world->CreateBody(&bd1);
b2CircleShape shapecircle1;
shapecircle1.m_radius = 0.5f;
b2FixtureDef fdcircle1;
fdcircle1.shape = &shapecircle1;
fdcircle1.density = 2.0f;
fdcircle1.friction = 2.0f;
circle1->CreateFixture(&fdcircle1);
// Boxes
b2PolygonShape shape;
shape.SetAsBox(6.0f/PTM_RATIO, 0.125f);
b2FixtureDef fd;
fd.shape = &shape;
fd.density = 20.0f;
fd.friction = 0.2f;
b2RevoluteJointDef jd;
jd.collideConnected = false;
const float32 y = 9.0f;
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set(15.0f/PTM_RATIO, y);
b2Body* prevBody = world->CreateBody(&bd);
prevBody->CreateFixture(&fd);
b2Vec2 anchor(float32(0), y);
for (int32 i = 1; i < 8; ++i)
{
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position.Set((15.0f + (i*10))/PTM_RATIO, y);
b2Body* body = world->CreateBody(&bd);
body->CreateFixture(&fd);
b2Vec2 anchor(float32(i*10)/PTM_RATIO, y);
jd.Initialize(prevBody, body, anchor);
world->CreateJoint(&jd);
prevBody = body;
}
}
-(void) draw
{
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
world->DrawDebugData();
// restore default GL states
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
-(void) tick: (ccTime) dt
{
//It is recommended that a fixed time step is used with Box2D for stability
//of the simulation, however, we are using a variable time step here.
//You need to make an informed choice, the following URL is useful
//http://gafferongames.com/game-physics/fix-your-timestep/
int32 velocityIterations = 8;
int32 positionIterations = 1;
// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
world->Step(dt, velocityIterations, positionIterations);
//Iterate over the bodies in the physics world
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
//Synchronize the AtlasSprites position and rotation with the corresponding body
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
delete world;
world = NULL;
delete m_debugDraw;
// don't forget to call "super dealloc"
[super dealloc];
}
@end
Any idea? Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的情况的问题是您的第一个框围绕锚点进行 360 度旋转。这可能发生在第一个和最后一个盒子上。我认为您需要限制您的加入的 360 度旋转。您必须定义盒子可以达到的最大角度。您可以通过在关节中使用电机来做到这一点。以下是 Box2D 手册中的一些代码,用于为您的关节创建电机,
希望对您有所帮助。
The problem in your case is that your first box makes a 360 degree rotation around the anchor. This can happen to first and last box. I think you need to restrict the 360 degree rotation for your join. You have do define that maximum angle that your box can achieve. You can do it by using motors in your joints. Following is some code from Box2D manual to create motors for your joints,
I hope it helps.