DionysosLai2014-5-7
我们常常要移动物理世界中的某个物体,例如说石头、木块等。假设我们直接改变这些物体的位置,让这些物体尾随我们手指移动,即使这样是可行的,却违反了物理世界的基本规则。这个世界没有“上帝之手”。
换个思路,假设我们要移动物体,那是否说,就是我们要在物体上施加一个某个方向的无穷大的力量。恩,没错。就是这样。
在Box2D中,有一个比較特殊的关节类型:鼠标关节(Mouse Joint),之所以特殊,就是由于它并非物理世界中原生的物体,是来自于用户的操作。鼠标关节,能够试图将物体拖向当前鼠标光标的位置,同一时候在选择方向上没有限制。
使用鼠标关节一般有三个步骤:
1. 创建(在touchBegan中)
2. 改变鼠标关节位置(在touchMove中);
3. 销毁鼠标关节(在touchEnd中)
依照上面步骤:我们一步步创建鼠标关节:
在头文件里创建一个鼠标关节:
b2MouseJoint* m_mouseJoint;
然后在cpp文件里初始鼠标关节为NULL:
m_mouseJoint = NULL;
以下就是创建鼠标关节:
b2Vec2 vec(m_pTouchPoint.x/PTM_RATIO,m_pTouchPoint.y/PTM_RATIO); // b2Vec2 vec = b2Vec2(touchPoint.x,touchPoint.y); if(m_mouseJoint != NULL) { return false; } // Make a small box. b2AABB aabb; b2Vec2 d; d.Set(0.001f, 0.001f); aabb.lowerBound = vec - d; aabb.upperBound = vec + d; b2BodyDef bodyDef; b2Body *m_groundBody = m_world->CreateBody(&bodyDef); // Query the world for overlapping shapes. QueryCallback callback(vec); m_world->QueryAABB(&callback, aabb); if (callback.m_fixture) { b2Body* body = callback.m_fixture->GetBody(); b2MouseJointDef md; md.bodyA = m_groundBody;//一般为世界边界 md.bodyB = body;//须要拖动的物体 md.target = vec; md.maxForce = 1000.0f * body->GetMass(); m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md); body->SetAwake(true); CCLog("touch bengin "); return true; } return false;
在这里。调用了一个回调函数。因此必须在头文件里,新建一个类:
class QueryCallback : public b2QueryCallback { public: QueryCallback(const b2Vec2& point) { m_point = point; m_fixture = NULL; } bool ReportFixture(b2Fixture* fixture) { b2Body* body = fixture->GetBody(); if (body->GetType() == b2_dynamicBody) { bool inside = fixture->TestPoint(m_point); if (inside) { m_fixture = fixture; // We are done, terminate the query. return false; } } // Continue the query. return true; } b2Vec2 m_point; b2Fixture* m_fixture; };
这里要注意一个问题,就是设置鼠标关节边界时:
md.bodyA= m_groundBody;//一般为世界边界
md.bodyB= body;//须要拖动的物体
md.bodyA是我们的世界
以下就是在touchMove中改变鼠标关节的属性,代码例如以下:
m_iTouchType = TOUCH_MOVE; CCPoint point = pTouch->getLocation(); m_pTouchPoint = point; if(m_mouseJoint == NULL ) return; b2Vec2 vecMouse; vecMouse.Set((m_pTouchPoint.x)/PTM_RATIO, (m_pTouchPoint.y)/PTM_RATIO); //改变关节位置. m_mouseJoint->SetTarget(vecMouse);
最后一个当我们手指离开屏幕时。我们要销毁我们所创建的鼠标关节。在ccTouchEnded增加例如以下代码:
m_iTouchType = TOUCH_END; CCPoint point = pTouch->getLocation(); m_pTouchPoint = point; CCLOG("%f, %f", point.x, point.y); //销毁关节. if(m_mouseJoint != NULL) { m_world->DestroyJoint(m_mouseJoint); m_mouseJoint =NULL; }
好。到现在为止一切ok该。
版权声明:本文博主原创文章。博客,未经同意不得转载。