cocos2d之Box2D詳解 刪除物理世界對象

cocos2d之Box2D詳解 刪除物理世界對象

DionysosLai 2014-5-8

         物理世界對象,有創造,就有銷燬。

         通常,我們在更新函數中會這樣寫到:

void HelloWorld::update(float dt)  
{  
	/// 第一件事情就是調用world對象的step方法,這樣它就可以進行物理仿真了。
	/// 這裏的兩個參數分別是“速度迭代次數”和“位置迭代次數”--你應該設置他們的範圍在8-10之間。(譯者:這裏的數字越小,
	/// 精度越小,但是效率更高。數字越大,仿真越精確,但同時耗時更多。8一般是個折中,如果學過數值分析,應該知道迭代步數的具體作用)。
	world->Step(dt, 10, 10);

	/// 使我們的精靈匹配物理仿真。
	for (b2Body *b = world->GetBodyList(); b; b = b->GetNext())
	{
		/// 遍歷world對象裏面的所有body,然後看body的user data屬性是否爲空,如果不爲空,就可以強制轉換成精靈對象。接下來,就可以根據body的位置來更新精靈的位置了。
		if (b->GetUserData() != NULL)
		{
			CCSprite* ballData = (CCSprite*)b->GetUserData();
			ballData->setPosition(ccp(b->GetPosition().x*PTM_RATIO, 
				b->GetPosition().y*PTM_RATIO));
			/// 弧度值轉化爲角度值 cocos2d裏面使用的是角度值,而box2d裏面使用的是弧度值。單位不統一,所以需要轉化。爲什麼前面*-1呢?
			/// 因爲cocos2d的角度是順時針,而box2d是逆時針。
			ballData->setRotation(-1*CC_RADIANS_TO_DEGREES(b->GetAngle()));
		}
	}
}

 

在這裏,我們做幾件事,一是:遍歷物理世界中的對象;將物理世界對象數據,轉換成我們的數據對象,然後更新對象的位置和旋轉度。

如果我們要銷燬其中的某個物理世界對象。通常我們會賦予我們的對象一個屬性,然後根據這個屬性來判斷是否要銷燬該對象。

如下面代碼所示:

m_world->Step(delta, 10, 10);

	/// 使我們的精靈匹配物理仿真。
	for (b2Body *b = m_world->GetBodyList(); b; ->GetNext())
	{
		
		if (b->GetUserData() != NULL)
		{
 			boxSprite* ballData = (boxSprite*) b ->GetUserData();
			if (ballData->getDead())
			{
				m_world->DestroyBody(b);
			}
			else
			{
				ballData->setPosition(ccp(b ->GetPosition().x*PTM_RATIO, 
					b ->GetPosition().y*PTM_RATIO));
			          ballData->setRotation(-1*CC_RADIANS_TO_DEGREES(b ->GetAngle()));
			}
		}
	}

Ps:ballData->getDead(),這裏的getDead函數,就是我們對對象賦予的一個屬性,來說判斷我們是否要銷燬對象。

        這段代碼有個很嚴重的問題,就是當我們銷燬對象時,這個對象的所有信息都將被消除,那麼我們將會去不到去下一個節點信息,正確的做法就是要提前獲取下一個節點,同時b->GetUserData() == NULL 情況下,我們也要獲取下一個節點,修改代碼如下:

	m_world->Step(delta, 10, 10);

	/// 使我們的精靈匹配物理仿真。
	for (b2Body *b = m_world->GetBodyList(); b; )
	{
		if (b->GetUserData() != NULL)
		{
			b2Body* b2node = b;
			b = b2node->GetNext();
 			boxSprite* ballData = (boxSprite*)b2node->GetUserData();
			if (ballData->getDead())
			{
				m_world->DestroyBody(b2node);
			}
			else
			{
				ballData->setPosition(ccp(b2node->GetPosition().x*PTM_RATIO, 
					b2node->GetPosition().y*PTM_RATIO));
				ballData->setRotation(-1*CC_RADIANS_TO_DEGREES(b2node->GetAngle()));
			}
		}
		else
		{
			b = b->GetNext();
		}
	}

 

         當然這是一個方法,如果不考慮效率的話,我們通過不修正我們對象的位置信息,我們也可以看起來,就像是將對象銷燬掉,即在刪除這段代碼即可:

	ballData->setPosition(ccp(b2node->GetPosition().x*PTM_RATIO,b2node->GetPosition().y*PTM_RATIO));
        ballData->setRotation(-1*CC_RADIANS_TO_DEGREES(b2node->GetAngle()));

         這是刪除對象一個方法,還有一個方法就是,我們可以將要刪除對象保存在一個臨時容器中,等物體鏈表遍歷完成之後,就可以刪除臨時容器中的物體了。



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