coco2d-x 基於視口的地圖設計

<pre name="code" class="plain">

基於視口的地圖設計

DionysosLai 2014-06-14

         第三人稱遊戲,玩家是處在“上帝視角”掌控着整個遊戲。因此,遊戲設計中,我們要讓遊戲主角處於整個屏幕中央或者屏幕的大部分區域內,像《超級瑪麗》、《天天酷跑》等一些遊戲,細心點玩家就會發現主角在移動過程中,基本處於在同一個位置、或者在一定範圍內,主角移動時,背景不會移動,但是當超出整個範圍內,那麼背景就會跟着移動了。統統這些設計,基本上就是基於視口的地圖設計了。比較經典例子可以算是《憤怒的小鳥》了,注意這裏的遊戲主角是發射出來的那一隻小鳥。

         對於這種地圖的設計,首先先了解視口概念。視口,即設定主角在一般情況下,可以移動的範圍,超出這個範圍,那麼地圖也要跟着移動了。如果不是一般情況,比如說地圖已經移動到屏幕邊緣了,這是角色超出視口時,地圖是不能跟着角色移動的,不能就看到黑邊了。對於視口,如下圖所示:

圖1

         黑色區域就是黑色範圍了。但是,這樣設計的視口存在一個問題,就是當角色由於某種原因時(也許只有上帝才知道這個原因吧),進入到了4個邊角區域時,那麼角色移動了,地圖卻不會移動(比如從A向B移動),而實際情況是地圖也要跟着移動。這個問題,解決方法之一,就是判斷地圖是否到了屏幕邊緣,否則做一些處理;解決方法之二,就是重新設定視口的概念。

         第二種的視口設計如下:


圖2

              視口這樣設計,就可以避免上面存在的問題,但是有一個問題就是如果C朝箭頭方向移動時,同樣不會跨過視口,地圖也不會移動了。爲了解決這個問題,增加一條規定,就是如果角色在視口外了,且不向視口方向移動,那麼同樣地圖也要跟着角色移動了。

         Ok,到此,基於視口的地圖設計基本就是這樣了。

         那麼,下面就是問題,就是整體設計了。

         由於,遊戲中,要主角經常經常要處理一些碰撞,因此建議將主角放在地圖同一層。由於這樣設計,保存角色位置的不變動,在地圖移動時,角色要朝着反方向移動了。

         下面就是一些設計的一些重點了。

         設計1 地圖和角色的移動設計:

         移動,歸根到底,就三種移動方式:

1. 角色和屏幕一起移動;

2. 角色移動、屏幕不移動;

3. 角色和地圖均不移動------比方說,角色碰到障礙物了,要停止下來。

代碼如下:

enum	/// 移動狀態
	{
		MAP_E_MOVE_ALL,		///< 地圖和角色均移動
		MAP_E_MOVE_ROLE,	///< 角色移動
		MAP_E_MOVE_STOP,	///< 地圖和角色均不能移動
	};

設計2 如何設置更改移動狀態:

時時檢測三種情況,1. 角色是否在視口內;2. 角色在視口外了,但是否有朝着視口移動的趨勢;3. 角色是否碰到障礙物了。

         代碼如下:

do 
	{
		/// 首先預判斷主角是否將會超出視口外並且當前在視口內
		if (isRoleInView(ccp(0,0)))
		{
			m_iMoveState = MAP_E_MOVE_ALL;	///< 地圖和主角一起移動
		}
		else
		{
			/// 已經在視口外面了,就判斷是否有想視口移動趨勢
			if (roleToView(pointBy))
			{
				m_iMoveState = MAP_E_MOVE_ROLE;	///< 主角移動
			}
			else
			{
				m_iMoveState = MAP_E_MOVE_ALL;	///< 地圖和主角一起移動
			}
		}

		if (isCollision(ccpMult(pointBy, 2.f)))
		{
			m_iMoveState = MAP_E_MOVE_STOP;
		}

	} while (0);

設計3 地圖調整

                   根據移動狀態,每時每刻都要移動地圖,那麼需要記錄每一幀移動的大小,再判斷         是否超出屏幕了,根據上下左右四個方向調整位置。

          

         設計4 如何移動

不建議使用引擎自帶的moveBy函數,這是由於我們要時刻檢測原因。因此,需要記錄我們要移動的位置,根據角色位置(相信在平板上,玩家點擊的位置,就是希望角色到達的位置),換算出相對向量。然後每一幀要移動距離乘於相對向量的單位向量了。

         代碼如下:

	float m_fMoveDistance;				///< 記錄每次移動的距離
	cocos2d::CCPoint m_moveVector;		///< 移動向量
	float m_fMoveSpeed;				///< 移動速度

設計5 地圖顯示設計問題

                   屏幕大小就這麼大,一張地圖,就有一個屏幕大小,一個屏幕最多隻能顯示四張地         圖,因此,我們可以讓不在屏幕內的地圖暫時消失起來,這樣可以大大提高遊戲效率。     ---在示例Demo中,我們設計了100*100的地圖,運行起來非常流暢。同樣,如果有相

         同的地圖,可以使用CCSpriteBatchNode。

    代碼如下:在函數void setMapVisible(void);中

        其實,對於一些不在地圖中顯示道具、物品也可以採用這個方法。目前代碼中,沒有這一    優化,後期要加上。

   

好了,基本上問題的解決了。源代碼下載,請登入我的GitHup網址:https://github.com/DionysosLai/MapLayer。歡迎大家下載。

 

對於,目前的設計,經過了遊戲《超級挖地機》的檢測,不存在問題。但存在一個設計bug,完全無法避免,就是在如圖的情況下:


A朝着箭頭的發現移動,如果A比較偏向屏幕右邊,那麼移動感覺好差啊。




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