现在的位置: 首页 > 综合 > 正文

Box2D 使用setTarget 函数拖动body (结合cocos2d-x 2.0版)

2013年09月04日 ⁄ 综合 ⁄ 共 3006字 ⁄ 字号 评论关闭

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8009302

初学box2d时,觉得它拖动body的方式很奇怪。我们需要(假如已经判断了鼠标点在了body上)在ccTouchesBegan 里面构造一个b2MouseJointDef结构体,并且来两个bodyA, bodyB 关联的设置,然后target设置为鼠标在box2d物理世界的坐标【单位:米】。代码如下:看这里: http://is.gd/VoBVUJ

void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){
	if(_mj)
		return;
	CCTouch* touch=(CCTouch*)pTouches->anyObject();
	CCPoint tpos=touch->getLocation();
	b2Vec2 posInWorld(tpos.x/PTM_RATIO, tpos.y/PTM_RATIO);
	if(_carBody->GetFixtureList()->TestPoint(posInWorld)){
		b2MouseJointDef mjDef;
		mjDef.bodyA=_world->CreateBody(new b2BodyDef);
		mjDef.bodyB=_carBody;
		mjDef.target=posInWorld;
		mjDef.collideConnected=true;
		mjDef.maxForce=(float)ULONG_MAX;
		_mj=(b2MouseJoint*)_world->CreateJoint(&mjDef);
	}
} //ccTouchesBegan

其中 _mj 是 HelloWorld类的成员域:“ b2MouseJoint* _mj; ”

CCPoint tpos=touch->getLocation(); 

用来获取触摸点的GL坐标,在cocos2d-x引擎1.0版本是这么获得:

CCPoint tpos = touch->locationInView(); tpos = CCDirector::sharedDirector()->convertToGL(location);

 

然后将触摸坐标转化为box2d的世界坐标: 

b2Vec2 posInWorld(tpos.x/PTM_RATIO, tpos.y/PTM_RATIO);

并且在构造mouseJointDef 的时候target设为此坐标: 

 mjDef.target=posInWorld;

而在ccTouchesMoved 里面,我们不断地将新触摸点赋给target:

void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){
 if(!_mj)
  return;
 CCTouch* touch=(CCTouch*)pTouches->anyObject();
 CCPoint tpos=touch->getLocation();
 b2Vec2 posInWorld(tpos.x/PTM_RATIO, tpos.y/PTM_RATIO);
 _mj->SetTarget(posInWorld);
} //ccTouchesMoved

这样便实现了body在屏幕上被拖动的效果。当然别忘了在类的 init() 函数或者构造函数里先 setTouchEnabled(true); // 1.0版是 setIsTouchEnabled(true);

------------------------------------------------------

可是,“target” 究竟是什么玩意呢?记得如果不使用box2d,想实现cocos2dx 里面的精灵拖动,是这样的:

void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){
 cout<<"in ccTouchesMoved..."<<endl;
 CCTouch* touch=(CCTouch*)pTouches->anyObject();
 CCPoint start=touch->getLocation();
 CCPoint end=touch->getPreviousLocation(); 

。。。。
 CCPoint newPos=sprite->getPosition();
 newPos=ccpAdd(newPos, ccpSub(end, start));
 sprite->setPosition(newPos); 

。。。。。。。

在ccTouchesMoved 里面获取本次触摸坐标,以及前一次触摸坐标,然后将当前坐标与两次触摸坐标向量差相加,作为新坐标。这应该是很好理解的。而box2d 的target凭什么也能拖动body呢?查box2d 帮助手册,看到这样的说明:

8.10 Mouse Joint

The mouse joint is used in the testbed to manipulate bodies with the mouse.It attempts to drive a point on a body towards the current position of the cursor. There is no restriction on rotation.

The mouse joint definition has a target point, maximum force, frequency, and damping ratio. The target point initially coincides with the body’s anchor point. The maximum force is used to prevent violent reactions when multiple
dynamic bodies interact. You can make this as large as you like. The frequency and damping ratio are used to create a spring/damper effect similar to the distance joint.

Many users have tried to adapt the mouse joint for game play. Users often want to achieve precise positioning and instantaneous response. The mouse joint doesn’t work very well in that context. You may wish to consider using kinematic
bodies instead.

 

 

target 就是个‘目标’,如果将想要移动的body绑定到了 mouseJoint 对象,那么,只要不断地更新target 坐标,body就会自动朝着这个‘目标’飞。因为我们的驱动力度设的很大很大:mjDef.maxForce=(float)ULONG_MAX;
所以body飞的很快,以至于看起来就是被手指拖着移动的。如果maxForce 设的很小,那么拖动效果看起来就像是用一根很松的橡皮筋拖着走。很有意思~

 原文链接:http://blog.csdn.net/zhangxaochen/article/details/8009302

 {{OVER}}

抱歉!评论已关闭.