在看了一些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);
if(_mouseJoint != NULL && flag == true) { world->DestroyJoint(_mouseJoint); _mouseJoint = NULL; }