在看了一些box2d 知识后,做了个小车的demo
在HelloWorldScene.h中,我以一个矩形作为车的主体,请看以下
virtual bool init();
static cocos2d::CCScene* scene();
CREATE_FUNC(HelloWorld);
void update(float time);
virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent); //处理按下事件
virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent); //处理按下并移动事件
virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); //处理松开事件
b2Body *ground;
b2World *world;
b2Body *m_car;
b2Body *m_wheel1;
b2Body *m_wheel2;
b2WheelJoint* m_spring1; //轮子链接
b2WheelJoint* m_spring2;
float32 m_hz;
float32 m_zeta;
float32 m_speed;
b2Fixture *carbody;//车子主体
b2Fixture *w1;//轮子材料
b2Fixture *w2;//轮子材料
b2MouseJoint *_mouseJoint;//鼠标链接
bool flag;
在HelloWorldScene.cpp中的init()实现
m_hz = 4.0f;
m_zeta = 0.7f;
m_speed = 50.0f;
CC_BREAK_IF(! CCLayer::init());
CCSize winsize=CCDirector::sharedDirector()->getWinSize();
b2Vec2 vector=b2Vec2(0.0f,-10.0f);
bool dosleep=true;
world=new b2World(vector);
world->SetAllowSleeping(dosleep);
world->SetContinuousPhysics(true);
b2BodyDef b2bodydef;
b2bodydef.position.Set(0.0f,0.0f);
ground=world->CreateBody(&b2bodydef);
b2PolygonShape groundBox;
//buttom
groundBox.SetAsBox(winsize.width/PTM_RATIO, 0, b2Vec2(0, 0), 0);
ground->CreateFixture(&groundBox, 0);
// top
groundBox.SetAsBox(winsize.width/PTM_RATIO, 0, b2Vec2(0, winsize.height/PTM_RATIO), 0);
ground->CreateFixture(&groundBox, 0);
// left
groundBox.SetAsBox(0, winsize.height/PTM_RATIO, b2Vec2(0, 0), 0);
ground->CreateFixture(&groundBox, 0);
// right
groundBox.SetAsBox(0, winsize.height/PTM_RATIO, b2Vec2(winsize.width/PTM_RATIO, 0), 0);
ground->CreateFixture(&groundBox, 0);
flag=false;
CCSprite *sprite=CCSprite::create("CloseNormal.png");
this->addChild(sprite);
CCSprite *sprite1=CCSprite::create("CloseNormal.png");
this->addChild(sprite1);
CCSprite *sprite2=CCSprite::create("rect.png");
this->addChild(sprite2);
b2PolygonShape chassis;
chassis.SetAsBox(sprite2->getContentSize().width/PTM_RATIO/2, sprite2->getContentSize().height/PTM_RATIO/2);
b2CircleShape circle;
circle.m_radius = 0.4f;
b2BodyDef bd;
bd.userData=sprite2;
bd.type = b2_dynamicBody;
bd.position.Set((winsize.width/2)/PTM_RATIO, (winsize.height/2)/PTM_RATIO);
m_car = world->CreateBody(&bd);
carbody=m_car->CreateFixture(&chassis, 1.0f);
b2FixtureDef fd;
fd.shape = &circle;
fd.density = 1.0f;
fd.friction = 0.9f;
bd.position.Set((winsize.width/2+20)/PTM_RATIO, (winsize.height/2-sprite->getContentSize().height/2)/PTM_RATIO);
bd.userData=sprite;
m_wheel1 = world->CreateBody(&bd);
w1=m_wheel1->CreateFixture(&fd);
bd.position.Set((winsize.width/2-20)/PTM_RATIO, (winsize.height/2-sprite1->getContentSize().height/2)/PTM_RATIO);
bd.userData=sprite1;
m_wheel2 = world->CreateBody(&bd);
w2=m_wheel2->CreateFixture(&fd);
b2WheelJointDef jd;
b2Vec2 axis(0.0f, 1.0f);
jd.Initialize(m_car, m_wheel1, m_wheel1->GetPosition(), axis);
jd.motorSpeed = 0.0f;
jd.maxMotorTorque = 20.0f;
jd.enableMotor = true;
jd.frequencyHz = m_hz;
jd.dampingRatio = m_zeta;
m_spring1 = (b2WheelJoint*)world->CreateJoint(&jd);
jd.Initialize(m_car, m_wheel2, m_wheel2->GetPosition(), axis);
jd.motorSpeed = 0.0f;
jd.maxMotorTorque = 10.0f;
jd.enableMotor = false;
jd.frequencyHz = m_hz;
jd.dampingRatio = m_zeta;
m_spring2 = (b2WheelJoint*)world->CreateJoint(&jd);
this->scheduleUpdate();
this->setTouchEnabled(true);
这样子即可组成一个小车了
可我们要update函数,这样才可以实现车子不断地更新位置,
int velocityIterations = 8; //速度迭代,可以调整物体的运动
int positionIterations = 1; //位置迭代,可以调整物体的位置,减少物体间的重叠。
world->Step(time,velocityIterations,positionIterations);
b2Body* node=world->GetBodyList();
while(node->GetUserData()!=NULL){
b2Body* b=node;
node=node->GetNext();
CCSprite *Sprite = (CCSprite*)b->GetUserData();
Sprite->setPosition( ccp(b->GetPosition().x*PTM_RATIO,
b->GetPosition().y*PTM_RATIO) );
Sprite->setRotation( -1*CC_RADIANS_TO_DEGREES(b->GetAngle()) );
}
在用到touch类的函数及为实现小车的点击拖移,及加一个鼠标节点。
如在void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)函数中实现
//if (_mouseJoint != NULL) return;
CCLOG("b");
CCTouch *touch = (CCTouch*)pTouches->anyObject(); //使用CCSet的方法
// 获取点在视图中的坐标(左上角为原点)
CCPoint location = touch->getLocation();
b2Vec2 p = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
CCLOG("c");
if(carbody->TestPoint(p))
{
CCLOG("d");
b2MouseJointDef md;
md.bodyA = ground;
md.bodyB = m_car;
md.target = p; //移动的目标
md.collideConnected = true; //设置碰撞链接
md.maxForce = 1000.0f * m_car->GetMass();
_mouseJoint = (b2MouseJoint *)world->CreateJoint(&md);
m_car->SetAwake(true);
flag = true;
}
if (w1->TestPoint(p))
{
CCLOG("e");
b2MouseJointDef md;
md.bodyA = ground;
md.bodyB = m_wheel1;
md.target = p; //移动的目标
md.collideConnected = true;//设置碰撞链接
md.maxForce = 1000.0f * m_wheel1->GetMass();
_mouseJoint = (b2MouseJoint *)world->CreateJoint(&md);
m_wheel1->SetAwake(true);
flag = true;
}
if (w2->TestPoint(p))
{
CCLOG("e");
b2MouseJointDef md;
md.bodyA = ground;
md.bodyB = m_wheel2;
md.target = p; //移动的目标
md.collideConnected = true;//设置碰撞链接
md.maxForce = 1000.0f * m_wheel2->GetMass();
_mouseJoint = (b2MouseJoint *)world->CreateJoint(&md);
m_wheel2->SetAwake(true);
flag = true;
}
void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)中设置位置坐标
if (_mouseJoint == NULL || flag == false) return;
CCTouch *touch = (CCTouch*)pTouches->anyObject(); //使用CCSet的方法
// 获取点在视图中的坐标(左上角为原点)
CCPoint location = touch->getLocation();
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
_mouseJoint->SetTarget(locationWorld);
void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
if(_mouseJoint != NULL && flag == true)
{
world->DestroyJoint(_mouseJoint);
_mouseJoint = NULL;
}
box2d 中demo下载 点击打开链接