cocos2d-x 3.2 之 2048 —— 第四篇 ★ 核心 ★,cocos2d-x2048
***************************************轉載請註明出處:http://blog.csdn.net/lttree******************************************
大家十一過得腫麼樣啊~
我現在的情況就是——每逢佳節 胖三斤 啊 ,胖三斤。。o(╯□╰)o。。
好了,繼續做2048,
這是第四篇啦~
這篇的內容就是對觸摸的處理喲~
就是,你上下左右滑動,相應移動~
我們先在 遊戲的宏定義類 中,建立一個枚舉方向變數:
GameDefine.h:
<span style="font-family:Comic Sans MS;">enum class MOVE_DIR{UP,DOWN,LEFT,RIGHT};</span>
然後,我們可以在 遊戲介面 進行螢幕觸摸處理了:
GameScene.h:
<span style="font-family:Comic Sans MS;">int m_x,m_y;bool m_startMove;</span>
<span style="font-family:Comic Sans MS;">void moveAllTiled( MOVE_DIR dir );</span>
m_x和m_y 的作用是 記錄螢幕開始觸摸時的座標,
m_startMove 判斷是否開始觸摸,並且在一個滑動結束前,不允許再次擷取觸摸
moveAllTiled 函數 作用 就是根據滑動的方向,對相應方向的數字塊 進行合并或者移動
GameScene.cpp—— init函數:
<span style="font-family:Comic Sans MS;">// 螢幕觸摸處理// 建立觸摸事件auto event = EventListenerTouchOneByOne::create();event -> onTouchBegan = [&](Touch *tou , Event *eve){// 記錄觸摸位置m_x = tou -> getLocation().x;m_y = tou -> getLocation().y;m_startMove = true;return true;};event -> onTouchMoved = [&](Touch *tou , Event *eve){// 記錄觸摸結束的位置int x = tou -> getLocation().x;int y = tou -> getLocation().y;// 如果這個觸摸事件開始,並且觸摸位置相差有10像素,則開始進行移動合并if( m_startMove==true && ( abs( m_x - x ) > 10 || abs( m_y - y ) >10 )){m_startMove = false;MOVE_DIR dir;// 根據起末座標位置,判斷向哪個方向移動if( abs(m_x - x) > abs(m_y - y) ){if( m_x < x )dir = MOVE_DIR::RIGHT;elsedir = MOVE_DIR::LEFT;}else{if( m_y < y )dir = MOVE_DIR::UP;elsedir = MOVE_DIR::DOWN;}moveAllTiled(dir);}};// 當前情境添加監聽器,就是可以擷取當前情境的 觸摸事件Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(event,this);</span><span style="font-family:Arial;"></span>
具體解釋,都在代碼中給出了,
然後進行對moveAllTiled函數設定:
<span style="font-family:Comic Sans MS;">void GameScene::moveAllTiled( MOVE_DIR dir ){// 根據具體方向進行,相應方向的移動switch ( dir ){case MOVE_DIR::UP:moveUp();break;case MOVE_DIR::DOWN:moveDown();break;case MOVE_DIR::LEFT:moveLeft();break;case MOVE_DIR::RIGHT:moveRight();break;default:break;}// 移動完成,隨機產生新塊newNumberTiled();}</span>
這個函數,未來還要加很多東西,
比如判定是否遊戲結束,判斷是否可以向某個方向移動,
還有音效等等。。
在moveAllTiled函數中,用到了
moveUp、moveDown、moveLeft和moveRight四個函數,下面對這四個函數進行定義,
當然,首先要在GameScene.h中進行聲明:
void moveUp();void moveDown();void moveLeft();void moveRight();
然後,先對moveUp 進行定義:
<span style="font-family:Comic Sans MS;font-size:14px;">void GameScene::moveUp( ){// 向上移動所有的塊for( int col = 0 ; col < GAME_COLS ; ++col ){for( int row = GAME_ROWS - 1 ; row >= 0 ; --row ){if( map[row][col] > 0 ){for( int row1 = row ; row1 < GAME_ROWS - 1 ; ++row1 ){// 上方是空的 才會移動if( map[row1+1][col] == 0 ){map[row1+1][col] = map[row1][col];map[row1][col] = 0;m_allTiled.at( map[row1+1][col] - 1 ) -> moveTo( row1+1 , col );}else{// 判斷, 是否可以消除// 擷取上面那格子的數字int numObj = m_allTiled.at( map[row1+1][col] - 1 ) -> m_number;// 擷取當前格子的數字int numNow = m_allTiled.at( map[row1][col] - 1 ) -> m_number;// 兩個格子數字相同if( numNow == numObj ){// 上面那一行數字X2m_allTiled.at( map[row1+1][col] - 1 ) -> doubleNumber();// 去除掉當前數字塊m_allTiled.at( map[row1][col] - 1 ) -> removeFromParent();// 擷取當前數字塊編號int index = map[row1][col];m_allTiled.erase( map[row1][col] - 1 );// 糾正所有大於index號碼的編號大小for( int r = 0 ; r < GAME_ROWS ; ++r ){for( int c = 0 ; c < GAME_COLS ; ++c ){if( map[r][c] > index ){--map[r][c];}}}// 將當前塊編號設定為0map[row1][col] = 0;}break;}}}}}}</span>
詳細解釋,代碼中也有注釋。
但還是要說一下這個原理:( 應該屬於2048的核心部分了~ )
就是從最下面一行最左面到 上面倒數第二行最右面,挨個遍曆,
每個都要和自己上面一行相應列的數字塊進行比較,
——如果本行的map值為0,則不管繼續
——如果本行map值不為0,則從本行相應列一直遍曆到倒數第二行的相應列
————如果上面那一行map值為0,則將本行與上面那一行互換(其實本行置0,上面那一行換成本線)
————否則,因為兩行都不為0,判斷兩行數值是否相等
————————若相等,則上面那一行的數值翻倍,本行數字塊移除,並對map內其他相應編號進行改變
————————若不等,則break
邏輯塊由map和Vector共同處理控制,
map儲存的是編號,就是這個塊是本圖內第幾個產生的塊,最先產生的塊,map值為1,第二個為2,等等,
而Vector是儲存這個數字塊的類,包括這個數字塊的位置,和數字塊數位值。
用這兩個控制而不是僅僅單用Vector好處就是,我們不需要遇到判斷,就要去Vector找,
而是先通過map可以判斷當前位置有沒有數字塊,
而且在隨機產生那裡,也方便很多,程式效率會得到提高。
關於,核心原理部分已經說完,現在我們可以設定一下,關於對相應數字塊的翻倍處理了:
在設定這個函數之前,要對之前的數字塊進行些處理,
我們要在函數裡擷取到 數字塊背景顏色層 和 數字顯示層,
所以,我們要對這兩個設定個Tag:
bk -> setTag( 101 );label -> setTag( 102 );
別忘了,在標頭檔聲明doubleNumber函數喲(我就不打出來了)
<span style="font-family:Comic Sans MS;font-size:12px;">void NumberTiled::doubleNumber( ){// 將數字塊的數字值翻倍this->m_number = this->m_number*2;// 擷取到背景層和數字層auto bk = this -> getChildByTag(101);Label *label = (Label *) bk -> getChildByTag(102);// 對數字層的數字,重新繪製label -> setString( StringUtils::format( "%d",m_number) );//根據值得大小,對背景層重繪顏色switch ( this -> m_number ){case 2:bk -> setColor(Color3B(230,220,210));break;case 4:bk -> setColor(Color3B(230,210,190));break;case 8:bk -> setColor(Color3B(230,150,100));label -> setColor(Color3B(255,255,255));break;case 16:bk -> setColor(Color3B(230,120,80));label -> setColor(Color3B(255,255,255));break;case 32:bk -> setColor(Color3B(230,100,90));label -> setColor(Color3B(255,255,255));break;case 64:bk -> setColor(Color3B(230,70,60));label -> setColor(Color3B(255,255,255));break;case 128:label -> setScale(0.7f);bk -> setColor(Color3B(230,190,60));label -> setColor(Color3B(255,255,255));break;case 256:label -> setScale(0.7f);bk -> setColor(Color3B(230,190,60));label -> setColor(Color3B(255,255,255));break;case 512:label -> setScale(0.7f);bk -> setColor(Color3B(230,190,60));label -> setColor(Color3B(255,255,255));break;case 1024:case 2048:label -> setScale(0.5f);bk -> setColor(Color3B(210,180,30));label -> setColor(Color3B(255,255,255));break;default:break;}}</span>
OK,來運行一下,看看效果:
怎麼樣,還可以吧~
接下來,要對 下、左、右 剩下三個方向進行函數定義:
<span style="font-family:Comic Sans MS;font-size:12px;">void GameScene::moveDown( ){// 向下移動所有的塊for( int col = 0 ; col < GAME_COLS ; ++col ){for( int row = 0 ; row < GAME_ROWS ; ++row ){if( map[row][col] > 0 ){for( int row1 = row ; row1 > 0 ; --row1 ){if( map[row1-1][col] == 0 ){map[row1-1][col] = map[row1][col];map[row1][col] = 0;m_allTiled.at( map[row1-1][col] - 1 ) -> moveTo( row1-1 , col );}else{int numObj = m_allTiled.at( map[row1-1][col] - 1 ) -> m_number;int numNow = m_allTiled.at( map[row1][col] - 1 ) -> m_number;if( numNow == numObj ){m_allTiled.at( map[row1-1][col] - 1 ) -> doubleNumber();m_allTiled.at( map[row1][col] - 1 ) -> removeFromParent();int index = map[row1][col];m_allTiled.erase( map[row1][col] - 1 );// 糾正塊的編號for( int r = 0 ; r < GAME_ROWS ; ++r ){for( int c = 0 ; c < GAME_COLS ; ++c ){if( map[r][c] > index ){--map[r][c];}}}map[row1][col] = 0;}break;}}}}}}void GameScene::moveLeft( ){// 向左移動所有的塊for( int row = 0 ; row < GAME_ROWS ; ++row ){for( int col = 0 ; col < GAME_COLS ; ++col ){if( map[row][col] > 0 ){for( int col1 = col ; col1 > 0 ; --col1 ){if( map[row][col1-1] == 0 ){map[row][col1-1] = map[row][col1];map[row][col1] = 0;m_allTiled.at( map[row][col1-1] - 1 ) -> moveTo( row , col1-1 );}else{int numObj = m_allTiled.at( map[row][col1-1] - 1 ) -> m_number;int numNow = m_allTiled.at( map[row][col1] - 1 ) -> m_number;if( numNow == numObj ){m_allTiled.at( map[row][col1-1] - 1 ) -> doubleNumber();m_allTiled.at( map[row][col1] - 1 ) -> removeFromParent();int index = map[row][col1];m_allTiled.erase( map[row][col1] - 1 );// 糾正塊的編號for( int r = 0 ; r < GAME_ROWS ; ++r ){for( int c = 0 ; c < GAME_COLS ; ++c ){if( map[r][c] > index ){--map[r][c];}}}map[row][col1] = 0;}break;}}}}}}void GameScene::moveRight( ){// 向右移動所有的塊for( int row = 0 ; row < GAME_ROWS ; ++row ){for( int col = GAME_COLS - 1 ; col >= 0 ; --col ){if( map[row][col] > 0 ){for( int col1 = col ; col1 < GAME_COLS - 1 ; ++col1 ){if( map[row][col1+1] == 0 ){map[row][col1+1] = map[row][col1];map[row][col1] = 0;m_allTiled.at( map[row][col1+1] - 1 ) -> moveTo( row , col1+1 );}else{int numObj = m_allTiled.at( map[row][col1+1] - 1 ) -> m_number;int numNow = m_allTiled.at( map[row][col1] - 1 ) -> m_number;if( numNow == numObj ){m_allTiled.at( map[row][col1+1] - 1 ) -> doubleNumber();m_allTiled.at( map[row][col1] - 1 ) -> removeFromParent();int index = map[row][col1];m_allTiled.erase( map[row][col1] - 1 );for( int r = 0 ; r < GAME_ROWS ; ++r ){for( int c = 0 ; c < GAME_COLS ; ++c ){if( map[r][c] > index ){--map[r][c];}}}map[row][col1] = 0;}break;}}}}}}</span>
OK,完成,這次就到這裡,
下次就是要對遊戲相關功能進行完善,
比如:
——判斷失敗
——添加動畫
——添加音效
不知不覺,這個2048就快要結束了~。~ 嘿嘿
下回見~
本篇文章代碼下載:http://pan.baidu.com/s/1o6p1E4M
***************************************轉載請註明出處:http://blog.csdn.net/lttree******************************************
剛下了cocos2d-x-32,在vs2013上編譯時間出現了下面一些問題,怎解決新手入門表示各種頭痛T_T
我也試過裝cocos2d-x,不過當時好像只支援到2012就放棄了,不過你這個因為cocos2d-x也只是提供了幾個庫而已,無法解析是因為你在編譯的時候沒有在VS裡將cocos2d-x的庫給串連進來,所以無法解析這些符號,具體的設定應該是“右鍵項目屬性 → C/C++ → 常規 ”裡面把庫檔案添加進來,百度上一大堆教你如何添加庫的教程
Cocos2d-x 32alpha建立的Lua項目在android平台移植不了的問題
Cocos 3.0建立預設的Lua項目時,其Android項目可謂是非常不完整。產生的項目模版。根本就不包含C++的編譯。
你的異常實際上告訴你的是,你的項目libs目錄下,根本就沒有產生SO檔案。
我也嘗試過去修改這個預設的Android項目模版,不過修改量太大了,折騰了大半天才搞定。
我對你的建議是,不要使用Cocos來建Lua項目。就建普通的C++項目即可。普通的C++項目編譯通過了,就可以在libs目錄下得到SO庫了。
反正對於Android的Lua項目,其需要的並不是C++的代碼,而是一個SO庫檔案,
有了這個SO庫檔案,剩下的事就容易搞定了。