1. 程式人生 > >RPG遊戲 01-人物行走和地圖圖塊

RPG遊戲 01-人物行走和地圖圖塊

要開發一個遊戲,地圖是首先應該考慮的,我這裡使用的是tiled來編輯地圖。tiled對於一般的遊戲開發還行,相對通用,不過也沒有那麼強的針對性。所以在開發遊戲時要對從tiled解析的內容裡再在程式中進行相應的處理。

今天考慮的是圖塊,對於圖塊,如果簡單地分的話可以分為兩種屬性:1.priority屬性 2.pass_down  pass_left pass_right pass_up

priprity,顧名思義,就是優先順序的意思,這裡可以規定為0角色不可通過 1角色可通過,並且主角覆蓋改圖塊 2角色可通過,圖塊在角色之上。

對於pass_%s 則是指的是對於一些特殊圖塊而言。比如這種


這種圖塊主角是可以在上面的,只不過某些方向不可通過,這就需要在程式中特殊處理。上圖,主角向右是無法通行的。

關於尋路演算法,大家可以參考A*演算法,然後加上這種判斷即可,比如我在程式碼中就是每次只能移動一格。以上圖為例,下一個可以通過,但是從本圖塊到下一圖塊的pass_right 為false,這就無法過去了。反之亦然。

另外一個就是遮擋問題。這個問題雖然對於遊戲性沒什麼關係,但是卻相當重要。我的思路如下:把能和角色放生碰撞的層稱之為碰撞層,然後角色也要加到碰撞層中。對於priprity為0的,因為無法通過,自然不存在什麼遮擋問題,這時需要考慮和其他圖塊的遮擋問題。如果為1的主角的要在這些圖塊之後渲染,對應為2 的,則相反。

實現大致如下。

這裡的tmx是我自己解析的,所以我就規定,從左至右 從上至下圖塊的localZOrder依次增大。這樣能實現圖塊之間的遮擋關係。然後對於priority為2的單獨處理。程式碼大致如下。

	//儲存所有優先順序為2的圖塊
	vector<int> tileIds;
	auto tilesets = m_pTiledMap->getTilesets();

	for (auto tileset : tilesets)
	{
		auto& properties = tileset->getProperties();
		
		for(auto itMap = properties.cbegin();itMap != properties.cend();itMap++)
		{
			auto id = itMap->first;
			auto& valueMap= itMap->second;

			auto it = valueMap.find("priority");

			if (it != valueMap.cend() && it->second.asInt() == 2)
				tileIds.push_back(id + tileset->firstGrid);
		}
	}
	//設定優先順序為2的圖塊localZOrder
	auto& children = this->getCollisionLayer()->getChildren();

	for (auto child : children)
	{
		//獲取精靈的名字
		auto name = child->getName();

		if (name.empty()) continue;
		
		int id = SDL_atoi(name.c_str());
		//設定localZOrder
		if (find(tileIds.begin(),tileIds.end(),id) != tileIds.end())
		{
			child->setLocalZOrder(child->getLocalZOrder() + GameScene::CHARACTER_LOCAL_Z_ORDER);
		}
	}
<tileset name="Outside_A5" tilewidth="48" tileheight="48" tilecount="128" columns="8">
 <image source="Outside_A5.png" width="384" height="768"/>
 <tile id="0">
  <properties>
   <property name="pass" type="bool" value="false"/>
  </properties>
 </tile>
 <tile id="88">
  <properties>
   <property name="pass_left" type="bool" value="false"/>
   <property name="pass_up" type="bool" value="false"/>
  </properties>
 </tile>

注意上面的m_pTiledMap->getTilesets()獲取的是tmx地圖所使用的全部tileset。而下面的 auto& properties = tileset->getProperties()則是獲取所有屬性,其返回值是std::unordered_map<int,ValueMap>。

而接下開的則是獲取tileset的圖塊屬性來找出符合的圖塊。上面還有就是tileset對應的屬性。

這樣,在每次載入一個地圖時,都需要一次設定即可,其他的就不需要處理了。當然,另外一個解決辦法就是再有一個裝飾層,使之在碰撞層後渲染,不過這樣需要細心,也挺麻煩的。這個可以參考這個http://blog.csdn.net/lufy_Legend/article/details/17748629

發一張遮擋的圖片。