cocos2d之Box2D詳解 鼠標關節實現

cocos2d之Box2D詳解 鼠標關節實現

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 \n");

		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了。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章